极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 52547|回复: 17

ARDUINO+MPU6050+步进电机的自平衡小车

[复制链接]
发表于 2013-6-9 18:24:30 | 显示全部楼层 |阅读模式
5
本帖最后由 ANDOON 于 2013-6-9 20:12 编辑

先亮出我的程序,参看大神们的:

  1. /*****************====================================********************/
  2. //**************** 一阶互补滤波+ PID  + MPU6050********************/
  3. //************************************************************************//
  4. #include <Wire.h>
  5. #include <i2cdev.h>
  6. #include <MPU6050.h>
  7. #include <AFMotor.h>
  8. //*********************************************************/
  9. //*********************************************************/
  10. MPU6050 accelgyro;
  11. int16_t ax, ay, az;
  12. int16_t gx, gy, gz;

  13. //********************************************************/
  14. //*************************L293D**************************/
  15. // two stepper motors one on each port
  16. AF_Stepper motor1(200, 1);//LEFT
  17. AF_Stepper motor2(200, 2);//RIGHT

  18. #define Gry_offset 296//陀螺仪X轴的静态飘移。
  19. #define Gyr_Gain -0.00763//由陀螺仪X轴读数转换为角速度值,=1/131 敏感比例因子131、65.5、32.8、16.4 LSB/s,向前方向与X轴为反方向,故乘以-1  
  20. #define ACC_Gain 0.000061//由读数转换为加速度值,=1/16384  Sensitivity Scale Factor 16384、8192、4096、2048 LSB/g
  21. #define pi 3.1415926
  22. #define K 0.715//一阶互补滤波权重取值,不知由来,可更改。

  23. /********** 互补滤波器参数 *********/
  24. unsigned long now ;
  25. unsigned long preTime = 0;
  26. float angleG = 0;

  27. /*********** PID控制器参数 *********/
  28. unsigned long lastTime;           // 前次时间
  29. float ITerm, lastInput;    // 积分项、前次输入
  30. float Output = 0.0;        // PID输出值
  31. float LOutput,ROutput;

  32. float LSpeed_Need=0.0,RSpeed_Need=0.0;// 转弯设置

  33. void setup(){
  34.   Wire.begin();
  35.   Serial.begin(38400);
  36.   accelgyro.initialize();//MPU6050初始化。
  37.   motor1.setSpeed(10);
  38.   motor2.setSpeed(10);
  39. }
  40. void loop(){
  41.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);//读取六轴数值
  42.   float Y_Accelerometer = ay * ACC_Gain;        //转换为向前的加速度(g),为负值
  43.   float Z_Accelerometer = az * ACC_Gain;        //转换为向下的加速度(g)
  44.   float angleA= atan(Y_Accelerometer/ Z_Accelerometer)* (-180)/ pi;//加速度仪,反正切获得弧度值,乘以180度/pi
  45.                                                                    //获得角度值,乘以-1得正值
  46. ANGLE_1();                                                //一阶互补滤波后的输出倾斜角度
  47. if (abs(angleA)<45) {  // 角度小于45度 运行程序
  48.       PIDD();                                             //PID控制器
  49.       DISTAN();                                        //左右电机步进距离输出
  50.   }
  51.    else {      // 角度大于45度 停止PWM输出
  52.       motor1.release();
  53.           motor2.release();
  54.         }
  55.    Serial.print(angleG); Serial.print("\t");
  56.    Serial.println(Output);
  57. }

  58.   //*********************************************************************/
  59.   //*************angleG= 一阶互补滤波后的输出倾斜角度(o)**********************/
  60. void ANGLE_1()
  61. {
  62.   now = millis();//当前时间(ms)
  63.   float dt = (now - preTime) / 1000.0;//微分时间(s)
  64.   preTime = now;//上一次采样时间(ms)                                                            
  65.   float gx_revised = gx + Gry_offset;//陀螺仪x轴静态时修正后的角速度读数,向前为负值
  66.   float omega= Gyr_Gain* gx_revised;//陀螺仪,转换为向前的角速度(o/s),Gyr_Gain取负,故负负得正
  67.   float angle_dt = omega * dt;//角度的单次积分值
  68.   //angleG+= angle_dt;//陀螺仪,积分获得角度值
  69.   angleG+= (Gyr_Gain * (gx + Gry_offset)) * dt;
  70.   float A= K/ (K+ dt);//陀螺仪的权值
  71.   angleG= A* (angleG+ omega* dt)+ (1-A)* angleA;//一阶互补滤波后的输出角度(o)
  72. }
  73.   //************************PID控制器*************************************/
  74. //*************步进电机根据倾斜程度调整输出距离***************************/
  75. //************左电机输出距离LOutput**************************************/
  76. //************右电机输出距离ROutput**************************************/
  77.   //********************************************************************/
  78. void PIDD(){
  79.    

  80.   }
  81. //**********************左右电机步进距离输出******************************/
  82. //***************************************************************/
  83. void DISTAN(){
  84.     stepper1.setMaxSpeed(300.0);
  85.     stepper1.setAcceleration(100.0);
  86.     stepper1.moveTo(LOutput);
  87.    
  88.     stepper2.setMaxSpeed(300.0);
  89.     stepper2.setAcceleration(100.0);
  90.     stepper2.moveTo(ROutput);
  91.    
  92.     stepper1.run();
  93.     stepper2.run();
  94. }
复制代码

望大神们帮忙修改PID控制和步进电机控制程序,小弟谢谢了。

回复

使用道具 举报

 楼主| 发表于 2013-6-9 18:25:46 | 显示全部楼层
电机驱动是L293D模块。
回复

使用道具 举报

发表于 2013-6-9 19:29:05 | 显示全部楼层
那平衡怎么和前进结合的???
回复

使用道具 举报

发表于 2013-6-9 19:35:03 | 显示全部楼层
很复杂啊,看不懂==。
把这些东西弄成一个库该多好
回复

使用道具 举报

 楼主| 发表于 2013-6-9 19:39:32 | 显示全部楼层
学慧放弃 发表于 2013-6-9 19:29
那平衡怎么和前进结合的???

//************************PID控制器*************************************/
//*************步进电机根据倾斜程度调整输出步进距离***************************/
//************左电机输出距离LOutput**************************************/
//************右电机输出距离ROutput**************************************/
   //********************************************************************/
void PIDD(){
     

  }
//**********************左右电机步进距离输出******************************/
//***************************************************************/
void DISTAN(){
     stepper1.setMaxSpeed(300.0);
     stepper1.setAcceleration(100.0);
     stepper1.moveTo(LOutput);
     
    stepper2.setMaxSpeed(300.0);
     stepper2.setAcceleration(100.0);
     stepper2.moveTo(ROutput);
     
    stepper1.run();
     stepper2.run();
}
回复

使用道具 举报

发表于 2013-6-9 19:47:20 | 显示全部楼层
ANDOON 发表于 2013-6-9 19:39
//************************PID控制器*************************************/
//*************步进电机 ...

喔,你那小车平衡性能好不???不是说陀螺仪算法还是有很大误差吗??
回复

使用道具 举报

 楼主| 发表于 2013-6-9 19:58:01 | 显示全部楼层
学慧放弃 发表于 2013-6-9 19:47
喔,你那小车平衡性能好不???不是说陀螺仪算法还是有很大误差吗??

误差不大。。不会控制它平衡,不会算应该让小车步进多少,才能平衡。
回复

使用道具 举报

发表于 2013-6-9 21:05:04 | 显示全部楼层
ANDOON 发表于 2013-6-9 19:58
误差不大。。不会控制它平衡,不会算应该让小车步进多少,才能平衡。

你可以参考德国四轴的算法看看
回复

使用道具 举报

发表于 2013-8-17 16:24:47 | 显示全部楼层
步进电机做不了平衡车吧?
回复

使用道具 举报

 楼主| 发表于 2013-9-1 21:38:47 | 显示全部楼层
L╃→煌/xin 发表于 2013-8-17 16:24
步进电机做不了平衡车吧?

基于Cortex-M4与步进电机下两轮自平衡小车的移动控制
http://www.amobbs.com/thread-5531409-1-1.html
回复

使用道具 举报

发表于 2013-9-1 22:40:12 | 显示全部楼层
同感,我也觉得步进电机跑起来真的很慢啊。
回复

使用道具 举报

发表于 2013-9-1 23:16:39 | 显示全部楼层
第一次见到有人用步进电机做平衡车
回复

使用道具 举报

 楼主| 发表于 2013-9-2 13:04:13 | 显示全部楼层
本帖最后由 ANDOON 于 2013-9-2 13:07 编辑
  1. /*****************====================================********************/
  2. //**************** 一阶互补滤波+ PID  + MPU6050********************/
  3. //************************************************************************//
  4. #include <Wire.h>
  5. #include <i2cdev.h>
  6. #include <MPU6050.h>
  7. //*********************************************************/
  8. //*********************************************************/
  9. MPU6050 accelgyro;
  10. int16_t ax, ay, az;
  11. int16_t gx, gy, gz;

  12. //********************************************************/
  13. //*************************MOTOR**************************/
  14. // Define two steppers and the pins they will use
  15. int dirPin_1 = 8;
  16. int stepperPin_1 = 9;
  17. int dirPin_2 = 6;
  18. int stepperPin_2 = 7;


  19. #define Gry_offset 296//陀螺仪X轴的静态飘移。
  20. #define Gyr_Gain -0.00763//由陀螺仪X轴读数转换为角速度值,=1/131 敏感比例因子131、65.5、32.8、16.4 LSB/s,向前方向与X轴为反方向,故乘以-1  
  21. #define ACC_Gain 0.000061//由读数转换为加速度值,=1/16384  Sensitivity Scale Factor 16384、8192、4096、2048 LSB/g
  22. #define pi 3.1415926
  23. #define K 0.715//一阶互补滤波权重取值,不知由来,可更改。

  24. /********** 互补滤波器参数 *********/
  25. unsigned long now ;
  26. unsigned long preTime = 0;
  27. float angleG = 0;

  28. /*********** PID控制器参数 *********/
  29. [color=Red]unsigned long lastTime = 0;           // 前次时间
  30. float ITerm = 0.0, lastInput = 0.0;    // 积分项、前次输入
  31. float Output = 0.0;        // PID输出值
  32. [/color]float LOutput,ROutput;

  33. float LSpeed_Need=0.0,RSpeed_Need=0.0;// 转弯设置

  34. void setup(){
  35.   Wire.begin();
  36.   Serial.begin(38400);
  37.   accelgyro.initialize();//MPU6050初始化。
  38.   pinMode(dirPin_1, OUTPUT);
  39.   pinMode(stepperPin_1, OUTPUT);
  40.   pinMode(dirPin_2, OUTPUT);
  41.   pinMode(stepperPin_2, OUTPUT);
  42. }
  43. void loop(){
  44.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);//读取六轴数值
  45.   float Y_Accelerometer = ay * ACC_Gain;//转换为向前的加速度(g),为负值
  46.   float Z_Accelerometer = az * ACC_Gain;//转换为向下的加速度(g)
  47.   float angleA= atan(Y_Accelerometer/ Z_Accelerometer)* (-180)/ pi;//加速度仪,反正切获得弧度值,乘以180度/pi
  48.                                                                    //获得角度值,乘以-1得正值
  49.   now = millis();//当前时间(ms)
  50.   float dt = (now - preTime) / 1000.0;//微分时间(s)
  51.   preTime = now;//上一次采样时间(ms)                                                            
  52.   float gx_revised = gx + Gry_offset;//陀螺仪x轴静态时修正后的角速度读数,向前为负值
  53.   float omega= Gyr_Gain* gx_revised;//陀螺仪,转换为向前的角速度(o/s),Gyr_Gain取负,故负负得正
  54.   float angle_dt = omega * dt;//角度的单次积分值
  55.   //angleG+= angle_dt;//陀螺仪,积分获得角度值
  56.   angleG+= (Gyr_Gain * (gx + Gry_offset)) * dt;
  57.   float A= K/ (K+ dt);//陀螺仪的权值
  58.   angleG= A* (angleG+ omega* dt)+ (1-A)* angleA;//一阶互补滤波后的输出角度(o)
  59. //********************************************************************
  60. //*********************************************************************
  61.   if (abs(angleG)<45) {    // 角度小于45度 运行程序
  62.       
  63.       PIDD();
  64.       PWMB();
  65.    }
  66.    Serial.print(angleG); Serial.print("\t");
  67.    Serial.println(Output);
  68. }
  69.   //*********************************************************************/
  70.   //********************************************************************/
  71.   /**********=================PID控制器====================*************/
  72.   //********************************************************************/
  73. void PIDD(){
  74.     now = millis();                                         // 当前时间(ms)
  75.     float TimeChange = (now - lastTime) / 1000.0;               // 采样时间(s)
  76.     float Kp = 10.0, Ki = 0.23, Kd = 0.0;                    // 比例系数、积分系数、微分系数
  77.     float SampleTime = 0.1;                                 // 采样时间(s)
  78.     float Setpoint =-2.0;                                  // 设定目标值(degree)
  79.     //float outMin = -400.0, outMax = +400.0;                   // 输出上限、输出下限
  80.     if(TimeChange >= SampleTime) {                              // 到达预定采样时间时
  81.         float Input = angleG;                              // 输入赋值
  82.         float error = Setpoint - Input;                     // 偏差值
  83.         ITerm+= (Ki * error * TimeChange);                      // 计算积分项
  84.        // ITerm = constrain(ITerm, outMin, outMax);           // 限定值域
  85.         float DTerm = Kd * (Input - lastInput) / TimeChange;    // 计算微分项
  86.         Output = Kp * error + ITerm + DTerm;                // 计算输出值
  87.        // Output = constrain(Output, outMin, outMax);         // 限定值域
  88.         LOutput=Output+RSpeed_Need;                         //左电机
  89.         ROutput=Output-RSpeed_Need;                         //右电机
  90.         lastInput = Input;                                  // 记录输入值
  91.         lastTime = now;                                     // 记录本次时间
  92.     }
  93.   }
  94. //**********************PWM调速输出******************************/
  95. //***************************************************************/
  96. void PWMB(){
  97.   if(Output > 0){
  98.     step_forwards(Output);
  99.   }
  100.   if (Output < 0){
  101.     step_backwards(abs(Output));
  102.   }
  103. }
  104. //**********************电机运转控制******************************/
  105. //***************************************************************/
  106. void step_forwards(int speeds){
  107.     digitalWrite(dirPin_1,0);
  108.     digitalWrite(dirPin_2,1);
  109.    
  110.     digitalWrite(stepperPin_1, HIGH);
  111.     digitalWrite(stepperPin_2, HIGH);
  112.     delayMicroseconds(speeds);
  113.     digitalWrite(stepperPin_1, LOW);
  114.     digitalWrite(stepperPin_2, LOW);
  115.     delayMicroseconds(speeds);
  116.   }
  117. [color=Red]  void step_backwards(int speeds){
  118.     digitalWrite(dirPin_1,1);
  119.     digitalWrite(dirPin_2,0);
  120.    
  121.     digitalWrite(stepperPin_1, HIGH);
  122.     digitalWrite(stepperPin_2, HIGH);
  123.     delayMicroseconds(speeds);
  124.     digitalWrite(stepperPin_1, LOW);
  125.     digitalWrite(stepperPin_2, LOW);
  126.     delayMicroseconds(speeds);[/color]
  127.   }
复制代码
最终能够稳定站立的程序,使用LV8731驱动步进电机,L293输出电流太小,容易热。
回复

使用道具 举报

 楼主| 发表于 2013-9-2 13:08:33 | 显示全部楼层
dalywan 发表于 2013-9-1 22:40
同感,我也觉得步进电机跑起来真的很慢啊。

基于Cortex-M4与步进电机下两轮自平衡小车的移动控制
http://www.amobbs.com/thread-5531409-1-1.html
回复

使用道具 举报

 楼主| 发表于 2013-9-2 13:08:54 | 显示全部楼层
tangmao48 发表于 2013-9-1 23:16
第一次见到有人用步进电机做平衡车

基于Cortex-M4与步进电机下两轮自平衡小车的移动控制
http://www.amobbs.com/thread-5531409-1-1.html
回复

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-4 03:47 , Processed in 0.060117 second(s), 20 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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