大家好,我是起航,我又来了,这次跟大家聊聊平衡小车。了解我的朋友都知道,我极有可能会把帖子写的又臭又长,所以,,,做好准备,上车吧!
先说项目初衷:想给我外甥做个玩具。
是的,就这么简单。但是做的时候发现,呵呵~~~
外甥是2010年11月份生的,现在上小学了。萌生这个想法的时候是2016年,那时做为一名电子工程师经常在我姐面前吹牛,说我有多厉害。
我姐说,你给我做个空调吧,家里缺个空调! 我............
然后我觉得,在小朋友面前显摆一下自己有多厉害还是可以的。所以,想了想做什么合适。其实,可选项也没几个。我总不能给外甥做个流水灯、MP3、电子秤吧。
四轴飞行器目前不行,因为有螺旋桨,非常容易伤到小朋友。所以,小车是首选。当然,四个轱辘的就算了,没什么意思。要做就做两轮,这样才有成就感。
确定做什么了,然后就是收集相关资料。我把网上能搜到的大部分自平衡小车资料都下载,过了一遍,这是基本功课,必须要做好。
看完才知道,两轮自平衡车,最开始是给双腿行动不变的人设计的。但是,发明出来以后,发现它在保安、巡逻等方面作用更加明显,于是就慢慢普及开了。
国内早期的自平衡小车的方案我找到的是阿莫电子论坛的一篇帖子,2010年的,很牛逼。方案如下:
控制器:ATmega16;8MHz;
加速度传感器:MMA2260;陀螺仪:EWTS82;
传感器的融合:卡尔曼滤波;
马达:EN_2342CR(速比64)+双路12脉冲编码器+CD40106对信号整形;
驱动板芯片:CD4001+IR2111+IRF1404(驱动电流可以很大);
还有图片:
注意看他的控制器和传感器,和现在的完全不一样。
那个时候AVR单片机还是很火的。他用了ATmega16,注意频率,只有8MHZ。然后是传感器:一个加速度传感器,一个陀螺仪!那个时候MPU6050貌似还没露面(我也不知道是还没被设计出来,还是没推广开,知道的可以科普下),为了获取加速度和角度,用了两个传感器。所以现在的我们还是很幸福的。
那个帖子虽然老,但是讨论了很多非常有价值的问题,有兴趣的同学可以百度:
自己做的双轮自平衡小车
链接就不放了,度娘不稳定。
时间当时是2016年,网上大部分的方案是STM32+MPU6050,也有一些用arduino做的。Arduino的问题我稍后再说,当时想的是:随大流!既然32的案例多,那么资料就多,出于稳妥,先买个样机玩玩吧。
当时没认真对比,随便买了个。买回来才发现,资料少的可怜。店铺名称我就不说了,这里奉劝大家,无论买什么,多咨询,多对比。否则学不好,不要怪别人。样子如图:
外形还是很霸气的,大小跟我的一只鞋差不多大,电机扭矩也很给力。但是依然弥补不了卖家配套资料不足的短板。
资料少是一方面,让我惊掉下巴的是,程序居然是用STM32的2.0的库写的。没经历过STM32库函数版本变动的同学是不会理解的,32的库从刚出来到现在相对稳定的3.5版本,变更了几次,每次都是大变样。早期的工程师叫苦不迭,甚至还有的扬言说要自己写一套库函数。
但当时是2016年,16年啊!!!3.5版本已经稳定好几年了!但是卖家提供的程序竟然是2.0版本的库函数,当然,功能是没有问题的。所以我早期的工作就是把整套程序用3.5的库重写一遍,既熟悉了程序流程,也方便了后续的调试。
资料少我忍了,又让我发现一个问题,卖家的原理图和实际硬件不配套。我耐着性子跟卖家反映了这个问题,给出的答复是:技术保密,不影响应用。
我再忍。
然后又发现一个问题,这个电路没有留JTAG或者SW接口,只有一个串口下载的接口。注意,连排针上都没有调试接口,可想而知,这个板子设计的有多失败。
到这里,我竟然已经习惯了。也无所谓了,于是就开始改程序改着玩。
前面我在把库函数版本从2.0变到3.5的时候,已经过了一遍流程。所以每段程序的功能我几乎都了解了,这套板子是STM32+MPU6050,然后使用6050内部DMP固件的方式来获取角度。这种方式获取的值的精度是很高的,而且不需要再经过滤波。但是同样的,对单片机的ROM和RAM的要求也很高。换句话说,低配的单片机玩不来!
先改哪?
就从呼声最高的PID参数开始吧。关于PID参数整定的文章,网上一搜一大堆。同样,抱怨参数不好调的文章也是一大堆。那我就改参数改着玩吧。
结果发现,无论怎么改(只要变动不是特别夸张),,,,,貌似小车都很稳定,这........和我预想的不太一样啊......
这个问题曾经困扰了我很长一段时间,直到搜了一堆相关资料又看了稚晖的文章,才解决了我的疑惑。稚晖是谁?后面再说,同样,会提到他的蛋黄,一个萌翻了的自平衡小车。
简单来说,平衡车好不好调,有几个因素影响:
- 处理器性能,DMP固件的方式肯定是很好的,32没问题,但是一些低端单片机就玩不来了。这时,就需要读取原始数据,然后做一阶滤波或者卡尔曼滤波,这种方式来实现。
- 电机性能,非常重要!!!力矩越大越好。参数整定,说是P+I+D三个,但如果电机性能好,只要P+D就够了,不需要I。现在市面上的大部分平衡车套件几乎也不需要I,毕竟加了一个参数,难度会上去很多。
- 编码器精度。电机性能好,只能保证角度平衡,但是会朝某个方向一直跑,越跑越快,最后速度跟不上,倒下。编码器可以检测电机转了多少,不是转多少圈,是一圈的几分之几。精度高的编码器可以检测电机转了几百分之一 圈,精度低的编码器只能测 十几分之一 圈,甚至几分之一。
上面三点,是从硬件的角度来说的。当然,还有一些别的因素,比如说结构上,重心越低越好,体积越大越好调等。欢迎大家补充。
也就是说,电机性能不错,单片机性能也高,所以PID参数调节难度不大。这就尴尬了,我都做好百米冲刺的准备了,结果告诉我已经到终点了....
既然这样,那就换个玩法。现在的角度获取不是DMP方式吗? 我不用了,换成直接读取原始数据,然后一阶滤波。
先说可行性,这个思路的可行性是没有问题的。网上普遍的反应是这个方式简单,虽然数据不是特别准,但是做小车没问题。我曾经在极客工坊论坛潜水很长一段时间,看了很多案例,这种原始数据+一阶滤波算是比较常见的。
但是有一点,极客工坊里大部分都是arduino,而arduino的晶体一般都是16MHZ,为了确保我和他们尽量处于同一起跑线,我把STM32的频率也降到了16MHZ。然后,噩梦开始了......
代码如下:
void Yijielvbo(float angle_m, float gyro_m)
{
float dt = 0.0f;
dt = (float)TIM_GetCounter(TIM1);
dt = dt / 1000000;
TIM_SetCounter(TIM1, 0);
angel = K1 * angle_m+ (1-K1) * (angel + gyro_m * dt);
}
dt是每次获取角度的时间间隔。使用这种方式,给我最大的感觉就是严重的滞后性。参数K1和滞后性相关,我也进行了调试,有效果,但是达不到要求。
小车放在地上,能明显感觉到已经向一个方向偏了一段时间了,才反映过来。如果不使用一阶滤波也不用卡尔曼,可以感觉到小车的反映速度明显快很多(当然了,还是站不起来~~~)
所以,我当时主要疑惑的问题:一阶滤波的滞后性怎么处理,是否和电机性能有关?
现在回想起来,有两个可能因素:1、STM32频率从72降到16MHZ的时候,IIC的速度可能忘了调节了;2、一阶滤波的代码可能没调好。
一阶滤波的方式当时试了好几天,最后忍不了了。换卡尔曼滤波吧!
这里要说一下,卖家发货时提供的程序只有一份读取DMP方式的,没有一阶滤波、也没有卡尔曼。跟卖家软磨硬泡了一下午,给我找来了一份卡尔曼的,电机驱动方向有点问题,PID参数也需要调整。
于是我拿过来,整了一下,在16MHZ的情况下,竟然就占了起来。
卡尔曼,你是个好人!
到这里,角度获取的几种方式,我都已经过了一遍了。优缺点,心里也有数了。接下来,做点什么?(原谅我自己玩的比较嗨,快忘了给外甥做玩具的事了)
我想把程序简化一下,看看能简化到什么程度,于是开始了给这套程序瘦身。不瘦不知道,一瘦发现卖家的程序里很多没用的东西(我竟然已经习惯了这种卖家,没有情绪拨动了),于是我都逐步测试,确认没用,然后删了。
简化之前,下载到单片机里面要占用30多K,简化以后,我印象里只有15K左右了。如果使用寄存器方式编程的话,代码量还要小一些。
到这里,我已经清楚要给外甥做一个什么样的玩具了。这个玩具不只是给他的,也是给我自己的。
硬件电路框架还是网上普遍在用的,但是核心我已经不想用STM32了,因为没有意思。我想用STM8,因为做这个东西,8位单片机足够了。
这也是我做这个东西,强烈想表达的一个想法。有一段时间,我在QQ群里和网友交流技术问题的时候,经常会有一些新人提问:学8位单片机好,还是学STM32好?
为什么他们会问这样的问题?
因为32位单片机的各方面性能几乎都是碾压8位单片机的,很多用人单位确实也在技能要求里面提到了会用到32。但是,这并不意味着8位单片机就不行了,说个最俗的因素,8位单片机便宜!
骚尼哥在回答这类问题时,说了一段话,我印象很深:会用STM32不代表牛逼,会用8位单片机不代表不牛逼,能把STM32的项目用8位单片机做出来,这才算牛逼!
是的,32位单片机确实性能强,但如果用不到合适的地方,就是资源的浪费,这不是一个优秀的工程师该做的事。
很多新人做项目,很少考虑需要用到的处理器性能,动不动就是32位单片机。这对一件商品来说,确实是一件好事,因为被大众认可了。但是对一个工程师来说,我不这么认为。我印象很深的一件事,一个学生想做个平衡小车,但是角度环调不好,问我怎么回事。我让他跟我说下他的硬件方案:他说他用的STM32F4系列的某个芯片(型号我记不清了),电机是网上随便找的。
我当时的心里是一阵阵的无力感,F4系列都用上了,呵呵,但是电机这个最重要的因素却没认真考虑。
为什么不用arduino?网上的案例也很多,学起来还简单。
呵呵...
先说arduino的来源吧。他是意大利的一名教师和一名晶体工程师发明的一个灵活性非常高的电子平台,主要是因为当时的学生跟他抱怨找不到便宜好用的微控制器。
Arduino有多好用?
由于我的工作的原因,我和北京一些中小学有接触。我能感觉到的是,北京这边,基于arduino的单片机课程,或者机器人课程是非常多的,面向的都是中小学生。所以,中小学生都能学会的编程,有多难?
所以说,它的火爆程度还是很高的。那,能不能用它来做产品?
这就是个很严肃的问题了。做产品的话,首先要考虑的是什么(抛去成本)?
稳定性,稳定性,稳定性!!!
如果稳定性不行,入门再简单,功能再强大,都是扯淡!明白?
那么,它的稳定性到底行不行?这其实是一个备受争议的问题。因为最初它是由于教学的目的被设计出来的,当前国内用的最多的也只是DIY爱好者和一些中小学的兴趣课里。
罗列一下它在国内的主要用途:DIY工具,中小学生兴趣课,还有一些玩具。这样的背景,导致国内几乎很少有团队敢在设计产品的时候拍着胸脯说用它没问题。
那么,它真的不行?
注意我的措辞,我刚才在罗列用途的时候,修饰词是“国内”。在国外,其实是有很多公司用arduino来设计产品的,当然也有一些成功的商业产品。
为什么国内没有?或者很少?
没人愿意让自己去试错。在国内没有出现大量的成功案例之前,这个现象估计很难改变。举个例子,我之前曾经在一家汽车电子公司里工作过。汽车是一个电磁环境非常复杂的东西,选用芯片的时候,公司老板问的最多的一句话就是:同行有没有用过这个芯片?
有的话,才敢放心用。否则,既说服不了自己,也说服不了客户。因为一旦出现问题,要么切换供应商,要么就召回.....
用汽车电子的例子,可能有些极端,但我想表达的意思是:在没有足够案例证明的情况下,它很难被接受。
关于arduino的问题,大家可以看一篇文章:关于使用Arduino做开发的二三理解
百度吧。这篇文章算是说的比较中肯的。简单来说,在未来,它可能在国内的公司里推广开来,目前的话,快速开发一些小批量功能不太复杂的产品可以考虑,否则的话,轻易还是不敢用。
这里再说个事,之前曾经有个大学生跟我聊天,说他们实验室的人基本都是用arduino,51,32都不怎么学。
我当时心里咯噔一下,第一反应就是:这群学生被耽误了....
然后他说,他觉得arduino和传统单片机差别很大,还是要学一下其它的,否则不好找工作。后面这句话让我还算欣慰。
然后说说蛋黄!这里说的不是鸡蛋黄,而是某位牛逼的人物自己做的一个超迷你平衡小车,名字叫蛋黄。制作过程非常暴力,以arduino为控制核心,用到了银行卡,502胶水,洞洞板,热熔胶,从别处拆来的电机、旧手机的电池,乐高积木,各种电子模块。总之,动手能力强的一批。时间跨度好几年,他做了三个版本,第一个长这样:
灵感来自于机器人瓦力。功能上和大部分平衡车一样,两轮直立,蓝牙遥控等。
第二阶段,据说因为他们学校有了3D打印机,所以想换个外壳,于是折腾了一下。第二个长这样。
相比第一个版本,功能多了很多。例如:蜂鸣器报警、抬头舵机互动、超声波测距、摄像头感应、OLED屏幕显示。我当时很难想像,他怎么把这么多功能都搞进去的。看来真的是老师布置得作业太少了!!!
第三阶段,把废旧的安卓手机和平衡车结合起来,做成了这个高端大气上档次的机器人管家。因为是基于安卓平台,所以他融入了视觉、语音、3D、物联网等因素。
到了第三阶段,我其实已经不太在乎它有什么功能了。因为,无论他弄出什么功能来,貌似都很正常。
那么,我要做的是个什么样的平衡小车呢?
面对这么优秀的爱好者作出的作品,我想了很长时间,我在想我到底应该做一个什么样的。跟他一样那没有意义,而且还不见得做得比他好。
我想了想,觉得有几以下几点是我应该要做到的,
1、要有学习的意义,就是说这个板子不光能跑平衡小车,还要作为一个学习的开发板,这是最基本的。
2、选型方面要合理,就像我最开始说的,学会32位的单片机并不见得比学会8位的单片机厉害,能用8位的单片机把32位的单片机的项目做出来,这才叫厉害,所以在做这个东西的过程中,尽量选择合适的资源。每一个元器件的选型都要有原因,有做产品的意识,同时要实现它的效果。
3、制作过程要尽量低成本。身为DIY爱好者,很多人会有这样的感觉,一样东西做的过程是非常兴奋的,演示的时候也非常兴奋,但是演示完了三天之后这个东西就开始吃灰了。所以为了防止这的情况出现,或者即便出现之后这个东西吃灰的情况,但因为它的价格也不是很高,不会心疼。所以我们尽量使用低成本的东西来实现。
4、组装过程要尽量简单。尽量避免太过复杂的组装过程,例如像蛋黄那样,很秀,但也会把大部分人难住,这样的方案需要极高的动手能力,对很多人来说这也是一个非常大的门槛,所以这一点也要尽量避免。
从这里开始,如果是刚入门的单片机爱好者或者想做东西练手的人,注意了。因为接下来的内容,我会用很长的篇幅讲述平衡小车的原理,以及制作过程中遇到的问题。这种剖析式的讲解能把制作过程中遇到的80%以上的问题解决掉,剩下20%是基础。
所以,没基础的或者已经做过的就当故事看了。
想清楚这几点之后我就开始动手准备了,首先是单片机,我选用的是stm8s103f3P6,这是一个20管脚的单片机,flash空间只有8k rom,1k的ram。在选之前,其实我自己也不知道这个东西能不能实现我的要求。但随着设计的过程进慢慢的进行,我发现它远远够超出我的预期,功能是非常强大的。
记得之前我在贴吧看到一篇帖子,就是在描述这个单片机,当时他把stm8s和传统的51做了一个对比,把它称为8位单片机的性价比之王,这个说法虽然有些夸张,但是在一定程度上也体现了这个单片机的功能强大。
我为什么会想到选这个芯片,其实是因为之前在淘宝上闲逛的时候,看一些最小系统板。当时看到他的照片的时候有一丝惊讶的感觉,因为它的体积非常之小,注意是最小系统板,它和一个一元的硬币放在一起也依然显得非常小巧,所以当时忍不住就买了几个回来做测试,结果发现非常好,然后价格也不贵,当时的价格我记得是3块钱左右。放个图:
我当年买的时候是三块多,现在涨了点。
角度传感器这个就不用说了,MP6050因为用的比较多,网上资料也比较多,价格也合适,所以就选它。
然后是电机驱动的部分,这里有两个选择,一个是L9110s,另外一个是tb6612,另外一个还有传统的l298n,但是那个东西体积非常太大,太丑了,我不喜欢,所以把它抛弃掉了。
那L9110S和TB6612怎么选?
这两个模块其实我都有买回来测试。先说L9110S,当时的价格比TB6612低一点,测试过程中发现有两个问题:一个是发热比较严重(据说后来新的芯片解决了发热的问题),当时我甚至加了散热片,只跑了几分钟就热的不行;另一个是能量转换效率貌似不高,打个比方,同样用50%的占空比驱动电机,只用肉眼观察,TB6612比L9110S明显要快一点。
注:我说的这些数据都是2016年~2017年做测试得出的结果,现在可能有了变化,所以仅供参考。
还有一件事比较诡异,2019年下半年,TB6612在淘宝上几乎断货。部分有货的,价格从四五块钱直接张到了20左右。咋回事?
然后是电池,电池最开始选的时候我也没有什么经验,所以就各种电池都买了一些,4.2伏的,8.4伏的都有。
然后是电机,电机的话,我主要看中了一款n20的电机,据说性能比较好。所以我在淘宝买了一些。看了一下各方面参数都还可以,但是带码盘和不带码盘的电机价格差别有点大,但是前期研发先不管,买回来再说。
最后是轮胎,刚好和n20电机配套的,有一款D字型的橡胶轮胎,外形也是非常的可爱,然后就买了一些回来。
然后就开始搞事情了。
首先是搭建这个小车的结构,我一开始并没有直接使用PCB来做车身,也没有用亚克力板子来做车身,我使用的是洞洞板,按照一定的尺寸评估整个车身的大小,然后用剪刀裁定的尺寸,然后使用铜柱进行多层的结构组装。
组装的过程也是非常的暴力,剪子钳子,热熔胶,螺丝刀,各种工具都要上,还有杜邦线,电烙铁等等。
组装的过程很惨烈,出来的外形自然也就没那么好看了,这里应该还有当年组装的外形,放个图给大家看一下,这就是当时最早的一个版本。比较脏也比较难看,现在已经放在一边吃灰了。
可以看到左边是MPU6050,右边是STM8S的最小系统板。上下两层洞洞板,采用铜柱做固定。
怎么确定这个新组装出来的结构可以用,这是一个最基本的问题。但是好在我有之前买的那个平衡车,于是我把它的控制板拆下来,然后使用我新买的电机、轮胎、电池、角度传感器、电机驱动模块组成的车身,这样组装在一起做了一个测试。
这个时候第1个问题出现了,就是使用32的平台来控制这个结构时。如果使用的是DMP方式读取MPU6050的角度,控制小车,是可以站立的;但如果使用原始数据转化为角度再去控制的话,几乎是站不住的。
发现这个问题是非常吓人的,因为如果必须使用DMP方式的话,那就跟我的初衷相违背了。所以这个问题必须要想办法解决。
于是我又开始了长时间的上网查资料,这次查资料的时候,主要的重点放在小车的结构上面。
什么样的结构小车最容易平衡站立,而且站立的最稳,是不是要重心低一点?还是要质量分布均匀一点?还是结构要大一点?
甚至我回想起了小时候玩的一个游戏,就是用一根手指,把一根木棍立在一根手指上,看如何能保持这根棍子的直立。到底是质量大的棍子容易直率还是质量小棍子容易直率。
随着结构和程序的不断优化,我慢慢发现了这个问题的核心点,根据我的回忆,当时最核心的地方在于,由于我是用的是原始数据计算角度的方式,这种方式和DMP方式计算出的角度有一定的偏差。而这个偏差会导致当小车发生偏移的时候,我的电机没有办法快速的给出响应,也就是说反应速度不够。
有些人看到这个问题,第一反应就是8位的处理器速度不够,但其实你忘了我在上面贴出的第1个例子,他使用的单片机就是8M的时钟,而这里我使用的stm8s,我已经把它的时钟设置为16M,所以这个时钟的因素是可以忽略的。
然后引起我注意的是一条不太起眼的消息,就是网上有人在讨论小车结构的时候会说到车身越大、平衡越好掌握;越小、越不容易掌握。因为大的车身它发生偏移的时候,需要的时间长一些,而小的车身发生倾斜的时候,时间貌似更短,所以这就需要更快的反应速度。
这个时候就需要一个控制算法的出现了,前面也提到过,就是PID。因为当前市面上大部分平衡小车的套件,他们使用的电机性能比较强,同时车身也比较大,所以电机的响应能力和速度是完全可以应付车身的,处理小车倾斜时面对的状况。
但是我现在选了一个车身比较小的结构,同时电机扭距不是特别强的电机。那么这个电机的性能就需要一些特殊方式来提高,而提高响应速度最直接的方式就是使用PID这个算法里面的参数I,也就是积分。积分的特性就是它会累积误差,时间越久累积的误差越大,它纠正的力度也就越大,当然这个时间久并不是咱们人体感应的时间,而是单片机的时间。对他来说几个循环过去,如果发现误差还在继续增加,那么它会产生非常强大的修正的力,这个力会作用在电机上,最终使小车的车身恢复平衡。
终于把这个因素考虑进来之后,小车颤颤巍巍的站了起来,第1个问题顺利解决。
发现他摇摇晃晃的站了起来,这个时候我可以确定这个结构是可行的。
这个时候工作要分两个方向同时进行,一个是电路板的绘制。当时第1批板子,我使用的是autumn designer这个绘图工具。当时我印象里应该是画了两三个版本,然后发给嘉立创去打样。现在还能找到当时的板子,随手放一个图。
可以看到,那个黑色的是散热片,下面紧挨着L9110S模块。中间的两个排母用来接STM8S的最小系统板,MPU6050挨着L9110S在另一个角落。
另外就是程序的编写,stm8s的单片机从我买那个最小系统板回来之后还是第1次用,但是编程方式和其他单片机都是大同小异的。只要注意一下细节,网上搜几个例程,搜几个参考的工程,基本上都是可以玩上手的。况且,卖家当时还提供了很多基础的资料,上手完全没有问题。
而且当时我心里想的是32我都玩了,8我还玩不了呢,这是一个很简单的逻辑问题。
准备程序的移植和编写,当时在32这个平台上,我已经可以正常使用了,但是移植到stm8这个平台上,还需要一些工作。基础框架是没有问题的,使用普通IO模拟IIC总线读取MPU6050的数据,但是因为stm8s103f3P6这个芯片的flash非常小,所以没有办法使用DMP的方式读取比较高精度的数据。因此,所以这里使用的是读取原始数据,然后解析的方式。
也就是直接读取加速度和角速度,然后使用重力垂直向量的方式进行解析,这样来获取角度。这个思路也很简单,如下:
初始状态是,加速度计读数是A_X =0; A_Y=0; A_Z=1g;如下图:
然后旋转一定角度后是这样:
旋转后仍要保证竖直方向是1g的加速度,所以有将X轴和Z轴的加速度值矢量叠加后为1g即可用反正切求出P的大小来了
如图:
即可得
Angle = atan2(Acc_x,Acc_z);(注意:这里得出来的角度是弧度)
(上面内容转自CSDN博客:基于MPU6050的加速度求角度)
当时出现的第2个问题是,小车虽然站了起来,但是抖动和晃动是比较明显的,不是一个非常平稳的过程。怎么办?
刚好那段时间认识了做四轴的小马哥,他对MPU6050了解应该比我强,所以当时在网上简单咨询了一下。但因为小马哥看不到实物,不好分析。
这个时候我从两个方向去考虑问题,首先是结构上,有一部分原因我会怀疑这个小车的车身重量太轻,导致电机在对小车进行纠正的时候力度过猛,使小车产生震荡。
针对这个考虑,我在小车底部用胶粘了很多铜柱,增加车身重量,发现没有效果,然后又把这些铜柱放在车身顶部,然后又把它们摆成了各种形状,要么是长的要么是直立的,总之增加小车的质质量,进而增大它的惯性,但是这种方式依然没有效果。
第2个方向是对程序进行优化。例如调节PID参数、调整程序循环周期、在PID算法的基础上做微调等等,效果都不明显。
这里说一下,当时使用的滤波算法是卡尔曼滤波,是从那个不靠谱的STM32小车卖家那里移植过来的。
后面我在想,是不是算法移植有问题。查了一下资料,果然!已经有网友写成了可直接使用的库文件,同时,在使用卡尔曼滤波的时候,需要对相关参数做调整,最主要的应该是周期!
调整完成之后,小车从哆哆嗦嗦的状态,一下子变成了平稳的滑翔者!当时夜里11点多,我媳妇睡的呼呼的,我激动的把她叫醒,演示了一下我的样品。然后她给了六个字的评价:
别烦我,睡觉呢!
嗯,谢谢鼓励!
到这一步,角度环已经没有问题了。当时我还在QQ空间发了个视频,显摆了一下。当时很多人都希望我赶紧弄完,然后发教程。但谁知,一等就是两年~~~
原因很简单,第一年我卡在了路程环上,第二年我去忙别的事情了~
直接说路程环吧!
平衡小车的站立,至少需要两个环!一个是角度环,维持小车平衡。但是维持平衡还不够,你会看到它平衡的到处乱跑,不服从指挥。
所以需要第二个环:路程环(也有人叫速度环)。它能让小车原地不动,或者按照我们的要求移动。原理也很简单,它会监测小车轮胎的转速和转向,从而对小车的移动进行纠正。
为什么说至少需要两个环?
有的人还会做转向环,假设,如果有外力导致小车旋转了90°,那么也要把这个旋转纠正过来。
为什么说我在这里卡了一年?网上不是有很多方案吗?你手里不是也有样品吗?
确实,如果要做一个跟我手里一样的,一点都不难。但我不想做那样的,我用的是N20的电机,这种电机带码盘的很少,而且价格高的不正常!
有多高?
电机不加编码器,价格十多块。加了编码器之后,价格变成了37块钱!
自己定做一批高精度码盘?
一个是成本会有较大的提升,另外就是违背了我的初衷。我的其中一个初衷就是:尽量使用低成本、市面上现成的元件来制作这个小车。
一个电机十多块钱,但如果加上码盘,要卖到37!两个就70多!两个一元硬币大小的电机,卖70多,很难接受!
这个问题从2017年初就开始困扰我,怎么搞?再这么拖下去,外甥都要上大学了!!!
同期,卡着我的还有另一个问题,路程环的问题。假设,我真的没得选,用了37块钱一个的电机,能不能实现路程环?
这个我试了一下,虽然有些坎坷,但还是能用的。难道真的要用这个?
先给外甥做一个玩具出来吧,一方面做验证,另一方面,再拖下去,我这个舅舅的尊严就彻底没了。
做的过程很顺利,采用了8.4V的锂电池,转速一分钟300转的电机,外接了一个蓝牙串口模块,可以接手机,通过蓝牙串口助手发送指令,实现手机遥控的效果。在家附近找了个公园,测了一下无线传输的距离,撑死二三十米。但是忽悠小朋友足够了!
同时,继续查资料!
所以,这一阶段的主要问题是:如何在不使用测速码盘的情况下,或者是一些别的方式,实现小车原地站立。
查了很久,还真查到一个思路,还是最开始那个帖子。
那位前辈,也考虑了跟我一样的问题:不使用速度环,能否实现位置的维持!
他在处理这个问题的时候,思维上升到了能量的层面。小车在向前移动或者向后移动的时候,肯定会消耗能量。如果把前后消耗的能量抵消,那么小车就能原地不动了。
怎么计算这个能量?
说来也简单!把小车每个周期下,驱动电机的PWM的占空比,以及电机旋转方向记录下来,做累加。向前为正,向后为负,尽量保持累加和为零。进而实现小车的位置原地不动。
有没有效果?
据这位前辈说,有一定的效果,但是会随着时间不断偏移,偏移比较明显。
呵呵,这位前辈很调皮啊!这么搞,自己玩玩可以,不能做为作品对外分享啊。
怎么办?
那段时间差不多每天都在想这个问题,有时候睡觉也会想~
头疼了很长一段时间,终于出现了转机。
第一个问题的转机,我印象里出现在2017年下半年。
这里不得不提到一个人:孟瑞生,他曾经在电子发烧友论坛众筹STM32的开发板。我之所以注意到他,是因为他毕业于中北大学。
是的,跟我一个学校,也就是我师兄。
后来他去了嘉立创,创建了技新网。技新网主要做各种模块,方便工程师做验证。他们曾经推出过一款产品(非平衡车),上面同样使用了N20电机,同样对该电机进行了测速,但测速方式却和传统的平衡小车完全不一样。
传统的电机在测速的时候,他们是在电机的旋转轴上加了一个码盘,这样电机在旋转的时候可以测出它的转速,还有旋转方向,这个码盘可以是光栅码盘也可以是霍尔码盘。
放个图:
这里借用平衡小车之家的图给大家说下。
左边的电机在电机旋转轴上增加了一个霍尔码盘,电机转一圈,码盘输出13个信号(数量多少根据码盘结构)。而右边的电机,在旋转轴上增加了一个光电码盘,码盘旋转一圈可以输出500个脉冲。
无论是13还是500,都是减速前的脉冲个数,如果电机减速比是30的话,前面的数字还要乘以30.13X30或者500X30,就是小车轮胎旋转一圈输出的脉冲个数。
技新网是怎么做的?
他们使用了一个红外反射式传感器,做了个模块,利用轮胎自身的结构,组成了一个另类的测速装置,如图:
核心是里面用到的芯片:ITR8307。这是一个红外反射式传感器,芯片表面由两部分区域组成。一部分用来发射红外光,另一部分用来接收红外光。如果能接收到,说明芯片表面有类似镜面的物体存在,那么,这有什么用?
看轮胎!
早期的卖家在宝贝详情里会说一句话:轮胎自带编码器(现在好像看不到了)。
原谅我才疏学浅,孤陋寡闻!很长时间,一直没明白自带的编码器在哪,怎么用!直到技新网做了上面那个模块,我才明白过来。
轮胎内部自带白色牙齿(原谅我用“牙齿”这个词),共有12个。他们把红外反射模块固定在牙齿下面,当轮胎旋转时,牙齿会依次、间断的从传感器上面经过,出现的效果就是高、低、高、低电平的不断输出。单位时间内计算脉冲信号个数,速度有了~~~
注意这里的脉冲个数,上升沿12个、下降沿12个!轮胎转一圈只有24个!
然后是方向。很遗憾,这种编码器没法计算方向。但是无所谓,我只需要在检测到高低电平的时候判断一下电机的驱动方向就行了,毕竟当前脉冲个数不多,精度一般。
而这种解决方案的成本,相比37块钱一个电机的价格,简直便宜的不像话。
电机测速问题解决了,但是路程环怎么搞?
前面说了,常用的测速码盘,旋转一圈,输出的脉冲个数,要么300+,要么上千。而这里的码盘,旋转一圈,输出24个脉冲!!!
这个数量级的差别,导致我在调试路程环的时候几乎无从下手!现有的程序移植过去,上电,几乎看不到路程环起作用。如果把路程环里的PID参数调大,最直观的现象就是小车变得剧烈的抖动,然后倒下。
怎么办?
那段时间差不多每天都在想这个问题,有时候睡觉也会想~
头疼了很长一段时间,第二个问题终于出现了转机,结果就是算法方面要换一种思路。前面说了,角度环已经没有问题,有问题的是当前状态下的路程环。解决这个问题只有两个方向:1、优化;2换思路。
我选择了第二个,怎么换的思路?这里不得不提到我的岳父大人,他除了是我岳父,还有一个身份,就是一位老中医,老武术家。有一些人跟他学武术,周末的时候经常聚在一起练习。
我跟着去过几次,有一段对话让我印象很深。当时是一个人想他提问,关于搏击的问题。我岳父具体怎么回答的我已经记不清了,大致意思就是:
“两个人搏击,目的就是把对方放到。而放倒对方最核心的方式,就是破坏对方的重心!”
是的,破坏对方的重心。我当时对这段话印象深,是因为我岳父的学历,说实话不是很高(这里没有任何意思,只是陈述一个事实),但是却能用一种很科学的方式来描述这个问题。让我很是惊讶!
而后期我头疼的那段时间,这句话时不时出现在我脑子里。所以我在想,会不会有什么启发的作用?注意,下面是我的思考过程(你们也可以自己先想一下):
小车的站立也要保持重心平衡,如果不平衡,那么就会往一个方向偏。在这个过程中,我要阻止外力对小车重心的破坏。
小车的平衡靠角度环可以实现,但是会偏。怎么不让它偏?
由于小车的车身质量分布并不均匀,导致小车水平的时候可能并不是它的平衡角,那就需要找到这个平衡角。小车维持平衡的角度,刚好是小车重心垂直过电机轴的角度。所以小车初始调试的时候,需要先找平衡角。
假设已经找到了平衡角,在平衡角状态下,外力导致小车向前走了7步,我可以通过码盘测速测出来。那么,怎么纠正?
重心!
是的,我可以让小车的重心平衡角向反方向增加0.7°。这样角度环为了维持平衡,会自动往反方向纠正。往回走一步,重心平衡角上面添加的误差少一点,回到原地,角误差清零。
当我想出这个方法的时候,脑子是极度兴奋的!因为我相当于抛弃了传统的路程环,重新设计了一种控制思路。同样是夜里十一点多,我把这种思路转化为代码,编译、烧录、上电。
现象跟我想的一样,小车以一个位置为原点,做往复运动!
在这种情况下,只需要把偏差和重心结合起来,使用PID的方式计算出一个纠正用的误差角,叠加到小车的平衡角上就行了。而传统的路程环就彻底被我抛弃了,这种新的PID环,如果之前没有人用过的话,我想把它叫做重心环。
问题解决了,那几天脑子异常兴奋,开始准备后续的事情了。
我准备做一批,既可以做玩具,又可以当做最小系统板,还能以项目的形式学到东西。
接下来依然是三步走:
1、确定方案,画原理图、PCB,找工厂安排制板、焊接、组装;
2、编写教程;
3、给小车起个名字。
先说起名字的事,叫什么?
我和我媳妇想了好几天:
煎饼一号?蹭煎饼侠热度~~~
青蛙一号?板子绿的的就叫青蛙?下次制板变成红的,是不是还要叫蜻蜓?
舅舅一号?给外甥做的就叫舅舅一号?万一升级到舅舅二号,别人会以为他有两个舅舅。
后来想了想,解决小车技术的一个关键点是重心环的出现,所以我觉得应该和重心相关比较好,想起了之前的一部电影《地心引力》,就叫:地心一号吧!
硬件方案方面:
STM8S103F3P6+MPU6050+TB6612+蓝牙串口模块+红外遥控
蓝牙串口模块在这里有两个功能:一个是调整PID参数的时候,可以终端界面无线测试;另一个就是在键盘界面控制小车的行驶方向。
电池最开始我选的8.4V,也就是两片4.2V的串联。但是后面发现有4V左右1分钟300多转的电机,那自然就换回了4.2V的电池。目的很明确,节约成本。但同时引发两个问题:
1、STM8S工作电压3.3V,电源芯片怎么选?1117-3.3? 那是肯定不行的,这个问题我不直接给出答案,想知道的,搜一下“LDO”的意思,再看看1117-3.3的数据手册就行了
2、电池电压降低,小车的马力自然也降下来了,最直观的表现就是:它只能在室内光滑的瓷砖上走,路面坎坷的情况下,是走不了的。所以,如果有朋友想要大马力的,需要更换电池和电机。
但是不管怎么说,老夫很欣慰!
这个时候又出了一件事,绊了我一下~~~小车真的是命途多舛啊~~~~
什么事?
STM8S103F3P6涨价了!之前一片2元左右,你知道2018年涨到了多少吗?
当时嘉立创的价格从二点多一路涨到了15元!!!这个破玩意卖15!!!
可惜当时我没有截图,当时嘉立创宝贝详情页面上还标了是厂家管控的原因。当时有个说法,说是因为2018年意法半导体在推STM8S001,一个SO-8封装的8脚单片机,为了给它让路,所以搞了这么一堆破事。
2019年,总算价格下来了。陆陆续续,事情开始进行。生产方面,事情安排下去就行了,比较省心。
最后是教程,看过我51教程的人都知道,我做教程,喜欢把复杂问题简单化。每一节,尽量控制时间不超过20分钟,尽量讲几个知识点。有用、不多,但是很关键!学到知识的同时,更能学到方法!
所以又花了一段时间优化教程。关于STM32,很多人都是用库函数开发的。那么STM8,教程里用库还是寄存器?我当时想了一段时间!因为库已经是一种趋势了,我有预感,库普及的范围会越来越广!所以决定,STM8S的教程用库函数来开发。当然,如果大家感兴趣,后面我会再补一套寄存器的例程。
因为网上有人分享了一个自动生成STM8S库函数代码的工具,所以例程的编写一直进行的都比较顺利。直到2019年8月份左右,出了一个问题!一个很有意思的问题!这个问题我现在已经找到原因,并解决了!
先说下我的开发环境,我使用的是IAR工具,然后从ST官网下载了STM8S系列的外设库。原理图在设计的时候,为了尽量多的给大家增加一些可以学习的东西,同时又因为STM8S103F3P6管脚比较少。我把一体式红外接收器的管脚放在了STM8S103F3P6的PD1上,用过这个系列的朋友会知道:PD1不只是一个普通的IO,它还是STM8S的SWIM管脚,也就是下载管脚。
问题是什么?
问题就是,当我使用库函数的方式,用PD1管脚做红外遥控器的解码的时候,PD1无法正常工作。解码方式就是51里常用的定时器+下降沿中断的方式。
有人肯定会说,数据手册里有说明:PD1要当普通管脚用的话,需要禁用SWIM功能。
呵呵,你觉得我没看嘛?
我可以负责任的告诉你,不管你有没有禁用SWIM功能,PD1都能当做普通IO使用?
为什么?
因为我最初调试小车时,就是使用寄存器的方式写的,这些功能全都验证了一遍!!!现在这些代码还在我电脑里放着。
所以,这就很有意思了,这是怎么回事?
可以给你们一些思考时间,再往下看。
我当时找了一个STM8用的比较好的朋友,请他帮我写了一个测试程序,使用PD1管脚,库函数方式。很快,他写完发给我了。
结果我打开一看,傻眼了,他用的是另一个开发工具:STVD。
是的,开发STM8S,有几种不同的工具,IAR、STVD都可以,都支持官方的库函数。
他发来的程序能不能用? 肯定是能用的,因为我这个朋友写代码比较严谨,要么仿真验证、要么实物验证,而且风格一向很好。
怎么办?当然是让他重写,用IAR。
果然,他也遇到问题了。PD1一旦遇到下降沿中断,定时器的时间就跑的乱七八糟,状态很不稳。他跟我说了一下,我基本已经断定问题在哪了。
福尔摩斯说过一句话:排除掉所有的不可能,剩下的,无论多么不可思议,它就是真相!
现在已经验证过的是:IAR+寄存器编程、STVP+库函数编程都没有问题,芯片、下载器、电路更没有问题。剩下的,就是IAR出了问题!是的,它对库函数的支持有问题!
而且这个结论出来以后,我瞬间想起了以前用库函数的时候,出现的一些奇怪的问题,都能解释清了。
现在的问题是,怎么办?教程已经录到结尾了,总不能又重新录吧。
想了想,也有办法!
混编!
是的,同时使用库函数和寄存器的方式进行编程。这种方式对新手来说可能有些奇葩,但其实早就存在了。更早的了解到这种方式,对新人来说,可能是一件好事。STM32里混编可能用的相对多一些,但这不影响。问题已经确定了,把和问题相关的部分代码都换成寄存器方式编写的,调一调~~~OK
所以,到最后,我拿出来的是这样的一个作品:
它精致、迷你、强大!
它不完美,甚至有缺陷!但是,它的出现让人期待,让人相信美好的事情总是会发生的。它的功能,我可能会持续优化下去,如果有感兴趣的朋友,也可以一起优化。资料稍后我会放到网盘,也可能会放到github上。
希望你们喜欢——地心一号!