STM32自平衡小车
时间:2022-11-12 15:00:00
前言
平衡汽车制作前后已经半个多月了。在这段时间里真的很难。我想放弃几次,但幸运的是,我终于完成了演示视频链接和代码链接。我希望你能支持它
文章目录
- 前言
- 一、踩坑之路
-
- 1.固件库转hal库的无从下手
- 2.mpu6050
- 3.电机驱动选择
- 4.电源管理
- 5.PCB设计
- 二、模块选择
- 三、各调试部分的主要代码
- 四、PID调参
-
- 1.直立环
-
- 比例系数KP的确定
- 微分系数KD的确定
- 2.速度环
-
- 比例系数KP的确定
- 积分系数KI的确定
- 3.转向环
-
- 比例系数KP的确定
- 微分系数KD的确定
- 五、引脚连接
-
- 1.初版PCB
- 总结
一、踩坑之路
1.固件库转hal库的无从下手
刚接触hal库看起来很简单,但实际上有很多问题。因为配置问题,我曾经把它放在一边stm32f103c8t6芯片被锁定,我认为芯片坏了。最后,我找到了一些博客文章来解决它
2.mpu6050
第一次用这个模块,很奇怪,在网上发现了很多文章,才开始敲代码。mpu6050不能初始化,程序卡死。后来,程序只能在主循环中使用,不能使用INT引脚外部中断精确定时,至今未解决。最后,使用定时器是10ms精准定时
3.电机驱动选择
开始使用TB6612电机驱动,但不知道电路有什么问题,导致芯片烧毁,现在有阴影,然后选择a4950,PCB板也是根据这个设计设计的,但是因为使用a每个轮子4950模块PWM死区不同,不易调整PID,最后确定L298N为电机驱动模块
4.电源管理
设计PCB时使用的a4950考虑到5V12-5v再考虑降压模块stm32供电为3.3v电压,无奈PCB又加了一个5-3.3V降压模块
5.PCB设计
没有考虑到OLED的位置,a4950的引脚方向相反,mpu6050的位置不固定,容易松动,影响角度。更好的是,我引出了未使用的引脚,这给我后来改变计划带来了极大的便利。
二、模块选择
1.带编码器的减速电机及周围相关部件
2.主控芯片STMF103C8T6
3.IIC接口OLED
4.MPU6050–姿态传感器
5.HC05蓝牙模块
6.12转5V,5转3.3V降压模块
7.ADC电源模块
8.12V电源
三、各调试部分的主要代码
1.MPU6050
初始化
MX_GPIO_Init(); MX_USART2_UART_Init(); MX_TIM3_Init(); printf("init=%d\r\n",mpu_dmp_init()); while(mpu_dmp_init()); //dmp初始化 printf("OK!\r\n"); HAL_TIM_Base_Start_IT(&htim3);//每10ms触发中断
定时器中断测试
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if(htim->Instance==TIM3)//进入中断 {
mpu_dmp_get_data(≈OutMpu.pitch, &OutMpu.roll, &OutMpu.yaw);
MPU_Get_Accelerometer(&OutMpu.aacx,&OutMpu.aacy, &OutMpu.aacz); //加速度传感器数据
MPU_Get_Gyroscope(&OutMpu.gyrox, &OutMpu.gyroy, &OutMpu.gyroz); //得到陀螺仪数据
OutMpu.temp=MPU_Get_Temperature(); //得到温度信息
}
}
2.编码器电机
初始化
void TIM_Init(void)
{
//定时器1 PWW
//2 编码器
//3 中段
//4 编码器B
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);//PWM 10kZ 7199
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_1);//编码器
HAL_TIM_Encoder_Start(&htim2,TIM_CHANNEL_2);
HAL_TIM_Base_Start_IT(&htim3);//每10ms触发一次中断
HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_1);
HAL_TIM_Encoder_Start(&htim4,TIM_CHANNEL_2);
}//死区4230;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance ==TIM3)
{
Rcnt = Read_Speed(2);//右轮
Lcnt = -Read_Speed(4);
if(dir == 1)
PWM++;
else
PWM--;
Set_Pwm(PWM,PWM);//zuo you
}
}
3.蓝牙通信
中断接收
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART2)
{
abc=HAL_UART_Receive_IT(&huart2,UART_Receive_buffer, 1);
if(UART_Receive_buffer[0]=='A')
{
printf("\r\nYou send data : %d\n",UART_Receive_buffer[0]);
}
else
printf("\r\ntest");
HAL_UART_Transmit(&huart2,UART_Receive_buffer,1,0xffff);
}
}
四、PID调参
1.直立环
比例系数KP的确定
- 使微分系数KD参数置零
- 随便选则一个数,判断电机旋转极性,确定小车向前倾,车轮向前转
- 计算电机PWM驱动死区,例如我的小车死区是4000,PWM最大值为7200,假设俯仰角为10度,则(7200-4000)/10=320,那么我的KP范围为0-320
- 取中间值KP,调整参数,直到小车可以平衡一段时间,此时Kp就确定了
微分系数KD的确定
- 同样的方法,使比例系数KP参数置零
- 判断极性
- 计算KD范围
- 调参,使小车可以平衡一段时间
最后KP,KD同时控制PWM,参数*0.6,就是最后的KP,KD
2.速度环
比例系数KP的确定
- 极性的确定,关闭直立环的影响,随意设定一个KP值,KI等于KP/200,转动一个轮子,另一个轮子 也向同一方向转动,极性正确
- 计算KP范围KP=(7200-4000)/(160*40%)=50,及KP范围(0-50)
- 取中间值,打开直立环的作用,根据小车状态改变参数
积分系数KI的确定
1.KI等于KP/200
3.转向环
比例系数KP的确定
1.根据死区计算的PWM上升空间最大值为3200,那么两个轮子及各为1600的转向PWM空间
2.根据目标角度,偏转角度,Turn=-Turn_TargetPID.Turn_KP-gyroPID.Turn_KD;即可算的范围
微分系数KD的确定
1.Kd = Kp/100;
五、引脚连接
1.初版PCB
电机驱动模块最终修改为了L298N。
总结
平衡小车的制作,前期是真的很难熬的,一旦你坚持完成了,你会发现原来好像也没什么,非常感谢CSDN开源博主的资源,实验室学长的支持,B站资源,代码整理后会开源放在这里,希望对大家有所帮助,也希望大家可以帮助更多的人。
百度网盘代码
链接:https://pan.baidu.com/s/11l6evi1tm7rRGBleDvpYqw
提取码:nwei
csdn资源内容和网盘一模一样的