10877浏览
查看: 10877|回复: 5

[项目] 超声自平衡小车

[复制链接]
本帖最后由 丄帝De咗臂 于 2015-9-22 20:50 编辑

1、项目概述

2014年底在网上看到各种制作自平衡小车的帖子,也跟着做了起来。因为第一次做,心里没底,也就没有投入过多的资金,一切按照最小配置进行,所以选择“TT马达”,俗称“香蕉电机”的小车底盘。在等快递送货期间,才看到各种说用“香蕉电机”做自平衡小车的问题,最大的问题就是电机启动对传感器和单片机的干扰问题,还有就是平衡的稳定性不好等问题。在我以Arduino + MPU6050 + L298N为核心做完后,闲得没事干,就想做一款成本低,易上手,最小配置和最基本功能的自平衡小车,其目的就是给那些没有什么经验的刚入行的新手们提供一个入门的解决方案。所以这个项目的目标有以下几点:

a、成本低;

b、目标功能明确,就是实现小车的自平衡;

c、系统稳定可靠;

d、调试、操作方便简单。


2、项目方案


基于上述目标,本方案采用超声波测距模块作为小车平衡状态的检测,免去了对加速度、陀螺仪传感器的理解和复杂处理算法。小车的平衡控制仍然采用网络上流行的Arduino开源硬件,再加上电机驱动模块 L298N,电机仍然采用TT马达(香蕉电机)。

该方案为了降低成本,采用电位器调整设定小车的平衡参数,不使用蓝牙无线模块或有线串口在线调整参数。

用超声波测距的方式实现的自平衡小车,网络上有人提出这种方案无法在坡度变化的斜坡上保持平衡,这种说法经过我的实践,是有解决方案的,这个问题我将在后面进行阐述。

平衡控制的算法还是采用平衡车中经典的PD算法。


3、硬件设计

硬件设计比较简单,以Arduino Nano为核心控制模块,采用HC-SR04超声波测距模块,L298N电机驱动模块,供电采用7.4V/2200mAh锂电池。图中三个10K电位器分别用于平衡点设置、PD算法中Kp和Kd系数设置的调整。

电路原理图如下所示:
超声自平衡小车图1

图中J1为HC-SR04超声波测距模块,J2、J3为L298N模块,Arduino Nano为核心控制模块,MG1、MG2分别为左右电机。

与之前用香蕉电机+MPU6050做的自平衡小车相比较要简单很多,在MPU6050方案中,用了两块电池,其中一块单独用于电机供电,而且L298N必须用光耦隔离的。

而用超声波做的自平衡小车,虽然用的是TT马达(俗称香蕉电机),但仅一块电池供电,L298N电机驱动模块也没有光耦隔离,从最终调试后的效果上看,还比前者更稳定。

成品照:
超声自平衡小车图2

材料清单
超声自平衡小车图3
4、器材采购

a、Arduino Nano模块
b、HC-SR04 超声波模块
注意,HC-SR04超声波模块,一般有两种,我们用的是不带晶体的,还有种带晶体的不要买,在近距离不稳定,另外测量的最小周期要稍长一些。
c、L298N电机驱动模块
d、TT马达及固定件
e、电池及充电器


5、程序

代码如下(更多见附件)
  1. //利用超声波测距传感器实现小车平衡
  2. char val='z'; //调节与控制命令字
  3. double Kp=0.01, Kd=0.02; //PID系数
  4. unsigned int PB_ad=0, KP_ad=0, KD_ad=0, i; //平衡点调整,PID各调整设定系数
  5. unsigned int Len_Echo = 0; //回波时间
  6. int E_0 = 0, E_1 = 0, PWM_Out; //误差,PWM输出
  7. double Len_filter = 0, Len_0 = 100; //测距滤波,机械平衡距离
  8. unsigned int TrigPin = 4; //HC-SR04触发信号
  9. unsigned int EchoPin = 5; //HC-SR04回波检测
  10. unsigned int M_IN1 = 6; // L298-IN1
  11. unsigned int M_IN2 = 7; // L298-IN2
  12. unsigned int M_IN3 = 8; // L298-IN3
  13. unsigned int M_IN4 = 9; // L298-IN4
  14. unsigned int M_ENA = 10; // L298-ENA
  15. unsigned int M_ENB = 11; // L298-ENB
  16. //初始化
  17. void setup() {
  18.   Serial.begin(115200);
  19.   pinMode(M_ENA, OUTPUT); //电机控制
  20.   pinMode(M_IN1, OUTPUT);
  21.   pinMode(M_IN2, OUTPUT);
  22.   pinMode(M_ENB, OUTPUT);
  23.   pinMode(M_IN3, OUTPUT);
  24.   pinMode(M_IN4, OUTPUT);   
  25.   pinMode(EchoPin, INPUT); //超声波测距
  26.   pinMode(TrigPin, OUTPUT);
  27.   digitalWrite(TrigPin, LOW);
  28.   for(i=0; i<64; i++) {
  29.     PB_ad += analogRead(A0); //读取平衡点电位器设定值
  30.     KP_ad += analogRead(A1); //读取PID-P电位器设定值
  31.     KD_ad += analogRead(A2); //读取PID-D电位器设定值
  32.   }
  33.   Kp *= KP_ad/64; //Kp = 3.23;
  34.   Kd *= KD_ad/64; //Kd = 8.14;
  35.   Len_0 += PB_ad/640; //Len_0 = 189;
  36.   i = 0;
  37. }
  38. //主循环程序
  39. void loop() {
  40.   if (Serial.available() > 0) {
  41.     val = Serial.read();
  42.     if(val == 'F') {
  43.       Serial.print(Len_0); Serial.print("\t"); Serial.print(Kp); Serial.print("\t"); Serial.println(Kd);//查看设置参数
  44.     }
  45.     if(val == 'L') {
  46.       Serial.print(Len_Echo); Serial.print("\t"); Serial.println(Len_filter); //查看传感器实测值,滤波值
  47.     }
  48.   }
  49.   digitalWrite(TrigPin, HIGH); //发送超声波测量触发脉冲
  50.   delayMicroseconds(10);
  51.   digitalWrite(TrigPin, LOW);
  52.   Len_Echo = pulseIn(EchoPin, HIGH); //回波时间测量
  53.   if((Len_Echo < 300) && (Len_Echo > 70)) {
  54.     Len_filter *= 0.7; //一阶互补滤波
  55.     Len_filter += 0.3*Len_Echo;
  56.     i ++;
  57.     if(i > 50){
  58.       E_0 = Len_0 - Len_filter;
  59.       PWM_Out = Kp * E_0 + Kd * (E_0 - E_1);
  60.       E_1 = E_0;
  61.       i = 100;
  62.       SetMotorVoltage(PWM_Out);
  63.     }   
  64.   }else {
  65.     SetMotorVoltage(0); //超出平衡范围,停止PWM输出
  66.   }
  67.   delay(5); //延时5毫秒,保证超声测距可靠工作
  68. }
  69. //电机输出
  70. void SetMotorVoltage(int MotorVol) {
  71.   if(MotorVol >=0) {
  72.     digitalWrite(M_IN1, LOW);
  73.     digitalWrite(M_IN2, HIGH);
  74.     digitalWrite(M_IN3, LOW);
  75.     digitalWrite(M_IN4, HIGH);
  76.   }else {
  77.     digitalWrite(M_IN1, HIGH);
  78.     digitalWrite(M_IN2, LOW);
  79.     digitalWrite(M_IN3, HIGH);
  80.     digitalWrite(M_IN4, LOW);
  81.     MotorVol = -MotorVol;
  82.   }
  83.   if(MotorVol > 255) MotorVol = 255; //防止PWM值超过255
  84.   analogWrite(M_ENA, MotorVol);
  85.   analogWrite(M_ENB, MotorVol);
  86. }
复制代码
程序:下载附件v2.4.zip


6、调试流程

最新版超声平衡小车装配完毕后如下图所示。
超声自平衡小车图4

串口调试助手程序:下载附件SSCOM32.zip
a、准备工作

将Kp与Kd调为0,调整方法是,旋转电位器后,按下Arduino模块上的复位键调整方可有效。调整后用串口调试助手(sscom42.exe)发送“F”命令,读取超声自平衡小车参数的设定值。在使用串口调试助手前,首先选择串口调试助手对应的串口号,设置好波特率,方可发送上述命令读取超声自平衡小车参数的设定值,操作界面如下图所示。
超声自平衡小车图7

第一个数据为平衡点设定值,第二个数据为Kp,第三个数据为Kd。

b、超声波测距测试

发送相应“L”命令,读取超声波的测距值,注意,这里不是实际的mm或cm值,而是对应距离来回的传播时间值,是单片机内部计时的输出值。

操作界面如下图所示。
超声自平衡小车图8

第一个数为超声波测距模块的直接输出值,第二个数为一阶滤波后的值。改变超声波测距模块与被测界面的距离,这两个值会发生相应的改变,距离近,测得的值变小,距离远测得的值就增大。


c、寻找物理平衡点

在Kp、Kd为0时,用手寻找自平衡小车的物理平衡点,同时用“L”命令(500ms定时发送)读取超声波测量的返回值,确定平衡点的返回值,并记录下来。


d、平衡点PB的设定

调整PB电位器,并在Arduino复位后,用“F”命令读取超声自平衡小车参数的设定值,使得第一个返回的数据与上述确定的物理平衡点相一致。

e、判断电机运转方向是否正确

在完成上述调整后,逐渐增大Kp(请记住,每次调整后,都必须复位Arduino模块,调整才能生效),看到电机能够动作时,停止调整Kp。这时将超声波模块一端稍稍下压(也就是使超声波探头与地面距离缩短),观察两个电机的转动方向,往前(超声波测距模块一端为前)转测试正确的,往后转则说明相应的电机两根线接反了,将接反的线调换过来即可。


f、Kp参数整定

在电机接线正确后,再逐渐增大Kp,使得小车能够来回有点摆动即可进入调整Kd参数阶段。


g、Kd参数整定

在调整完Kp后,逐渐增大Kd,使得摆动消失,如果继续增大Kd,小车会出现明显的抖动,此时将Kd往回调整,使得抖动消失即可。


h、平衡点PB的进一步调整

在上述参数调整完毕后,小车一般就能保持平衡了,如果出现小车往一边跑的现象,可通过调整PB电位器加以修正。如果小车往前跑(超声波模块一端为前),调整PB使得平衡点设定值增大;如果小车往后跑,调整PB使得平衡点设定值减小,直到小车能够长时间稳定为止。
7、照片与视频
超声自平衡小车图9



8、总结与展望

超声自平衡小车的基本版已经完成,在制作过程中与我之前用MPU6050制作的小平衡车相比有以下几点体会:

a、在用TT马达的情况下,如果系统使用同一组电池供电,电机一启动Arduino与MPU6050立即死机,或者MPU6050的数据受干扰极为严重,不可使用。解决办法是用另一组电池单独给L298N供电,并且L298N要选择带光耦隔离的。但同样的使用TT马达的情况下,用超声波测距方案,系统仅用一组电池即可,而且L298N也无需光耦隔离,系统很稳定。

b、超声波传感器的选择要选择最小测量周期短的模块,第一次我使用的是US-015 超声波测距模块,US-015是目前市场上分辨率最高,重复测量一致性最好的超声波测距模块,US-015的分辨率高于1mm,可达0.5mm,测距精度高,重复测量一致性好,测距稳定可靠。但他的最小测量周期大于10ms,而且对输出数据经常有跳动(这是由于它的灵敏度很高,在近距离时超声波在模块与地面之间的来回反射的二次信号都能被检测到),为此在地面垫上一个地毯吸收了部分能量的超声波,才能稳定工作。在第二版中更换了HC-SR04超声波模块,这个模块的测距精度虽然只有3mm,但它的最小测量周期仅略大于3ms。但这种模块市场上有两种,一种没有晶体,一种是带晶体的,带晶体的很不稳定,建议大家不要选择。

c、小车的平衡稳定性与多种因素有关,建议在结构上,重心越低越好。

d、另外,我还做了一个对比测试,数据见下表:
超声自平衡小车图10

误差绝对值是指小车在一段时间内,实测距离与设定平衡点距离误差绝对值的平均值;滤波是指程序中对超声波测量的距离滤波或不滤波直接使用;循环周期是程序中的延时时间,超声波测量需要大约704us,一个周期大约为3.84ms,程序处理时间大约为136us,实测波形图如下。

超声测距波形图:
超声自平衡小车图11

3ms延时的一个周期波形图:
超声自平衡小车图12

通过以上对比分析,当一个循环周期大于20ms时,小车很难长时间保持平衡了,另外重心的升高,平衡的稳定性明显变差。

e、下一步选择具有测速功能的小车底盘,实现上下坡、下台阶等复杂动作,不为别的,只是证明超声自平衡小车这个方案是没有严重的缺陷的。因为自平衡小车本身就有很多局限性,譬如他能下台阶就不能上台阶吧,也不能在极不平坦的路上行走等等。

f、最后,我想说明一下,自平衡小车虽然简单,但也是一个麻雀虽小五脏俱全的项目,譬如小车的结构设计、电机的响应、扭矩的大小、小车的轮胎的选择、PID的调参等等都会影响到小车的平衡稳定性。我们在网上看到的资料大都是说传感器、程序和调参,在结构设计、电机的选择(明确的参数数据对比)等方面都很欠缺或不完整,没有充分的说服力。很多新人就想学校的实验课程一样,仅仅照别人的做法做了一遍,没有太大的收获,特别是碰到问题不知道如何深入分析。大家在DIY的过程中都做出点自己的东西,无论成功与失败,哪怕做一些经验和教训的总结也是对大家的贡献。希望大家在DIY这个乐园里无拘无束的、自由自在的、快快乐乐的玩耍!!!
原文:http://www.geek-workshop.com/thread-12538-1-1.html

hnyzcj  版主

发表于 2015-9-22 21:11:30

这个你做的张璐
回复

使用道具 举报

孙毅  初级技匠

发表于 2015-9-23 00:27:01

这个要多牛逼就多牛逼!
回复

使用道具 举报

栽培者  初级技师

发表于 2015-10-17 08:46:52

总价85. !牛。
回复

使用道具 举报

liweilin  高级技师

发表于 2016-12-29 15:03:47

用超声波做的之前也玩过,调试平衡花的时间最多。
回复

使用道具 举报

gray6666  初级技神

发表于 2017-1-12 12:49:28

简单实用,大赞
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail