分享

电机的速度pid闭环控制代码及注释

 jingxin95 2019-08-20

我写文章的内容,大部分围绕一个技术人员的技术路线、财务规划等,可能会稍微有点杂。但我感觉这是一些技术人员的普遍现象,都需要技术积累,都需要生存,都想做好的产品。在这里都可以看到相关的文章,我会陆续的整理思路和内容,发出来。

电机的速度pid闭环控制代码及注释

上一篇文章讲了基于stm32单片机的pwm输出,实现的代码。下面用一个例子来说明运动控制中,一个旋转速度闭环是如何通过代码实现,后面都加了注释。大家一起学习交流。

这个在机器人的运动控制中很常用,具体代码及注释如下:

#include "sys.h"

u8 Flag_Stop=1; //停止标志位

int Encoder; //编码器的脉冲计数

int Motor_1; //电机PWM变量

int main(void)

{

Stm32_Clock_Init(9); //系统时钟设置

delay_init(72); //延时初始化

LED_Init(); //初始化与 LED 连接的硬件接口

uart_init(72,115200); //初始化串口1

MiniBalance_PWM_Init(7199,0); //=====初始化PWM 10KHZ 高频可以防止电机低频时的尖叫声

Encoder_Init_TIM2(); //初始化编码器

Timer3_Init(99,7199); //=====10MS进一次中断服务函数,中断服务函数在control.c

while(1)

{

printf("%d\r\n",Encoder);

}

}

#include "motor.h"

void MiniBalance_Motor_Init(void)

{

RCC->APB2ENR|=1<<3; //PORTB时钟使能

GPIOB->CRH&=0X0000FFFF; //PORTB12 13 14 15推挽输出

GPIOB->CRH|=0X22220000; //PORTB12 13 14 15推挽输出

}

void MiniBalance_PWM_Init(u16 arr,u16 psc)

{

MiniBalance_Motor_Init(); //初始化电机控制所需IO

RCC->APB2ENR|=1<<11; //使能TIM1时钟

RCC->APB2ENR|=1<<2; //PORTA时钟使能

GPIOA->CRH&=0XFFFF0FF0; //PORTA8 11复用输出

GPIOA->CRH|=0X0000B00B; //PORTA8 11复用输出

TIM1->ARR=arr; //设定计数器自动重装值

TIM1->PSC=psc; //预分频器不分频

TIM1->CCMR2|=6<<12; //CH4 PWM1模式

TIM1->CCMR1|=6<<4; //CH1 PWM1模式

TIM1->CCMR2|=1<<11; //CH4预装载使能

TIM1->CCMR1|=1<<3; //CH1预装载使能

TIM1->CCER|=1<<12; //CH4输出使能

TIM1->CCER|=1<<0; //CH1输出使能

TIM1->BDTR |= 1<<15; //TIM1必须要这句话才能输出PWM

TIM1->CR1=0x8000; //ARPE使能

TIM1->CR1|=0x01; //使能定时器1

}

#include "encoder.h"

/**************************************************************************

函数功能:把TIM2初始化为编码器接口模式

入口参数:无

返回 值:无

**************************************************************************/

void Encoder_Init_TIM2(void)

{

RCC->APB1ENR|=1<<0; //TIM2时钟使能

RCC->APB2ENR|=1<<2; //使能PORTA时钟

GPIOA->CRL&=0XFFFFFF00;//PA0 PA1

GPIOA->CRL|=0X00000044;//浮空输入

/* 把定时器初始化为编码器模式 */

TIM2->PSC = 0x0;//预分频器

TIM2->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值

TIM2->CCMR1 |= 1<<0; //输入模式,IC1FP1映射到TI1上

TIM2->CCMR1 |= 1<<8; //输入模式,IC2FP2映射到TI2上

TIM2->CCER |= 0<<1; //IC1不反向

TIM2->CCER |= 0<<5; //IC2不反向

TIM2->SMCR |= 3<<0; //SMS='011' 所有的输入均在上升沿和下降沿有效

TIM2->CR1 |= 0x01; //CEN=1,使能定时器

}

/**************************************************************************

函数功能:把TIM4初始化为编码器接口模式

入口参数:无

返回 值:无

**************************************************************************/

void Encoder_Init_TIM4(void)

{

RCC->APB1ENR|=1<<2; //TIM4时钟使能

RCC->APB2ENR|=1<<3; //使能PORTb时钟

GPIOB->CRL&=0X00FFFFFF;//PB6 PB7

GPIOB->CRL|=0X44000000;//浮空输入

/* 把定时器初始化为编码器模式 */

TIM4->PSC = 0x0;//预分频器

TIM4->ARR = ENCODER_TIM_PERIOD-1;//设定计数器自动重装值

TIM4->CCMR1 |= 1<<0; //输入模式,IC1FP1映射到TI1上

TIM4->CCMR1 |= 1<<8; //输入模式,IC2FP2映射到TI2上

TIM4->CCER |= 0<<1; //IC1不反向

TIM4->CCER |= 0<<5; //IC2不反向

TIM4->SMCR |= 3<<0; //SMS='011' 所有的输入均在上升沿和下降沿有效

TIM4->CR1 |= 0x01; //CEN=1,使能定时器

}

/**************************************************************************

函数功能:单位时间读取编码器计数

入口参数:定时器

返回 值:速度值

**************************************************************************/

int Read_Encoder(u8 TIMX)

{

int Encoder_TIM;

switch(TIMX)

{

case 2: Encoder_TIM= (short)TIM2 -> CNT; TIM2 -> CNT=0;break;

case 3: Encoder_TIM= (short)TIM3 -> CNT; TIM3 -> CNT=0;break;

case 4: Encoder_TIM= (short)TIM4 -> CNT; TIM4 -> CNT=0;break;

default: Encoder_TIM=0;

}

return Encoder_TIM;

}

感谢阅读:)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多