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

news/2024/11/8 22:34:02/

1. 功能说明

在双轮小车上安装一个六轴陀螺仪传感器,本文示例将实现双轮小车自主平衡功能。

 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)下载到主控板:

【程序源代码资料内容详见 双轮平衡车-自平衡】

/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-04-25 https://www.robotway.com/------------------------------*//*  功能:自平衡小车接线:陀螺仪传感器(GND、VCC、RX、TX)接在扩展板的( Gnd、Vcc(3.3v)、RX、TX);直流电机分别接在(5,6),(9,10)*/#include<Math.h>#define Gyroscope_left_LimitAngle_Y  -0.05  //读取到陀螺仪 Y 轴向前的极限数值#define Gyroscope_Right_LimitAngle_Y  1.13  //读取到陀螺仪 Y 轴向后的极限数值#define Gyroscope_Middle_LimitAngle_Y  0.74  //读取到陀螺仪 Y 轴平放时的数值#define Motor_Pin_Count 4/*由于直流电机的物理差异,左右电机的速度值不同;需要先微调两电机的pwm值,保证小车能走直线(否则会出现小车原地打转)*/#define left_Motor_Speed_Init 60  //左侧电机的初始速度(0-255)#define right_Motor_Speed_Init 70  //右侧电机的初始速度(0-255)#define Motor_Speed_Mix 0  //电机速度增量最小值#define Motor_Speed_Max 20  //电机速度增量最大值unsigned char Re_buf[11],counter=0; //存储陀螺仪数据的变量unsigned char sign=0;  //定义是否接收到陀螺仪数据的标志位float a[3];  //用于存储x、y、z三轴的角速度包数值int motor_pin[4] = {5,6,9,10};//定义电机引脚int map_to_int[3] = {0,0,0};  //用于存储Y轴向左偏、向右偏、平放的数值enum{Forward = 1,Back,Stop};  //定义电机前进、后退、停止三种状态void setup(){delay(1000);Serial.begin(115200);//打开串口,并设置波特率为115200for(int i=0;i<Motor_Pin_Count;i++){pinMode(motor_pin[i],INPUT);  //将电机的四个引脚设置为输出模式}map_to_int[0] = Gyroscope_left_LimitAngle_Y*100;  //重新赋予陀螺仪 Y 轴向前的极限数值map_to_int[1] = Gyroscope_Right_LimitAngle_Y*100;  //重新赋予陀螺仪 Y 轴向后的极限数值map_to_int[2] = Gyroscope_Middle_LimitAngle_Y*100; //重新赋予陀螺仪 Y 轴平放时的数值}void loop(){Get_gyroscope_And_Control();//读取陀螺仪参数,并判断平衡小车前倾、后仰或者是平放状态}//实时读取陀螺仪发送的数据(serialEvent()函数会自动运行)void serialEvent() {  while (Serial.available()) {Re_buf[counter]=(unsigned char)Serial.read();if(counter==0&&Re_buf[0]!=0x55) return;  //第0号数据不是帧头  counter++;  if(counter==11)  //接收到11个数据{  counter=0;  //重新赋值,准备下一帧数据的接收sign=1;}  }}

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

/*------------------------------------------------------------------------------------版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.Distributed under MIT license.See file LICENSE for detail or copy athttps://opensource.org/licenses/MITby 机器谱 2023-04-25 https://www.robotway.com/------------------------------*/void Get_gyroscope_And_Control()//读取陀螺仪参数,并判断平衡小车前倾、后仰或者是平放状态{int gyroscope_acc_data= 0;int map_data= 0;if(sign){  sign=0;if(Re_buf[0]==0x55)  //检查帧头{  switch(Re_buf [1]){case 0x51:{a[0] = (short(Re_buf [3]<<8| Re_buf [2]))/32768.0*16;a[1] = (short(Re_buf [5]<<8| Re_buf [4]))/32768.0*16;a[2] = (short(Re_buf [7]<<8| Re_buf [6]))/32768.0*16;//把陀螺仪的加速度包的Y轴数据转换为直流电机的速度map_data = fabs(a[1]) * 100;  //fabs()取浮点数的绝对值if( (map_data >= (map_to_int[2]-10)) && (map_data <= (map_to_int[2]+10)) ){//小车处于平衡态Motor_State(Stop,0,0);  }else if( (map_data < (map_to_int[2]-10)) && (map_data >= map_to_int[0]) ){/*当小车前倾,自行调整至平衡假如现在获取到陀螺仪数据0.50,转换为50并进行映射为直流的pwm值过程Motor_State(Forward,60+map(50,64,5,0,20), 70+map(50,64,5,0,20))*/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) );}else if( (map_data <= map_to_int[1]) && (map_data > (map_to_int[2]+10)) ){//当小车后仰,自行调整至平衡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) );}  }break;}}}}void Motor_State(int _mode, int _left, int _right)//电机状态函数{switch(_mode){case Forward: {analogWrite(motor_pin[0],_right);analogWrite(motor_pin[1],0);analogWrite(motor_pin[2],_left);analogWrite(motor_pin[3],0);}break;case Back:  {analogWrite(motor_pin[1],_right);analogWrite(motor_pin[0],0);analogWrite(motor_pin[3],_left);analogWrite(motor_pin[2],0);}break;case Stop:  {analogWrite(motor_pin[0],0);analogWrite(motor_pin[1],0);analogWrite(motor_pin[2],0);analogWrite(motor_pin[3],0);}break;}}


http://www.ppmy.cn/news/85152.html

相关文章

方正书版10.0快捷键

方正书版10.0快捷键 一、字符工具条快捷键 1、注解括弧对 ctrlshift[ 2、上标 ctrlshiftI 3、下标 ctrlshiftM 4、数学态切换符 ctrlshift; 5、转字体符 ctrlshift’ 6、页码目录替换符 ctrlshift? 7、盒组括弧 ctrlshift] 8、盘外符括弧 ctrlshift( 9、转义…

一个非系统工程师所关心的——Android开机流程

一、Loader层 1. Boot ROM: 上电后&#xff0c;BootRom会被激活&#xff0c;引导芯片代码开始从预定义的地方&#xff08;固化在ROM&#xff09;开始执行&#xff0c;然后加载引导程序到RAM。 2. Boot Loader引导程序 Android是基于Linux系统的&#xff0c;它没有BIO…

【Axure教程】通过文本框维护下拉列表选项

下拉列表&#xff08;Dropdown List&#xff09;是一种常见的用户界面元素&#xff0c;用于提供一组选项供用户选择。它通常以一个展开的列表形式出现&#xff0c;用户可以点击或选择列表中的一个选项。一般来说&#xff0c;他的选项值是由系统代码组成的&#xff0c;所以一般是…

JAVA LIST 根据对象元素去重

应用场景&#xff1a;在开发中过程中 会存在根据List集合中的对象一个或者多个元素进行去重 1&#xff1a;根据List集合中的对象一个元素进行去重 List<PurchaseHead> organizationPurchaseHeadList purchaseHeadList.stream().collect(Collectors.collectingAndThe…

uniapp前端图片布局时z-index出现的几个问题

目录 图片的z-index是怎么看的 一些规则: 图片没有z-index吗&#xff1f; 图片会优先覆盖其他元素吗&#xff1f; z-index失效 static elative、absolute或fixed的元素 元素的z-index覆盖子元素吗 图片的z-index是怎么看的 z-index属性用于控制元素的堆叠顺序,它只对定位…

进程控制

目录 进程创建 fork函数 写时拷贝 进程终止 进程退出场景 进程常见退出方法 进程等待 进程等待的必要性 进程等待的方法 wait方法 waitpid方法 获取子进程status 等待行为options 进程替换 各类程序替换函数的使用 命名理解 execl函数 execv函数 execlp函数…

利用PaddleOCR识别增值税发票平台验证码(开箱即用)

前言:全国增值税发票查验平台验证码没什么好说的,根据指定的颜色识别验证码中的文字,图片如下 下面直接讲解利用paddleocr识别的思路,为什么使用paddleocr,因为paddle中集成了较好的ocr文字识别模型,开箱即用即可,废话不多说,剑指主题,识别思路步骤如下 步骤如下 1、…

react表格行下载文件方法总结

一、前言 下载文件时&#xff0c;后台接口返回的响应体是文件流格式的&#xff0c;前端接收时如果不进行处理&#xff0c;就会无法正确下载文件&#xff08;有可能会直接打开文件等&#xff09;。 在此记录下react的表格行使用file-saver下载文件的方法。&#xff08;注意不同…