基于RT-Thread的蓝牙遥控平衡小车
本文为kaichen参与RT-Thread应用作品征集赛作品原创。只要你采用RT-Thread操作系统设计开发,不限硬件(每人可提交作品数不限)就有机会获得2000元现金大奖哦!投稿:andychen@rt-thread.com
https://v.qq.com/txp/iframe/player.html?vid=u13459zixuk&width=500&height=375&auto=0基于RT-Thread的蓝牙遥控平衡小车演示视频
【背景描述】
出于业余爱好,以及学习自动化控制PID理论,经过多种选择后决定制作平衡车进行实际操练。刚开始试着用单纯的裸机,完成直立控制,然后慢慢的又增加了屏幕显示,用于参数调整显示,再然后用蓝牙透传进行串口遥控,并且增加用遥控器进行PID参数调增。增加这些功能以后,再进一步逐渐的增加功能,就需要进行在多任务的时间调配上进行更严格分配,每增加一个功能,都需要重新调整在这个上面花费了不少时间。例如,在屏幕的显示上,由于需要较多时间进行数据端口的模拟,耗费大量时间,如果需要增加多个参数显示,相应的屏幕程序就需要更多时间,就会改变整个程序的时间分配,平衡车直立控制就会不稳定,难与调试。由于上面的困扰,并且之前2010年的时候一个偶然机会了解到了RT-Thread实时操作系统,决定试着用操作系统的理念进行编写,可以省去在裸机调试时间分配的困扰。由于裸机我用了STM32F103C8T6芯片只有64KB,我本人懒于修改硬件,尝试修剪RTT,用尽可能少的组件,手动的把3.0.4版本去掉外围,只用内核。在内核上把平衡车的控制分为直立控制、蓝牙控制、屏幕控制、以及原来的LED控制,后续增加超声波,指南模块等。尽可能使用现成的元件搭建起实物原型,然后再不断增加功能,从扩充的过程中完成控制理论的学习和对实时操作系统的掌握。由于有限的代码空间也进一步锻炼代码的精简训练。
【开发环境】
主控:STM32F103C8T6
编译环境:MDK5.23
RT-Thread版本:RT-Thread 3.0.4内核
【硬件设计】
电池:用的是圆柱锂电池。可以直接用充电宝里面的锂电池,外加三串保护板。做成12V锂电。
主控板:最小系统板
电机驱动模块: 利用了里面的5V电源
LCD模块:12684
电机:
电机用的GB37电机,是一款使用霍尔传感器编码器的测速模块,配有13 线强磁码盘,A B 双相输出共同利用下,通过计算可得出车轮转一圈时,脉冲数可达30132=780 个,单相也可以达到390 个,精度足够能让平衡小车无所不能。
其实霍尔编码器还是不够精确的,会在快速转动的时候漏掉编码,为此我调试了很久。
遥控器用组成:ARDUINO2560+joystick+hc05蓝牙组成。
超声波模块:
三轴传感器:MPU6050
硬件系统用搭模块的方式组成,之间的连接可以全部用杜邦线连接。
电路原理图由于手工需要的时候接上去的,没有画,其实完全可以自己动手手动连接一下。
总的功能原理图如下:
原理功能图,用的是老图了。基本都是这个原理。器件上,陀螺仪用的是MPU6050。主控:STM32F103CT8最小系统板。
【软件设计】
工程概览:
线程初始化:
主要线程定义:
小车控制线程
蓝牙遥控协议解析:
超声波线程:
目前代码优化不够,还很多用全局变量传递参数。
器件驱动(参考部分开源代码)->直立控制->速度控制->方向控制->无线蓝牙控制(含遥控对控制参数的调整)
【关键代码解析】
我所做的不同是,角度用的是PI控制、速度用PID、方向用了PI,我在角度、速度、方向上都加进了PID控制。程序代码难理解的部分也是PID部分。后期会在进一步改进中模糊控制相应的PID控制参数。根据不同速度、角度判断是否进行积分。这是最耗费时间的。例如目前小车碰到障碍物时,无法前进,速度的积分控制在这时应当停止,目前还未做改进。
以下是控制直立的关键代码。保证每5毫米执行一次,完成角度采集,角度控制,方向控制,速度控制的周期。
int car_run(void)
{
float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
unsigned char more=0;
long quat[4];//
unsigned long sensor_timestamp=0;
float Pitch; //
short gyro[3], accel[3], sensors;//
int stop=0;
float angle_out,speed_out,direction_out;
float car_zero_angle=-1.78; //
static int run_err=0;
char numf[20];
dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more);
if ((sensors & INV_WXYZ_QUAT))//&&(more<10)
{
q0=quat[0] / q30;
q1=quat[1] / q30;
q2=quat[2] / q30;
q3=quat[3] / q30;
Pitch = asin(2 * q1 * q3 - 2 * q0* q2)* 57.3;
sprintf(numf,"A:%2.3f*",Pitch);
sping_english8x8(0 , 2 ,numf) ;
if (Pitch>20||Pitch<-20) stop = 1;
angle_out = AngleControl(Pitch,gyro[1],car_zero_angle,stop);
velocity_proc(&speed_out,&direction_out,speed_set,direction_set,stop);
MotorOutput(angle_out,speed_out,direction_out,stop);
}
else
{
if ((sensors & INV_WXYZ_QUAT)&&(more==0))run_err++;
}
return run_err;
}
Rt_thread由于资源限制,仅仅用了内核部分,利用了内核的线程调度功能,共创建了三个线程。关键点是在于三个线程的优先级别设置,这也是在设计平衡车对实时要求的一种体现。最关键的是车的平衡,设置为最高优先级,并且MPU6050的硬件要求5MS进行一次读数据。空闲时间之外可以进行蓝牙串口传输的解析工作,把遥控指令传给速度控制进程。
/* init hxlcd thread */
init_thread = rt_thread_create("hxlcd", hxlcd_thread_entry,RT_NULL,256, 15, 20);
if (init_thread != RT_NULL)
rt_thread_startup(init_thread);
/* init car control thread */
init_thread = rt_thread_create("car_run", car_control_thread,RT_NULL, 512, 10, 20);
if (init_thread != RT_NULL)
rt_thread_startup(init_thread);
/* init car Protocol thread */
init_thread = rt_thread_create("car_Pro", car_Protocol_thread, RT_NULL,2024, 11, 20);
if (init_thread != RT_NULL)
rt_thread_startup(init_thread);
【RT-Thread使用情况介绍】
该小车仅仅使用了RT-Thread内核,原本打算使用设备管理,但是编译后发现代码量大了后决定设备管理也不用。
【演示视频】
https://v.qq.com/txp/iframe/player.html?vid=c13456pukvj&width=500&height=375&auto=0小车载物
https://v.qq.com/txp/iframe/player.html?vid=c13450ny0yo&width=500&height=375&auto=0
小车推物
1.回复【野火RT-Thread】,免费下载《RT-Thread内核实现与应用开发实战指南—基于STM32》电子版
2.如果你是在读大学生,登记后即可进入RT-Thread官方大学生群,并享受后续针对学生的一切福利,包括RT-Thread官方新书尝鲜阅读、提前看开发教程、板卡使用等。立马登记请戳:https://wj.qq.com/s/2294003/858b(可点击原文进入登记网页,或复制粘贴至浏览器)
3.2018 RT-Thread物联网开发者沙龙即将在西安开展,本次沙龙除了精彩的主题分享,还特设workshop环节,让大家现场动手玩起来!
长按下面二维码报名7月28日(西安站)
你可以添加微信13924608367为好友,注明:公司+姓名,拉进 RT-Thread 官方微信交流群
RT-Thread
让物联网终端的开发变得简单、快速,芯片的价值得到最大化发挥。GPLv2+协议,可免费在商业产品中使用。
长按二维码,关注我们
👇点击进入大学生交流群登记页面