极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 2061|回复: 0

双轮平衡车实现自平衡功能

[复制链接]
发表于 2023-5-26 09:36:13 | 显示全部楼层 |阅读模式
本帖最后由 机器谱 于 2023-5-26 09:36 编辑

1. 功能说明
       在双轮小车上安装一个 六轴陀螺仪传感器【https://www.robotway.com/h-col-137.html】 ,本文示例将实现双轮小车自主平衡功能。


2. 电子硬件

       在这个示例中,我们采用了以下硬件,请大家参考:

主控板
Basra主控板(兼容Arduino Uno)
扩展板
Bigfish2.1扩展板
传感器
六轴陀螺仪
电池
7.4V锂电池

电路连接:
       ① 六轴陀螺仪传感器(GND、VCC、RX、TX)连接在Bigfish扩展板的Gnd、Vcc(3.3v)、RX、TX;
       ② 2个直流电机分别连在Bigfish扩展板的(5,6)、(9,10)。


3. 功能实现
       编程环境:Arduino 1.8.19
       实现思路:实现小车的自平衡。当人为去打破小车的平衡时,小车能够自行恢复到平衡状态。这里当俯视小车时,小车处于水平位置代表平衡状态;前倾或后仰等均为非平衡状态。

3.1 测试数据

      ① 需要先测出陀螺仪沿Y轴的状态数据。下表是本实验中测试出的实验数据,大家可参考格式,测试出自己的实验数据。

物料
测试数据‍‍
陀螺仪的加速度包Y轴数据
沿Y轴俯仰陀螺仪时,数据从(-0.05,1.13)逐渐增大;
陀螺仪平放时的值为0.74;

      ② 找准双轮小车的平衡状态(大家可尝试把锂电池安装在小车底部,让小车默认为平衡态)

3.2 示例程序
      将参考例程(Gyroscope_Control_Car.ino)下载到主控板:
  1. /*------------------------------------------------------------------------------------

  2. 版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

  3. Distributed under MIT license.See file LICENSE for detail or copy at

  4. https://opensource.org/licenses/MIT

  5. by 机器谱 2023-04-25 https://www.robotway.com/

  6. ------------------------------*/

  7. /*  

  8. 功能:自平衡小车

  9. 接线:陀螺仪传感器(GND、VCC、RX、TX)接在扩展板的( Gnd、Vcc(3.3v)、RX、TX);

  10. 直流电机分别接在(5,6),(9,10)

  11. */

  12. #include<Math.h>

  13. #define Gyroscope_left_LimitAngle_Y  -0.05  //读取到陀螺仪 Y 轴向前的极限数值

  14. #define Gyroscope_Right_LimitAngle_Y  1.13  //读取到陀螺仪 Y 轴向后的极限数值

  15. #define Gyroscope_Middle_LimitAngle_Y  0.74  //读取到陀螺仪 Y 轴平放时的数值

  16. #define Motor_Pin_Count 4


  17. /*

  18. 由于直流电机的物理差异,左右电机的速度值不同;

  19. 需要先微调两电机的pwm值,保证小车能走直线(否则会出现小车原地打转)

  20. */

  21. #define left_Motor_Speed_Init 60  //左侧电机的初始速度(0-255)

  22. #define right_Motor_Speed_Init 70  //右侧电机的初始速度(0-255)

  23. #define Motor_Speed_Mix 0  //电机速度增量最小值

  24. #define Motor_Speed_Max 20  //电机速度增量最大值


  25. unsigned char Re_buf[11],counter=0; //存储陀螺仪数据的变量

  26. unsigned char sign=0;  //定义是否接收到陀螺仪数据的标志位

  27. float a[3];  //用于存储x、y、z三轴的角速度包数值

  28. int motor_pin[4] = {5,6,9,10};//定义电机引脚

  29. int map_to_int[3] = {0,0,0};  //用于存储Y轴向左偏、向右偏、平放的数值

  30. enum{Forward = 1,Back,Stop};  //定义电机前进、后退、停止三种状态

  31. void setup()

  32. {

  33. delay(1000);Serial.begin(115200);//打开串口,并设置波特率为115200

  34. for(int i=0;i<Motor_Pin_Count;i++){

  35. pinMode(motor_pin[i],INPUT);  //将电机的四个引脚设置为输出模式

  36. }

  37. map_to_int[0] = Gyroscope_left_LimitAngle_Y*100;  //重新赋予陀螺仪 Y 轴向前的极限数值

  38. map_to_int[1] = Gyroscope_Right_LimitAngle_Y*100;  //重新赋予陀螺仪 Y 轴向后的极限数值

  39. map_to_int[2] = Gyroscope_Middle_LimitAngle_Y*100; //重新赋予陀螺仪 Y 轴平放时的数值

  40. }


  41. void loop()

  42. {

  43. Get_gyroscope_And_Control();//读取陀螺仪参数,并判断平衡小车前倾、后仰或者是平放状态

  44. }


  45. //实时读取陀螺仪发送的数据(serialEvent()函数会自动运行)

  46. void serialEvent() {  

  47. while (Serial.available()) {

  48. Re_buf[counter]=(unsigned char)Serial.read();

  49. if(counter==0&&Re_buf[0]!=0x55) return;  //第0号数据不是帧头  

  50. counter++;  

  51. if(counter==11)  //接收到11个数据

  52. {  

  53. counter=0;  //重新赋值,准备下一帧数据的接收

  54. sign=1;

  55. }  

  56. }

  57. }
复制代码

判断双轮小车前倾、后仰或者是平放状态的参考程序(Gyroscope_Device.ino)如下:
  1. /*------------------------------------------------------------------------------------

  2. 版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

  3. Distributed under MIT license.See file LICENSE for detail or copy at

  4. https://opensource.org/licenses/MIT

  5. by 机器谱 2023-04-25 https://www.robotway.com/

  6. ------------------------------*/

  7. void Get_gyroscope_And_Control()//读取陀螺仪参数,并判断平衡小车前倾、后仰或者是平放状态

  8. {

  9. int gyroscope_acc_data= 0;

  10. int map_data= 0;

  11. if(sign)

  12. {  

  13. sign=0;

  14. if(Re_buf[0]==0x55)  //检查帧头

  15. {  

  16. switch(Re_buf [1])

  17. {

  18. case 0x51:

  19. {

  20. a[0] = (short(Re_buf [3]<<8| Re_buf [2]))/32768.0*16;

  21. a[1] = (short(Re_buf [5]<<8| Re_buf [4]))/32768.0*16;

  22. a[2] = (short(Re_buf [7]<<8| Re_buf [6]))/32768.0*16;

  23. //把陀螺仪的加速度包的Y轴数据转换为直流电机的速度

  24. map_data = fabs(a[1]) * 100;  //fabs()取浮点数的绝对值

  25. if( (map_data >= (map_to_int[2]-10)) && (map_data <= (map_to_int[2]+10)) )

  26. {

  27. //小车处于平衡态

  28. Motor_State(Stop,0,0);  

  29. }

  30. else if( (map_data < (map_to_int[2]-10)) && (map_data >= map_to_int[0]) )

  31. {

  32. /*当小车前倾,自行调整至平衡

  33. 假如现在获取到陀螺仪数据0.50,转换为50并进行映射为直流的pwm值过程

  34. Motor_State(Forward,60+map(50,64,5,0,20), 70+map(50,64,5,0,20))

  35. */

  36. Motor_State(Forward,left_Motor_Speed_Init+map(map_data,(map_to_int[2]-10),map_to_int[0],Motor_Speed_Mix,Motor_Speed_Max),right_Motor_Speed_Init+map(map_data,(map_to_int[2]-10),map_to_int[0],Motor_Speed_Mix,Motor_Speed_Max) );

  37. }

  38. else if( (map_data <= map_to_int[1]) && (map_data > (map_to_int[2]+10)) )

  39. {

  40. //当小车后仰,自行调整至平衡

  41. Motor_State(Back,left_Motor_Speed_Init+map(map_data,(map_to_int[2]+10),map_to_int[1],Motor_Speed_Mix,Motor_Speed_Max),right_Motor_Speed_Init+map(map_data,(map_to_int[2]+10),map_to_int[1],Motor_Speed_Mix,Motor_Speed_Max) );

  42. }  

  43. }break;

  44. }

  45. }

  46. }

  47. }


  48. void Motor_State(int _mode, int _left, int _right)//电机状态函数

  49. {

  50. switch(_mode)

  51. {

  52. case Forward: {analogWrite(motor_pin[0],_right);analogWrite(motor_pin[1],0);analogWrite(motor_pin[2],_left);analogWrite(motor_pin[3],0);}break;

  53. case Back:  {analogWrite(motor_pin[1],_right);analogWrite(motor_pin[0],0);analogWrite(motor_pin[3],_left);analogWrite(motor_pin[2],0);}break;

  54. case Stop:  {analogWrite(motor_pin[0],0);analogWrite(motor_pin[1],0);analogWrite(motor_pin[2],0);analogWrite(motor_pin[3],0);}break;

  55. }

  56. }
复制代码

4. 资料下载
资料内容:自平衡-程序源代码
资料下载地址:https://www.robotway.com/h-col-207.html

想了解更多机器人开源项目资料请关注 机器谱网站 https://www.robotway.com

回复

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-4-24 21:11 , Processed in 0.043137 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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