【STM32 + HAL库】倒立摆

一天时间终于做完了这颗倒立摆,能够实现持久站立,但是抗干扰能力很弱。

先上两张未经排版的图(好吧,不能上传GIF)

截止本文写完,该摆最长站立了17分钟。

【硬件部分】

1、倒立摆机械部分由老师提供,由同步轮+同步带带动滑台在光杆上运动;角度反馈部分为安装在倒立摆下端的高精度电位器

2、电机为带编码器的减速直流电机,由TB6612芯片驱动

3、主控板为stm32f103vet6开发板

4、电机使用学生电源提供10V电压驱动,单片机由电脑USB供电。

【使用HAL库构建硬件层代码】

 

1、RCC时钟树配置

在CubeMX中,使用外部晶振提供时钟源,通过锁相环倍频到72MHz提供给外设,ADC模块的时钟不能太高,否则会影响转换精度。详细配置如图

 

2、TIM8编码器模式配置

使用stm32f103高级定时器TIM8的编码器模式,测量电机的转速。

在模式选择窗口,选择通道串联模式,由两个TIM输入通道接入正交编码器的A线和B线。

详细配置窗口中,选择向上计数,不允许自动重装载。编码器模式下,选择在通道1和通道2的上升沿计数。理论上而言,这样会导致计数值是实际值的4倍(但是实际程序中不是)

编码器数值由软件直接读取和重置,不需要重装载,也不需要中断。

注意将GPIO脚设置为上拉输入,部分编码器没有接上拉电阻,需要单片机内部提供。

 

3、ADC1测量电位器阻值

配置ADC1的一通道对电位器阻值进行测量,从而获取倒立摆的倾角。

如图是选择Channel1独立测量、连续测量模式,因为只有一个通道测量,所以扫描测量模式关闭。AD转换同样不需要中断,在软件中直接触发一次转换,之后读取转换值即可。

4、TIM1输出PWM

在模式配置中,选择时钟源为内部时钟源72MHz,选择通道一为PWM输出模式

在配置选项中,我们需要产生频率为1000Hz,占空比可变的PWM。可以选择预分频系数为72-1,预分频之后得到1MHz时钟信号;重装载寄存器为1000-1,得到1000Hz的PWM。选择PWM Mode 1,当计数器值小于某个值时,输出高电平,否则输出低电平(Mode 2)相反。同时配置输出GPIO为推挽输出模式。

【串级PID算法】

部分内容来自个人理解,如果不当,恳请批评指正。

显然这是一个串级PID算法。

第一级PID输入为倒立摆的实际角度和目标角度,输出电机的目标转速。

实际上输入为ADC转化的电位器两端的电压值,目标值为电位器在平衡位置时ADC转换的电压值,输出为目标转速。

第一级PID主要由比例和微分控制,由于下面还有一层PID,所以积分环节要么选择误差过零时将积分项清零,要么选择较小的积分限幅。考虑到倒立摆对平衡性要求较高,误差过零时将积分项清零的方法将使第一级PID的输出在平衡位置发生跳变,所以选择积分限幅,限制幅值较小,但积分参数较大。

第二级PID输入为电机的目标转速和实际转速,输出电机的PWM。

第二级PID主要由PID三项控制构成,原本决定不用I控制,但是在实际调试过程中,由于电机存在一定的死区,在平衡位置附近PWM输出很小,电机不转,严重影响控制品质;可以按固定的PWM值进行死区补偿,但是这样较为死板,考虑到倒立摆的摆动是一个相对慢的过程,所以使用积分项。同样需要积分限幅。

 

【调试过程】

一开始PID调了好久都没有效果,冷静下来才发现方法不对。后来的调试过程如下:

1、先给第一级PID赋较大的P,I和D参数为0

2、利用Arduino的串口绘图器,将目标值与实际值绘图,观察变化趋势,调节第二级参数

3、利用Arduino的串口绘图器,将目标值与实际值绘图,观察变化趋势,调节第一级参数

 

调试过程中的小技巧:

设置当倒立摆

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值