STM32
直播中

罗星

8年用户 1625经验值
擅长:模拟技术
私信 关注
[问答]

怎样去设计一种基于STM32的遥控小车呢

基于STM32的遥控小车主控板需要完成哪些功能呢?
怎样去设计一种基于STM32的遥控小车呢?

回帖(1)

李阳

2021-12-17 11:29:12
这次边做边写,基本上把做proj的整个步骤记录下来,包括中间的思考过程,也挺有意思的


小车主控板思路


主控板需要完成的功能:
1.接受传输过来的数据
2.根据数据控制电机PWM
3.根据数据控制舵机PWM

控制电机的PWM实现:
1.一个函数,两个参数:move(dir,speed)
2.dir控制前后,speed控制pwm.
3.如果方向改变需要延迟一定时间

控制舵机的pwm实现:
1.一个函数,两个参数:turn(dir,value)
2.dir控制左右,value是设定值控制pwm
3.value需要配合PID算法写好
两个电机控制需要两个tim的pwm,需要四个管脚输出控制正反转.
PID算法实现的时候,舵机有反馈线反馈现在所在的角度.反馈用ADC采样读取

PS: 未测试NRF24L01通信模块前自己留一个串口,使用蓝牙调PID
程序步骤


开启时钟(GPIO,TIM, ADC,USART,AFIO)
写move函数
写PID算法
写turn函数
配置蓝牙串口
调试PID
开启时钟

ABP1和APB2对应的外设见下表














  使用TIM生成PWM波


这里使用TIM生成的PWM是为了让PWM更加稳定可靠
原理解释
通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。
这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。
而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平),相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。
如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为 A/(N+1) 。

TIM3复用引脚
如下图







感觉没有引脚冲突的情况下,可以默认没有重映像,TIM3_CH1~4的管脚对应的就是PA6、PA7、PB0、PB1.
输出模式也好确定,查手册可以看到:输出采用推挽复用输出







Mode值放这方便查看:






void tim3()                          
{   
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  //初始化计数配置   
    TIM_OCInitTypeDef  TIM_OCInitStructure;//初始化TIM3的外设
    TIM_TimeBaseStructure. TIM_Period =999;    //计数上限为1000
    TIM_TimeBaseStructure.TIM_Prescaler =71;    //计时器预分频为72/(71+1)=1MHZ   
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //不分
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);     




    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   //TIM脉冲宽度调制模式1  
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 10;//设置了待装入捕获比较寄存器的脉冲值  
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM输出比较极性高
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能TIM3在CCR1上的预装载寄存器




    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 10;         
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);         
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能TIM3在CCR2上的预装载寄存器
    TIM_Cmd(TIM3,ENABLE);                     
}
注意TIM_OCPolarity的选择和OCMode的PWM两种模式的区别:
OCPolarity为高则高电平有效
若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM1时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出有效
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出无效

若TIM_OCInitTypeDef.TIM_OCMode = TIM_OCMode_PWM2时:
当计时器值小于比较器设定值时则TIMX输出脚此时输出无效
当计时器值大于或等于比较器设定值时则TIMX输出脚此时输出有效

修改比较寄存器值的函数TIM_SetComparex(TIM_TypeDef* TIMx, u16 Comparex)
把TIMx的比较寄存器x的值设成Comparex

u16 TIMCompare1 = 0x7FFF;
TIM_SetCompare1(TIM3, TIMCompare1);
试用驱动后的第一次修订

因为采用的大电机的mos驱动很窒息,有一个刹车功能,所以是采用的双路PWM驱动正反转。因此修改之前的TIM生成的PWM配置,采用多个定时器输出多路PWM波.
新的PWM安排如下:


TIM2的CH3和TIM3的CH1分别对应PA2和PA6给大电机的两路PWM.
TIM4的CH1对应着PB6给舵机的PWM.
新的引脚安排:


MOS驱动使能采用PB9.
大坑出现

尝试着正转和反转,但是遇到了大坑.想通过关闭TIM来关闭PWM输出,结果是关闭了TIM之后PWM输出端口就自动高电平无法拉低!.
原因:复用推挽输出下IO口无法控制高低电平,因此拉低只能使用配置占空比的方法.
所以之前配多路TIM是没太大意义的。。关闭PWM只要把占空比调成零就好了!坑啊!
  假装调了PID

舵机反馈线就是一个电位器的中间接线引出来的,左右接3.3V,中间接出来一根线连上ADC采样,读取现有值然后写一个PID反馈调节即可。舵机给一个正的PWM或者一个负的PWM即可完成正转和反转,PWM值的高低决定了转向的快慢,如果PWM占空比过小,那么舵机可能无法转动。不能超调过多,也不能调节量太小转动太慢,于是需要控制参数慢慢调节。PID调节经验看了半天,最后发现这个舵机根本就不灵敏,用不着调节I和D,调好P就行了,就是完成了一个负反馈。过程有一点点艰辛,因为用L298N的驱动时,之前没发现驱动不灵敏,导致最小占空比的PWM也是一直处于超调状态。换了MOS驱动很快就调好了,PID调节的内容就不写在这里了,只要看懂了算法很快就能自己写一个,毕竟这里甚至只用写一个P对吧…
  NRF24L01通信模块

这一块内容是交给女票做的,第一部分是完成SPI的配置。这个有一大堆教程,如果IO口模式配置正确了,SPI的配置内容没有问题,应该很快就能工作。使用SPI往NRF24L01寄存器里写一个值,然后读出来,如果写进去的和读出来的是一样的,那么SPI就配置完毕了。最后是玄学的通信模块调试。NRF24L01是最便宜的2.4GHz的无线通信模块,由于寄存器太多,女票读了好久文档然后自己写了通信要用的函数,接收发送等等。然后总是GG..调了很久才完成。代码在Git上,现在有一个随时可用的配置了,如果之后要做遥控类的东西通信要调的话就方便很多了。
  数据发送接收调节方向,速度,关机开机

遥控器使用两个摇杆电位器做的,用ADC不停采样然后用NRF24L01给车上的主控板不停歇的发送数据,一个控制方向PWM,一个控制驱动电机PWM.前进和后退需要有一定延迟,因为反应太
快而电机又有电感会出现不可逆转的损害。最后是为了防止因为线断了等导致方向或者电机突然失灵,做了一个按钮控制开机关机,就是紧急制动。这些都很好写,源码里直接可以看到。
  总结



小车主控板的大坑遇到不多,一个是MOS驱动问题,一开始双PWM控制不太会用,要拉低就是把占空比调到0. 第二个是由于端口太多,ADC,TIM的PWM输出,SPI等引脚可能按默认配置有重复,所以得使用IO口的重映射.
比较大的坑在通信模块,这是和女票一起调了很久才完成的,感觉有点玄学。看看基础配置,通信速率,传输地址,模式等等是不是都配对了。最后的无线通信调试是没有很好的DEBUG方法的,一步一步慢慢来。
小车做出来了还是挺好玩的,比较有成就感. 缺点就是线可能不太稳,如果撞车了有一定概率失去控制。。这个可以再改进一下。
这个小车电机极其强大,可以跑的巨快。。





举报

更多回帖

发帖
×
20
完善资料,
赚取积分