平衡小车

2015-12-071.3万
AI 快速预览详细 收起
本文介绍了如何使用MPU6050传感器和L298N电机驱动器制作平衡小车,并通过一阶互补滤波和PID控制解决小车抖动和PWM输出为0的问题。文章详细描述了调试过程和解决方案,包括调整PID参数和优化角度计算方法。最终实现了小车的稳定运行。
一直对平衡车感兴趣,又找来一个平衡车的资料。以下内容主要转帖而来,原文http://www.geek-workshop.com/for ... &highlight=L298
小车整体造型大概是这个样子的
平衡小车图1

平衡小车图2

小车可以站住,但是小车抖动比较厉害。
使用的mpu6050,使用的一介互补滤波,得出 角度 angle_x 。虽然原文作者调节了参数,但据说效果还不是很理想。
平衡小车图3



然后通过 if 语句进行判断    if(angle_x>0)   控制L298n
接下来就是把 angle_x 进行PID 控制。 Input = angle_x;
  myPID.Compute();
  Serial.print(Output=);           通过PID计算得出 Output         疑惑的是 Output竟然是0
平衡小车图4

Output=0         这是什么原因呢????

然后把Output当做两个车轮的PWM脉冲,
  analogWrite(motor1PWMPin, Output);
  analogWrite(motor2PWMPin, Output);
Output=0 ,我测量motor1PWMPin motor2PWMPin两个管脚的电压还都是1.75,不管小车角度怎样,电压都不会改变。  ????

设定小车的静态平衡角度为  Setpoint = 10.0;     
初始   Input = 0.0;
  myPID.SetSampleTime(100);    //采样时间
  myPID.SetMode(AUTOMATIC);


PID的调节   PID myPID(&Input, &Output, &Setpoint, 1, 0, -10, DIRECT);

调了几天,没什么效果,真是郁闷。。。
又查了一些资料,可能是电机太水,但是也有看到别人用香蕉电机的,效果也还不错。

斗就斗把,后来加了码盘,用了槽型对射管,对两个轮子进行测速,蓝牙控制准备让小车行走,就使用Arduino uon 的两个外部中断计脉冲的个数,
标志==40的时候 车轮转动一圈,然后当接收到前进的命令的时候,让两个轮子全部正转2圈,但是经过测试 小车一直在保持平衡,所以没时间正转2圈(这样理解可以吧)。 所以 这个控制程序不会写了。。。欢迎大神可提供帮助哦,到时候我也可以去帮帮原作者,装一下大神,哈哈

代码
  1. #include<Wire.h>
  2. #include "gyro_accel.h"
  3. #include "PID_v1.h"
  4. // Defining constants
  5. #define dt 1            // time difference in milli seconds
  6. #define rad2degree 57.3  // radian to degree conversion
  7. #define Filter_gain 0.95  // e.g. angle = angle_gyro*Filter_gain + angle_accel*(1-Filter_gain)
  8. // Global Variables
  9. unsigned long t = 0;      // Time Variables
  10. float angle_x_gyro=0, angle_y_gyro=0, angle_z_gyro=0, angle_x_accel=0, angle_y_accel=0, angle_z_accel=0, angle_x=0, angle_y=0, angle_z=0;
  11. char val ;
  12. int maichong,lefta,leftaa,leftone,righta,rightaa,rightone;
  13. // DC motor driver with L298N
  14. const int motor1PWMPin = 10; // PWM Pin of Motor 1
  15. const int motor1Polarity1 = 9; // Polarity 1 Pin of Motor 1
  16. const int motor1Polarity2 = 8;  // Polarity 2 Pin of Motor 1
  17. const int motor2PWMPin = 5;  // PWM Pin of Motor 2
  18. const int motor2Polarity1 = 6; // Polarity 1 Pin of Motor 2
  19. const int motor2Polarity2 = 7;  // Polarity 2 Pin of Motor 2
  20. const int left=0; //码盘
  21. const int right=1;//码盘
  22. int ValM1 = 255;  // Initial Value for PWM Motor 1
  23. int ValM2 = 255;  // Initial Value for PWM Motor 2
  24. double Setpoint, Input, Output;
  25. PID myPID(&Input, &Output, &Setpoint, 1, 0, -10, DIRECT);
  26. //PID myPID(&Input, &Output, &Setpoint, 25, 4, -5.5, DIRECT);
  27. void setup()
  28. {
  29.   // MPU-6050
  30.   Serial.begin(115200);
  31.   Wire.begin();
  32.   MPU6050_ResetWake();
  33.   MPU6050_SetGains(0,1);  // Setting the lows scale
  34.   MPU6050_SetDLPF(0);    // Setting the DLPF to inf Bandwidth for calibration
  35.   MPU6050_OffsetCal();  // very important
  36.   MPU6050_SetDLPF(6);  // Setting the DLPF to lowest Bandwidth
  37.    
  38.   t = millis();
  39.    
  40.   // DC motor
  41.   pinMode(motor1PWMPin, OUTPUT);
  42.   pinMode(motor1Polarity1, OUTPUT);
  43.   pinMode(motor1Polarity2, OUTPUT);
  44.    
  45.   pinMode(motor2PWMPin, OUTPUT);
  46.   pinMode(motor2Polarity1, OUTPUT);
  47.   pinMode(motor2Polarity2, OUTPUT);
  48.   //0 1 zhongduan
  49. attachInterrupt(left, jishu1, CHANGE);
  50. attachInterrupt(right, jishu, CHANGE);
  51.   
  52.    
  53.   // set enablePin of motor 1 high so that motor 1 can turn on
  54.   digitalWrite(motor1PWMPin, HIGH);
  55.   digitalWrite(motor1Polarity1, HIGH);
  56.   digitalWrite(motor1Polarity2, LOW);
  57.   // set enablePin of motor 2 high so that motor 2 can turn on  
  58.   digitalWrite(motor2PWMPin, HIGH);
  59.   digitalWrite(motor2Polarity1, HIGH);
  60.   digitalWrite(motor2Polarity2, LOW);
  61.    
  62.   Input = 0.0;
  63.   Setpoint = 10.0;
  64.   
  65.   myPID.SetSampleTime(100);
  66.   myPID.SetMode(AUTOMATIC);
  67.   
  68. }
  69. void jishu()
  70. {  
  71.     lefta++;
  72.     if(lefta==45)
  73.     {  
  74.       lefta=0;  //mai chong biao zhi qing ling
  75.       leftone++;//一圈
  76.     }  
  77. }
  78. void jishu1()
  79. {  
  80.     righta++;
  81.     if(righta==45)
  82.     {  
  83.       righta=0;  //mai chong biao zhi qing ling
  84.       rightone++;//一圈
  85.     }  
  86. }
  87. void rightz()//右轮正转
  88. {
  89.   digitalWrite(motor1PWMPin, HIGH);digitalWrite(motor1Polarity1, HIGH);digitalWrite(motor1Polarity2, LOW);
  90. }
  91. void rightf()//右轮反转
  92. {
  93.   digitalWrite(motor1PWMPin, HIGH);digitalWrite(motor1Polarity1, LOW);digitalWrite(motor1Polarity2, HIGH);
  94. }
  95. void leftz()
  96. {
  97.   digitalWrite(motor2PWMPin, HIGH);digitalWrite(motor2Polarity1, HIGH);digitalWrite(motor2Polarity2, LOW);
  98. }
  99. void leftf()
  100. {
  101.   digitalWrite(motor2PWMPin, HIGH);digitalWrite(motor2Polarity1, LOW);digitalWrite(motor2Polarity2, HIGH);
  102. }
  103. void st()//电机停
  104. {
  105.   digitalWrite(motor1PWMPin, HIGH);digitalWrite(motor1Polarity1, LOW);digitalWrite(motor1Polarity2, LOW);
  106.   digitalWrite(motor2PWMPin, HIGH);digitalWrite(motor2Polarity1, LOW);digitalWrite(motor2Polarity2, LOW);
  107. }
  108. void blue()//蓝牙
  109. {
  110.   if (Serial.available() > 0) {
  111.       val = Serial.read();
  112.      /* if(val == 'A') {
  113.         Serial.println(angle_x); //jiaodu
  114.       }*/
  115.       if(val == 'z') {
  116.        rightz();
  117.       }
  118.       if(val == 'x') {
  119.       rightf();
  120.       }
  121.       if(val == 'c') {
  122.        leftz();
  123.       }
  124.       if(val == 'v') {
  125.        leftf();
  126.       }
  127.       if(val == 'b') {
  128.        st();
  129.       }
  130. }}
  131. void loop()
  132. {
  133.   t = millis();
  134.   
  135.   MPU6050_ReadData();
  136.    
  137.   angle_x_gyro = (gyro_x_scalled*((float)dt/1000)+angle_x);
  138.   angle_y_gyro = (gyro_y_scalled*((float)dt/1000)+angle_y);
  139.   angle_z_gyro = (gyro_z_scalled*((float)dt/1000)+angle_z);
  140.   angle_z_accel = atan(accel_z_scalled/(sqrt(accel_y_scalled*accel_y_scalled+accel_x_scalled*accel_x_scalled)))*(float)rad2degree;
  141.   angle_y_accel = -atan(accel_x_scalled/(sqrt(accel_y_scalled*accel_y_scalled+accel_z_scalled*accel_z_scalled)))*(float)rad2degree;
  142.   angle_x_accel = atan(accel_y_scalled/(sqrt(accel_x_scalled*accel_x_scalled+accel_z_scalled*accel_z_scalled)))*(float)rad2degree;
  143.   angle_x = Filter_gain*angle_x_gyro+(1-Filter_gain)*angle_x_accel;
  144.   angle_y = Filter_gain*angle_y_gyro+(1-Filter_gain)*angle_y_accel;
  145.   angle_z = Filter_gain*angle_z_gyro+(1-Filter_gain)*angle_z_accel;
  146.    
  147.   digitalWrite(motor1PWMPin, HIGH);
  148.   digitalWrite(motor2PWMPin, HIGH);
  149. Serial.print("\n");Serial.print("    ");Serial.print("angle_x=");  Serial.print(angle_x);Serial.print("  ");Serial.print("angle_y=");Serial.print(angle_y);Serial.print("  ");Serial.print("angle_z=");Serial.print(angle_z);
  150. Serial.print("____");           //串口输出
  151.    
  152.   // change direction is very important   平衡
  153.   if(angle_x>0)
  154.   {
  155.     myPID.SetControllerDirection(REVERSE);
  156.      
  157.     // set enablePin of motor 1 high so that motor 1 can turn on
  158.     digitalWrite(motor1Polarity1, HIGH);
  159.     digitalWrite(motor1Polarity2, LOW);
  160.     // set enablePin of motor 2 high so that motor 2 can turn on  
  161.     digitalWrite(motor2Polarity1, HIGH);
  162.     digitalWrite(motor2Polarity2, LOW);
  163.   }
  164.   else
  165.   {
  166.     myPID.SetControllerDirection(DIRECT);
  167.     // set enablePin of motor 1 high so that motor 1 can turn on
  168.     digitalWrite(motor1Polarity1, LOW);
  169.     digitalWrite(motor1Polarity2, HIGH);
  170.     // set enablePin of motor 2 high so that motor 2 can turn on  
  171.     digitalWrite(motor2Polarity1, LOW);
  172.     digitalWrite(motor2Polarity2, HIGH);
  173.   }
  174.    
  175.   Input = angle_x;
  176.   Serial.print("Input=");Serial.print(Input);Serial.print("____");
  177.    
  178.   myPID.Compute();
  179.   Serial.print("Output=");Serial.print(Output);Serial.print("____");                        Output 怎么会是0????
  180.    
  181.   analogWrite(motor1PWMPin, Output);
  182.   analogWrite(motor2PWMPin, Output);
  183.   
  184.   Serial.print("Setpoint=");Serial.print(Setpoint); Serial.print("\t");
  185.   Serial.print("left=");Serial.print(lefta);Serial.print("  ");Serial.print(leftone); Serial.print("\t");
  186.   Serial.print("right=");Serial.print(righta);Serial.print("  ");Serial.print(rightone); Serial.print("\t");   //串口输出
  187.    blue();//蓝牙
  188.    
  189.    if(rightone==1) //转动1圈标志
  190.        {
  191.          rightone=0;   
  192.          st();   // 停止转动
  193.        }
  194.       
  195.    
  196.   while((millis()-t) < dt)
  197.   {
  198.     // Do nothing
  199.   }
复制代码

平衡小车图5


创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(7)
诩
蛮厉害的
DFBJFz5siXP
DFBJFz5siXP
厉害啊 我到现在还是搞不明白PDI
20060606
20060606
好创意赞一个
qq913622228180
qq913622228180
这个东西有点赞呀!!!!!
dsweiliang
dsweiliang
做个大型的,能载人的
qq815076543322
qq815076543322回复dsweiliang
你得赞助张禄 哈哈
qq815076543322
qq815076543322
张禄 你东西全了 也做一个
qq815076543322
qq815076543322回复丄帝De咗臂
我的懒性也越来越大
丄帝De咗臂
丄帝De咗臂
作者
回复qq815076543322
多谢鼓励,哈哈,可是我始终战胜不了我的惰性
virtualwiz
virtualwiz
沙发沙发~
曾经想做个超级超级小的平衡车来着:lol学习一下
丄帝De咗臂
丄帝De咗臂
作者
回复virtualwiz
超级超级小,到底是多小
- 没有更多了 -