8846| 15
|
[讨论] 两轮自平衡小车的制作总结 |
自从一个月前帮朋友搞定了SD卡软字库后(https://mc.dfrobot.com.cn/thread-305932-1-1.html),感觉Arduino还是蛮好玩的,于是抱着学习的目的,做了一个两轮的自平衡小车,先上图。 不负重 负重 X轴斜坡 Y轴斜坡 X+Y轴斜坡 遥控行驶 自平衡小车 遥控器 |
不负重:https://v.youku.com/v_show/id_XNDcxMzE4MzI0OA==.html 负重:https://v.youku.com/v_show/id_XNDcxMzE4Nzg3Mg==.html X轴斜坡:https://v.youku.com/v_show/id_XNDcxMzE4OTUyNA==.html Y轴斜坡:https://v.youku.com/v_show/id_XNDcxMzE5MDY2MA==.html X+Y轴斜坡:https://v.youku.com/v_show/id_XNDcxMzE5MTY1Mg==.html 遥控行驶:https://v.youku.com/v_show/id_XNDcxMzE5MjY2OA==.html |
先说说硬件模块的选择 开发板一开始选择的是Arduino nano,到后面发现有两个问题。一个是加上wifi模块或者蓝牙模块后,nano体积小的优势就丧失了。另一个是有些模块只能工作在3.3v下,这样一来就需要额外再加一个电平转换模块。所以最终选择了esp32,使用了最常见的devkit v1开发板(ESP WROOM 32)。 姿态模块就是烂大街的MPU6050,不过我碰到一个问题,就是通过I2C读取MPU6050时,如果这时候SPI总线上有数据交换(我使用了一块SPI接口的TFT屏幕),就会导致I2C读取超时,这个问题一直没能很好的解决,所以最后换了块串口接口的MPU6050,算是曲线救国吧。 电机驱动模块是TB6612,体积小。我使用的是12V电压,卖家说如果超过10V有可能会爆电容,不过到目前为止,板子上面的钽电容还好好的,没有炸掉。 超声波测距也是烂大街的SR04,不过这个测量精度,只能是呵呵了。 小车上的屏幕,使用的是I2C接口的OLED屏,遥控器的屏幕,则是SPI接口的TFT屏。至于为什么要选择两种不同接口的屏幕,很简单,我是抱着学习的目的,所以两种接口都要试试。 电机是JGA25-370,减速比1:34,12线的霍尔编码器,另外再配个底座。之所以选择霍尔编码器,是因为我会在室外测试小车,所以尽量的选择了封闭式的编码器,如果你只是在室内测试的话,那就选择光电编码器,毕竟精度比霍尔编码器大了几十倍。 电池是普通的航模电池,1500mAh-4S-35C,足够我调试一整天了。 降压模块选择的是MP1584,一个转3.3V,一个转12V。另外加了一个40k的可调电阻,分压1/5给EPS32用来测量电池电压。这里有个小插曲,EPS32有两组ADC,第二组是和wifi冲突的,如果开启了wifi,就只能用第一组ADC了。 在室外测试的时候,发现蓝牙的通讯距离不够远,所以后期又增加了一块2.4GHz的无线传输模块,视距可以达到50米,再远我没试过,模块介绍是可以达到100米。但是距离是够了,丢包率却高的吓人,最后只能在程序中添加了校验和来解决这个问题。 一开始没想做遥控器的,后来发现用手机遥控起来不方便,就做了这么一个遥控器,直接用MPU6050控制。用起来很简单,遥控器拿在手里,然后手直接前后左右摆动就可以控制小车运动了。遥控器的硬件模块也差不多,电池是700mAH的,体积足够小,可以藏在开发板的下面。另外使用了一块充电+升压一体的模块。 最后就是组装了,秉着简单、可重复利用的宗旨,使用了洞洞板、插座、电线、铜柱、螺丝,另外3D打印了支架用于固定屏幕和SR04,以及遥控器的盒子。 |
本帖最后由 开在边缘 于 2020-6-16 18:47 编辑 软件的编写 最核心的就是PID算法了,基本知识就不多说了,网上关于PID算法的介绍实在太多了。这里我说一下自己的理解和碰到的问题。 在角度环(平衡环)中,一般都不用I,也就是积分,取而代之的是速度环。如果你的电机没有编码器的话,那就很难用上速度环了,这时候你可以使用角度环中的积分。我测试的时候,如果不用速度环,使用角度环中的积分也可以让小车平衡,就是效果没有速度环那么好。 在速度环中,我没有使用积分限幅。当你推动小车,打破平衡后,小车应该回到原点。此时如果使用了积分限幅,当小车移动距离太大的话,因为积分限幅了,就会导致小车无法回到原点。如果不用积分限幅的话,那么后期遥控小车运动的时候,速度就要人为控制了,否则速度太快,小车就无法保持平衡了。另外如果电机没有编码器的话,就无法使用速度环来控制小车的前后移动,此时可以通过改变角度环中的小车的平衡角度,变相的控制小车的前后移动。 转向环我是参照了速度环,将Z轴的角速度做为比例控制,同样可以很好的控制小车在静止状态和运动状态的转向。 调试PID参数时,最好是无线方式。一开始我是有线方式,结果小车翻车后,直接把开发板上的USB口给撅下来了,心疼10秒钟。还好开发板便宜,否则心都要滴血。后来写了简易的调试程序,直接通过TCP的方式进行调试。 在调试中,我发现如果先调试好角度环,然后再调试速度环的时候,无论怎么调,小车都会摆动的很厉害。后来网上查了很久,看到一篇文章,其中提到在调试速度环的时候,最好把角度环按比例减小一点。我把角度环整体减小到90%,再调试速度环,就非常顺了。同样的在调试转向环的时候,再把角度环和速度环整体减小一点,调试起来也方便了。 静态调试结束后,开始动态调试。如果不改动PID,我发现小车虽然可以运动起来,但是姿势很僵硬,特别是在急转弯的时候会扭扭歪歪。感觉就像是角度环强行的把小车掰正,导致了小车无法快速运动。参照之前的方式,在小车运动时,将PID参数按比例减小一点,就可以让小车很顺的前后移动和转弯了。 所以最后我给每一组PID参数,增加了2个参数,一个是静态状态下的比例参数,一个是动态状态下的比例参数。 另外电机的电压非常重要,如果不稳压的话,直接将电池接到电机驱动板上,会导致电压不稳,当电池电压下降的时候,小车就无法快速的恢复平衡,辛辛苦苦调好的参数,会随着电压的变化,而变得一无是处。 如果小车上装载重物,并且重心偏高的话,那么最好将PID参数放大一点,这样可以让小车尽快恢复平衡,否则小车左右摆动的幅度会越来越大,最后倒下。 |
本帖最后由 开在边缘 于 2020-6-16 20:23 编辑 任务的分配 后期因为改用了ESP32的开发板,有两个CPU核心,Arduino默认只使用core1,core0是不使用的,这个就太浪费了。 我把MPU6050和PWM有关的任务,放在loop()里面,也就是core1上执行,剩下的无线通讯、屏幕显示、超声波测距等都放在core0上执行。 但是在实际开发中,在core0上执行的任务导致的看门狗问题一直困扰着我。 loop()里面的程序,执行时间再长,也不会引起看门狗复位,同时也不需要喂狗。这个应该是Arduino自己做了这些事情。 其他放在core0上执行的任务,如果程序执行时间过长,就会导致看门狗复位。我查了很多资料,无论是自己喂狗,还是索性关闭看门狗,都不起作用。最后我只能使用vTaskDelay(1),让系统空闲1ms,就解决了这个问题。具体原因我也不知道为什么,我只是猜想,是不是因为系统空闲了,自动喂狗了? 无线通讯 ESP32本身就支持WIFI和蓝牙,考虑室外的通讯距离,后期我又增加了一块额外的2.4GHz的无线串口模块(实测视距>50米)。 WIFI 这个主要用在一开始的调试阶段,ESP32连接WIFI后开启TCP Server,然后Windows下面编写了一个简易的TCP Client程序,进行PID参数的调节。 蓝牙 这个主要用于遥控,ESP32的蓝牙,是低功耗蓝牙+经典蓝牙。开始的时候,我是使用的低功耗蓝牙,但是有一个问题,一直无法解决。直接使用ESP32的BLE例程,一个字都不改,当两块ESP32通过BLE连接后,有时候好好的,没问题。但是有时候短短几秒钟,就会断开连接。如果此时重连接,还是一样。这个问题,在使用BLinker时也存在。Blinker通过BLE连接ESP32后,有时候好好的,一直保持连接。有时候几秒钟后就自动断开连接了。折腾了好长时间,一直都不知道问题出在哪里,所以后期改用了经典蓝牙。 经典蓝牙用起来就简单多了,直接使用蓝牙串口,就和串口一样操作。不过同样也有一个问题,也一直无法解决。当2块ESP32通过蓝牙串口相连后,如果一块ESP32持续的向另一块ESP32发送数据,而此时接收数据的ESP32突然断电,这时候发送数据的那块ESP32会卡在发送程序中(我指的是蓝牙串口自己的发送程序),这样就导致了接收数据的ESP32上电后,就算再次连接成功,也无法接收到任何数据,而那块发送数据的ESP32则一直卡在发送程序中,除非重启。有意思的是,这块卡在发送程序中的ESP32,竟然看门狗也不起作用,不知道是为什么。 我尝试过,此时如果把发送数据的ESP32的蓝牙串口end掉,则马上会出现看门狗超时复位。如果把整个发送过程做为一个任务,就算结束这个任务,再开启这个任务,也没用。 这个问题表现出来的实际操作就是,当遥控器上电,通过蓝牙串口连接上平衡小车后,平衡小车开始回传数据给遥控器,此时如果关闭遥控器电源,再重新打开电源,遥控器可以通过蓝牙串口连接上平衡小车,也可以发送数据给平衡小车,但是无法接收到平衡小车的数据,因为平衡小车的发送程序卡住了。 2.4GHz的无线串口模块 这个主要用于室外的远距离遥控,我在室外测试的时候,最远视距50米,再远就没有尝试了,说明书上写的是可以达到100米。 不过啥东西都不是完美的,多多少少都有问题,这个模块的问题就是丢包率太高了。前期没有校验的时候,发现接收到的数据很多都是错误的,开始以为是距离远造成的干扰,但是后来发现距离1米内还是会丢包。最后没办法,程序中增加了校验位,用于剔除丢包的数据。不过剔除这些错误数据后,发现正确的数据没剩下多少了,带来的问题就是通讯速率的降低,导致的结果就是小车的运动总感觉慢半拍。 参数的保存 这个使用EEPROM来保存,这里要注意一点,如果你使用了Blinker,那就不要使用地址0-2047,这些地址被Blinker占用了。 这里我碰到过一个很奇怪的问题,有时候当我写EEPROM时,ESP32就重启了,连接串口后,显示的信息是地址不存在。 后来发现和电机通电有关,如果电机在运转,就会出现这个问题。如果电机不在运转,就没问题。 难道是电磁造成的干扰? 这个问题困扰了我3天,3天后解决了,怎么解决的?我也不知道,因为我一个字也没改,就突然好了,不出问题了。真是搞不懂。 |
本帖最后由 开在边缘 于 2020-6-16 20:41 编辑 最后总结一下 建议: 1、增加一个按钮,我称之为“急停按钮”。顾名思义,按下按钮,电机紧急停止,这个功能在调试的时候是非常管用的。同时在后期,可以为这个按钮增加单击、双击、三击等功能(类似鼠标)。在我的平衡小车上,双击可以更换屏幕显示的内容。另外在平衡小车上电的时候,如果按着按钮,就忽略无线通讯功能,这样在调试的时候可以排除遥控器上的问题。 2、急停功能除了考虑Y轴和X轴角度偏大,同时也要把电机卡死和电机空转考虑进去。 电机卡死:在一段时间内(比如300-500ms),当PWM大于一定数值,而编码器小于一定数值,就可以判断轮子卡住了 电机空转:当把平衡小车拿起来后,会因为速度环的原因,导致轮子一直在转,所以要考虑电机空转的问题。我的判断方法是,在一段时间内(比如300-500ms),如果遥控器并没有给出移动或者转向的指令,但是PWM一直保持最大值,则判断为平衡小车离地了,这时候就需要急停。 3、调试的时候,我发现在柔软的地面上(比如地毯、沙发),平衡小车会非常的稳定,30%的概率会达到完全静止,一动不动,直挺挺的站在那里。我觉得应该是柔软的地面,对平衡小车的轮子造成了很大的阻力,当电机的扭矩无法克服阻力时,这个扭矩会反作用在平衡小车的车体上。我在网上查了查国外的一些做的很好的平衡小车,发现他们使用的轮子都很大,看上去很重的样子。所以我猜想是不是在电机可驱动的范围内,适当增加轮子的重量,会对平衡小车的平衡能力起到很好的作用? 还未解决的问题: 1、I2C接口读取数据时,如果此时SPI接口也在读写数据,会造成I2C超时。我试过把两者放在两个任务中,然后两个任务在不同cpu核上运行,也同样会超时。 2、低功耗蓝牙会莫名其妙断开连接。 3、经典蓝牙发送数据时,接收端突然断电,会导致发送端卡死在发送数据程序中。 4、转向环我是将Z轴的角速度做为比例控制,在运动状态下没什么问题,但是在静止状态下,有时候微小的Z轴方向的转动会检测不到(不知道是因为模块本身的问题,还是因为程序轮询的问题),这就导致了静止状态下不够稳定。我测试的时候,一般在30分钟内,小车会旋转偏离大概10-30度左右。 后期预计增加的功能: 1、增加一个线性ccd模块,用于循线。 2、增加一个舵机,用来旋转超声波测距模块,这样可以探测周边更大范围的距离。 |
您好我有一个问题,请问如果通过改变倾角的方式来控制小车前进的话,小车能否以固定的速度前进呢,我调试了好久,一直没有找到能够让小车保持固定速度前进的方法,求指点!谢谢~ |
© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed