极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 24578|回复: 10

arduino做的平衡车

[复制链接]
发表于 2014-8-14 23:26:20 | 显示全部楼层 |阅读模式
本帖最后由 ypw 于 2014-8-14 23:27 编辑



  1. #include <I2Cdev.h>
  2. #include <MPU6050.h>
  3. #include <Wire.h>

  4. #define X_pianyi -6
  5. float P = 40, D = 0.025;
  6. //PID的P和D的值
  7. //====================
  8. MPU6050 accelgyro;
  9. int DIR1 = 7, PWM1 = 6, PWM2 = 5, DIR2 = 4;
  10. //dir代表方向,pwm代表速度
  11. int16_t ax, ay, az;
  12. int16_t gx, gy, gz; //存储原始数据
  13. float aax, aay, aaz, ggx, ggy, ggz; //存储量化后的数据
  14. float Ax, Ay, Az; //单位 g(9.8m/s^2)
  15. float Gx, Gy, Gz; //单位 °/s
  16. float Angel_accX, Angel_accY, Angel_accZ; //存储加速度计算出的角度
  17. long LastTime, NowTime, TimeSpan; //用来对角速度积分的
  18. #define LED_PIN 13//LED

  19. bool blinkState = false;
  20. void set(int a)
  21. {
  22.   analogWrite(PWM2, abs(a));
  23.   if (a > 0)
  24.   {
  25.     digitalWrite(DIR1, HIGH);
  26.     digitalWrite(DIR2, HIGH);
  27.   }
  28.   else if (a < 0) {
  29.     digitalWrite(DIR1, LOW);
  30.     digitalWrite(DIR2, LOW);
  31.   }
  32.   else {
  33.     digitalWrite(PWM1, LOW);
  34.     digitalWrite(PWM2, LOW);
  35.   }
  36. }
  37. void setup()//MPU6050的设置都采用了默认值,请参看库文件
  38. {
  39.   digitalWrite(PWM1, LOW);
  40.   digitalWrite(PWM2, LOW);
  41.   pinMode(DIR1, OUTPUT);
  42.   pinMode(DIR2, OUTPUT);
  43.   pinMode(PWM1, OUTPUT);
  44.   pinMode(PWM2, OUTPUT);
  45.   digitalWrite(DIR1, LOW);
  46.   digitalWrite(DIR2, LOW);
  47.   pinMode(LED_PIN, OUTPUT);
  48.   delay(500);
  49.   Wire.begin();
  50.   Serial.begin(57600);
  51.   Serial.println("Initializing I2C device.....");
  52.   accelgyro.initialize();
  53.   Serial.println("Testing device connections...");
  54.   Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failure");
  55.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  56.   Ax = ax / 16384.00;
  57.   Ay = ay / 16384.00;
  58.   Az = az / 16384.00;
  59.   Angel_accZ = atan(Az / sqrt(Ax * Ax + Ay * Ay)) * 180 / 3.14;
  60.   Gx = -Angel_accZ;
  61.   Serial.println(Gx);
  62.   if (!(Gx < 180 && Gx > -180))setup();
  63.   digitalWrite(13,1);
  64. }
  65. void loop()
  66. {
  67.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); //获取三个轴的加速度和角速度
  68.   //======一下三行是对加速度进行量化,得出单位为g的加速度值
  69.   Ax = ax / 16384.00;
  70.   Ay = ay / 16384.00;
  71.   Az = az / 16384.00;
  72.   //==========以下三行是用加速度计算三个轴和水平面坐标系之间的夹角
  73.   Angel_accX = atan(Ax / sqrt(Az * Az + Ay * Ay)) * 180 / 3.14;
  74.   Angel_accY = atan(Ay / sqrt(Ax * Ax + Az * Az)) * 180 / 3.14;
  75.   Angel_accZ = atan(Az / sqrt(Ax * Ax + Ay * Ay)) * 180 / 3.14;
  76.   //==========以下三行是对角速度做量化==========
  77.   ggx = gx / 131.00;
  78.   ggy = gy / 131.00;
  79.   ggz = gz / 131.00;
  80.   //===============以下是对角度进行积分处理====== ==========
  81.   NowTime = millis(); //获取当前程序运行的毫秒数
  82.   TimeSpan = NowTime - LastTime; //积分时间这样算不是很严谨
  83.   //下面是互补滤波算法
  84.   Gx = (Gx + ggx * TimeSpan / 1000)*0.995-0.005*Angel_accZ;
  85.   LastTime = NowTime;
  86.   int spd;
  87.   spd = (Gx - X_pianyi) * P - ggx * D;
  88.   if (spd < 250 && spd > -250)set(spd);
  89.   else {
  90.     set(0);
  91.   }
  92.   //==============================
  93.   Serial.print("Ax=");
  94.   Serial.print(Gx);
  95.   Serial.print("\tWx=");
  96.   Serial.print(ggx);
  97.   Serial.print("\tspd=");
  98.   Serial.println(spd);
  99. }
复制代码
回复

使用道具 举报

发表于 2014-8-15 09:07:54 | 显示全部楼层
做例子不错。我昨儿个也想到这种积分方法,我觉得中断影响MPU6050,一开电机那个角度就飘到爪哇国去了
回复 支持 反对

使用道具 举报

发表于 2014-8-15 09:36:43 | 显示全部楼层
这个程序看上去很精练,不知道效果如何呢?
回复 支持 反对

使用道具 举报

发表于 2014-8-15 11:16:15 | 显示全部楼层
视频看的 挺好的。

回复 支持 反对

使用道具 举报

发表于 2014-8-15 16:24:20 | 显示全部楼层
这个不错                              
回复 支持 反对

使用道具 举报

发表于 2014-8-23 09:45:25 | 显示全部楼层
电机用码盘没有呀?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-25 15:54:27 | 显示全部楼层
PLA 发表于 2014-8-23 09:45
电机用码盘没有呀?

没有,直接转圈平衡的
回复 支持 反对

使用道具 举报

发表于 2014-8-25 16:34:15 | 显示全部楼层
楼主能看看我的这篇帖子么?
http://www.arduino.cn/thread-7049-1-1.html

我想做一个两轮自平衡小车。现在的问题是单独用MPU6050,可以得到角度,单独用L293,可以控制电机旋转,但是当两者一结合,电机就只向一个方向旋转。

我觉得是我用的那个老外的#include "gyro_accel.h"类有问题,链接如下:
http://hobbylogs.me.pn/?p=47
和控制电机冲突。

我的你的获取MPU6050的角度的方法好像很简单,但是我看不明白,楼主能给出一个单独使用MPU6040获取角度的程序么?你使用了滤波算法么?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-8-27 12:52:29 | 显示全部楼层
liangquan 发表于 2014-8-25 16:34
楼主能看看我的这篇帖子么?
http://www.arduino.cn/thread-7049-1-1.html

我直接用了MPU6050的库获取了加速度和角速度,然后用互补滤波算法得到了角度。

Gx = (Gx + ggx * TimeSpan / 1000)*0.995-0.005*Angel_accZ;

然后用PID控制
spd = (Gx - X_pianyi) * P - ggx * D;
回复 支持 反对

使用道具 举报

发表于 2014-8-27 14:03:01 | 显示全部楼层
ypw 发表于 2014-8-27 12:52
我直接用了MPU6050的库获取了加速度和角速度,然后用互补滤波算法得到了角度。

Gx = (Gx + ggx * Time ...

楼主能看看我的这篇帖子么?
http://www.geek-workshop.com/thread-10818-1-1.html

我现在的问题是:只要Arduino和MPU一结合,就不能按照我的想法去运行。您看看我的电路图有毛病么?您碰到过类似问题么?

我用11#楼的做演示,也不一定成功,这是怎么回事?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-10-1 12:13:30 | 显示全部楼层
liangquan 发表于 2014-8-27 14:03
楼主能看看我的这篇帖子么?
http://www.geek-workshop.com/thread-10818-1-1.html

我的电机和单片机是分开的电源,单片机用移动电源5V供电,功耗很低,电机用7.2V的镍氢电池供电,飞思卡尔车模的标配,由于电机的电源跟单片机是不一样的,所以没有这个不工作的问题.至于你那个具体是什么问题我也没看出来.
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 12:12 , Processed in 0.042930 second(s), 24 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表