赞
踩
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
STM32F103ZET6开发板,两个TB6612电机驱动模块,HC-05蓝牙模块,四个光电编码器电机
代码如下(示例):
在main函数中开启pwm输出通道。
- HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_4);
- HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_3);
- HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_2);
- HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);
通过__HAL_TIM_SET_COMPARE()函数输入占空比
- void Set_Pwma(int motor)
- {
- int pwma_abs;
- if(motor>0) Motor_Left();
- else Motor_Right();
- pwma_abs=myabs(motor);
- __HAL_TIM_SET_COMPARE(&htim8,TIM_CHANNEL_1,pwma_abs);
- }
- int myabs(int num)
- {
- int temp;
- if(num<0) temp=-num;
- else temp=num;
- return temp;
- }
- void Motor_Left(void)
- {
- HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET);
- HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_RESET);
- }
- void Motor_Right(void)
- {
- HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);
- HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_SET);
- }
代码如下(示例):
在main函数中开启定时器6
HAL_TIM_Base_Start_IT(&htim6);
调用定时器中断回调函数,每10ms返回一次。
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if(htim == &htim6)
- {
- time_count++;
-
- Direction=__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim3);//获取转动方向
- if(Direction==1)
- {
- CaptureNumber=65535-__HAL_TIM_GET_COUNTER(&htim3);//获取脉冲
- if(CaptureNumber==65535)
- {
- CaptureNumber=0;
- }
- htim3.Instance->CNT=0;
- NowCaptureNumber+=CaptureNumber;//计算总的脉冲数
- }
- else
- {
- CaptureNumber=__HAL_TIM_GET_COUNTER(&htim3);//获取脉冲
-
- htim3.Instance->CNT=0;
- NowCaptureNumber-=CaptureNumber;//计算总的脉冲数
-
- }
- var = NowCaptureNumber-OldCaptureNumber;//脉冲数的变化量
- OldCaptureNumber=NowCaptureNumber;
- speed1=var*60*100/4/500/30;//电机1转速
- }
- }
将要用到的变量封装为一个结构体
- typedef struct
- {
- float target_val;
- float actual_val;
- float pwm_CCR;
- float Add_CCR;
- float err;
- float err_last;
- float err_sum;
- float err_last_last;
- float Kp,Ki,Kd;
- }tPid;
定义一个结构体类型变量
tPid pidMotor1Speed;
- void PID_init()
- {
- pidMotor1Speed.actual_val=0.0;
- pidMotor1Speed.target_val=0.00;
- pidMotor1Speed.Add_CCR=0.0;
- pidMotor1Speed.pwm_CCR=0.0;
- pidMotor1Speed.err=0.0;
- pidMotor1Speed.err_last=0.0;
- pidMotor1Speed.err_last_last=0.0;
- pidMotor1Speed.err_sum=0.0;
- pidMotor1Speed.Kp=10.0;
- pidMotor1Speed.Ki=5.0f;
- pidMotor1Speed.Kd=0.0;
- }
增量式PID算法
- float PID_realize(tPid * pid,int16_t actual_val)
- {
- pid->actual_val = actual_val;
- pid->err = pid->target_val - pid->actual_val;
- pid->Add_CCR = pid->Kp*(pid->err-pid->err_last)+pid->Ki*(pid->err)+pid->Kd*(pid->err+pid->err_last_last-2*pid->err_last);
- if(pid->Add_CCR<-1||pid->Add_CCR>1)
- {
- pid->pwm_CCR+=pid->Add_CCR;
- }
- Pwm_xianfu(&pidMotor1Speed,999);
- Pwm_xianfu(&pidMotor2Speed,999);
- Pwm_xianfu(&pidMotor3Speed,999);
- Pwm_xianfu(&pidMotor4Speed,999);
- pid->err_last_last=pid->err_last;
- pid->err_last=pid->err;
- return pid->pwm_CCR;
- }
对PID返回的PWM值进行限幅
- void Pwm_xianfu(tPid * pid,int16_t max)
- {
- if(pid->pwm_CCR>max) pid->pwm_CCR=max;
- if(pid->pwm_CCR<-max) pid->pwm_CCR=-max;
- if(pid->target_val==0)
- {
- pid->pwm_CCR=0;
- }
- }
设置PID目标速度并实现PID控制电机转速
- void motorPidSetSpeed(float Motor1SetSpeed,float Motor2SetSpeed,float Motor3SetSpeed,float Motor4SetSpeed)
- {
- pidMotor1Speed.target_val=Motor1SetSpeed;
- pidMotor2Speed.target_val=Motor2SetSpeed;
- pidMotor3Speed.target_val=Motor3SetSpeed;
- pidMotor4Speed.target_val=Motor4SetSpeed;
- Set_Pwma(PID_realize(&pidMotor1Speed,speed1));
- Set_Pwmb(PID_realize(&pidMotor2Speed,speed2));
- Set_Pwmc(PID_realize(&pidMotor3Speed,speed3));
- Set_Pwmd(PID_realize(&pidMotor4Speed,speed4));
- }
最后在编码器测速下方调用PID控制电机函数
motorPidSetSpeed(motor1speed,motor2speed,motor3speed,motor4speed);
下载途径:https://pan.baidu.com/s/1OV5MgmTUjyNafIsshcdh6Q
提取码:8888
将蓝牙模块比单片机的串口引脚连接
使能串口
- __HAL_UART_ENABLE_IT(&huart3,UART_IT_RXNE);
- HAL_UART_Receive_IT(&huart3,(uint8_t *)&aRxBuffer,1);
编写串口回调函数来进行对PID目标速度的控制
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
- {
- if(huart == &huart3)
- {
- if(Usart1_Rx_Cnt > 255)
- {
- Usart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- HAL_UART_Transmit(&huart3, (uint8_t *)"Êý¾ÝÒç³ö", 10,0xFFFF);
- }
- else
- {
- RxBuffer[Usart1_Rx_Cnt++] = aRxBuffer;
- if(aRxBuffer == 'A')
- {
- motor1speed=40;
- motor2speed=-40;
- motor3speed=40;
- motor4speed=-40;
- }
- if(aRxBuffer == 'B')
- {
- motor1speed=-40;
- motor2speed=40;
- motor3speed=-40;
- motor4speed=40;
- }
- if(aRxBuffer == 'C')
- {
- motor1speed=0;
- motor2speed=0;
- motor3speed=0;
- motor4speed=0;
- }
- if(aRxBuffer == 'D')
- {
- motor1speed=-40;
- motor2speed=-40;
- motor3speed=40;
- motor4speed=40;
- }
- if(aRxBuffer == 'E')
- {
- motor1speed=40;
- motor2speed=40;
- motor3speed=-40;
- motor4speed=-40;
- }
- if((RxBuffer[Usart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Usart1_Rx_Cnt-2] == 0x0D))
- {
- HAL_UART_Transmit(&huart3,(uint8_t *)&RxBuffer, Usart1_Rx_Cnt,0xFFFF);
- while(HAL_UART_GetState(&huart3) == HAL_UART_STATE_BUSY_TX);
- Usart1_Rx_Cnt = 0;
- memset(RxBuffer,0x00,sizeof(RxBuffer));
- }
- }
- HAL_UART_Receive_IT(&huart3,(uint8_t *)&aRxBuffer,1);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。