首先使用STM32 Cube MX
生成带Makefile
的HAL库工程模版,然后修改Core
文件夹下的用户代码,使用make
命令编译,在build
目录即可获得seesaw.elf
等文件,接下来按下BOOT0+RESET
使单片机进入下载模式,使用usb将其连接到电脑,用STM32 Cube Programmer
将编译好的程序烧录进单片机。
小车为三轮,车身由铝合金框架连接构成,在其上固定有面包板,用杜邦线连接单片机、电机、蓝牙模块、电池盒与传感器,同时用扎线带等固定好分线器(位于侧面与底部)与电源模块(位于底部),具体实物图与分模块说明如下。
上面 | 底面 | 核心 |
侧面 |
单片机型号为STM32F401CCUx
,具体实物如上图。定义其引脚与中断如下,详细可见seesaw.ioc
,该文件可用STM32 Cube MX
打开。
电机型号为MG995
,使用单片机TIM1
产生的PWM
波驱动,实物图如下。
传感器为九轴传感器GY953
,通过UART1
与单片机通信,具有加速度、角加速度、欧拉角,磁场的测量功能,并且还可以以固定频率(默认50Hz
)输出数据,具体使用文档可以在网络上找到,不再赘述。项目中只使用了角加速度与欧拉角,并使用其固定频率作为外部时钟中断。
蓝牙模块作为调试使用,通过UART2
与单片机通信,在调试完毕后可以移除。
电源模块位于小车底部,提供恒定的5V
电压源。不过当电机转速突变时,其将产生约9V
的尖峰,可能会导致系统工作失常。本项目的代码通过避免速度突变使系统工作正常,不过也可通过加入电容调节。
本项目通过代码控制小车实现了以下一系列动作:
- 上电,标定正确航向(约 3s),成功后 LED 灭
- 在跷跷板为圆心 90° 扇形范围内,距离跷跷板 A 端 300mm 以外指定位置放置,按动 UKEY 启动,LED 亮,小车自主运动上跷跷板
- 在 60s 内,运动到中心点 C 附近
- 到达跷跷板左倾与右倾的欧拉角 pitch 极值点,通过平均计算出中点处 pitch 值
- 以中点处 pitch 值运行 PID 算法,使跷跷板处于平衡状态,然后保持平衡 10s ,并给出明显的平衡指示(LED 闪烁)
- 60s 内回到 A 端,并给出明显的到达指示(LED 闪烁)
程序完全采用中断驱动,在主函数中初始化电机、传感器等外设后,即在while (1)
中使用__WFI()
等待中断到来,处理相应事件。在上电后 1s ,单片机向传感器发出指令,使传感器向单片机以50Hz
频率主动发送欧拉角数据。
频率为50Hz
,是主要的中断源。程序的主体都在该中断下完成,中断优先级为1
。
当接收到数据进入中断后,程序将进行如下处理流程
- 找到帧的开始
0x5a5a
- 根据类型字段判断数据是欧拉角还是角加速度
- 角加速度
- 如果还未按过 UKEY 按键(步骤 1)或流程已经结束(步骤 6),直接返回
- 如果已经进入 PID 算法(步骤 4 及之后步骤),直接返回
- 否则(未进入 PID 算法)
- 如果 y 方向角加速度数据绝对值大于 256,系统进入不稳定状态(步骤 4),关闭电机,小车停止
- 否则(y 方向角加速度数据绝对值小于 256)
- 如果系统处于不稳定状态,且这种状态已经持续 1s ,系统回到稳定状态(步骤 4)
- 如果系统初次处于稳定状态或到达规定切换时间,将传感器切换到自动发送欧拉角模式(步骤 4)
- 如果系统不是初次处于稳定状态,且到达规定停止时间,将小车停止一段时间以避免可能的传感器漂移(步骤 4)
- 其余情况直接返回
- 欧拉角
- 如果处于返回阶段(步骤 6)
- 如果已经停止,LED 闪烁
- 如果还在后退,检测欧拉角 Yaw 值,如果发现已经水平,小车停止
- 如果还未按过 UKEY 按键(步骤 1)
- 如果上电后已经经过 1s 且传感器有数据(避免无效数据),取 1s 内的欧拉角 Pitch 与 Yaw 平均,以标定正航向
- 其余情况直接返回
- 否则(已经按过 UKEY 按键),如果还未调整好航向(步骤 2)
- 如果检测到小车抬头,说明小车已经部分上板,调整航向到正向
- 否则说明还未上板,继续直行
- 否则(已经按过 UKEY 按键,并调整好航向),如果进入 PID 算法(步骤 5)
- 利用当前 Pitch 值用 PID 算法计算速度
- 如果速度在很小范围波动(动态平衡),计时 10s,同时 LED 灯闪烁,时间到后倒车
- 否则(速度变化剧烈),重置定时器,小车以新的速度运行
- 否则(已经按过 UKEY 按键,并调整好航向,但未进入 PID 算法),如果系统已经达到过一次不稳定状态,且当前不处于不稳定状态(步骤 4)
- 如果到达规定检测时间,计算是否应当进入 PID 算法
- 如果应当进入 PID 算法(中点测量完毕),小车停止,在下一个数据包到来后即切换到 PID
- 否则(还在测量极值点),计算接下来的运动方向(让跷跷板再次倾倒的方向),开始运动,同时将传感器切换到角加速度模式检测不稳定状态
- 如果到达规定检测时间,计算是否应当进入 PID 算法
- 如果处于返回阶段(步骤 6)
通过按下按键启动自主程序,是仅使用一次的重要中断,中断优先级为4
。当按下UKEY
后,单片机向传感器发出指令,使传感器切换为发送角加速度数据,并使小车向前运动。
是HAL_Delay()
函数用到的中断,必须在最高中断优先级0
,否则程序将会在中断处理时死锁。