STM32平衡车

这篇具有很好参考价值的文章主要介绍了STM32平衡车。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

0. 关于本项目

首先附上本项目的GitHub仓库

本项目使用STM32F103C8T6作为主控,Keil5开发,Mahony算法进行姿态解算的平衡车。项目中给出了MPU6050ICM20602ICM42605三种主流IMU的驱动。目前仅实现了直立平衡,在设计设加入了BlueTooth模块,手机遥控部分还在开发中(新建文件夹) (°ー°〃)

首先需要的前提知识有:

  • Keil5的使用
  • STM32有一定了解
  • 电机驱动的原理,使用

1. 硬件

  1.1 器件购买

要制作一台平衡小车,需要用到的硬件材料有:轮子、带编码器的直流电机、电机排线、面包板、杜邦线、STM32、稳压模块、蓝牙模块、电机驱动模块、陀螺仪模块、超声波模块、电池、底盘、螺栓、铜柱、固定轧带、开关等。下面是物料表:

类型 链接 数量
MG513P20_12V 电机 直流减速电机带光电霍尔编码器码盘测速 1
电池 2S锂电池及充电器 1
5V DCDC稳压 DCDC降压模块 12V转5V3A 1
LCD ST7789主控 240×240 1.3寸ips TFT显示屏ips液晶屏 1

其余器件见下表格

ID 名称 型号 数量
1 STM32最小系统板 STM32F103C8T6 1
2 电机驱动 TB6612FNG 1
3 陀螺仪 MPU6050或ICM42605、20602 1
4 蓝牙 HC-07 1
5 10uF钽电容 6.3V,3528,3.52.82.1mm 1
6 20uF钽电容 6.3V,3528,3.52.82.1mm 1
7 电机插座、排线 6P-2.54mm 10cm排线 2
8 T型头 航模电池T型头 1
9 AMS1117-3.3V AMS1117-3.3V贴片 1
10 开关 摇臂开关 2
11 铜柱 六角3mm 若干
12 扎带 3.6mm 若干

  1.2 PCB

目前是第一版,画的很菜,用到的都是插接件,线也布的很乱 (:3」∠)。后续还会更新PCB(计划换成贴片,体积会更小)
STM32平衡车
STM32平衡车

  1.3 车模

STM32平衡车

SolidWorks画的简单底板尺寸如图(mm),用3D打印机制造,源文件在学校电脑上,回学校了再上传。
STM32平衡车

2. 算法

  2.1 PID算法

  2.1.1 理论分析

该项目为使的小车平衡最主要的两个环就是直立环和速度环,通过叠加得到最终给电机的输出,这也是网上绝大多数的小车平衡控制方法。

  1. 我们先使用常规的速度负反馈算法想象一下。首先我们给定一个目标速度值,由于小车在直立控制的作用下,此时小车要向前倾斜以获取加速度,车轮需要往后运动,这样小车速度就会下降。因为是负反馈,速度下降之后,速度控制的偏差增大,小车往前倾斜的角度增大,如此反复,小车便会倒下。
  2. 为保证直立控制的优先级,我们把速度控制放在直立控制的前面,也就是速度控制调节的结果仅仅是改变直立控制的目标值。因为根据经验可知,小车的运行速度和小车的倾角是相关的。比如要提高小车向前行驶的速度,就需要增加小车向前倾斜的角度,倾斜角度加大之后,车轮在直立控制的作用下需要向前运动。因此直立环的Kp后面乘的值并不是当前角度-机械中值,而是一个我们速度的期望。(这个理解了很重要!!!!)

a 1 = K p ∗ ( θ − a 2 ) + K d ∗ θ ′ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ① 直 立 环 a_1=Kp*(\theta-a_2)+Kd*\theta' \qquad········································①直立环 a1=Kp(θa2)+Kdθ

a 2 = K p 1 ∗ E r r s p e e d + K i 1 ∗ ∑ E r r s p e e d   ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ② 速 度 环 a_2=Kp_1*Err_{speed}+Ki_1*\sum Err_{speed}\space \qquad·····························②速度环 a2=Kp1Errspeed+Ki1Errspeed 

合并一下就可以得到:

a = K p ∗ ( θ ) + K d ∗ θ ′ − K p [ k p 1 ∗ E r r s p e e d + k i 1 ∗ ∑ E r r s p e e d ] ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ③ 最 终 式 a=Kp*(\theta)+Kd*\theta'-Kp[kp_1*Err_{speed}+ki_1*\sum Err_{speed}] \qquad········③最终式 a=Kp(θ)+KdθKp[kp1Errspeed+ki1Errspeed]

因此在代码实现上我们就可以实现两个环的直接相加或相减,在TIM3定时器中10ms一个周期进行控制。

      Balance_PID_Result = Position_PID_Cal(&Balance_PID, imu.Roll + 0.3f);
      if (Time_GAP_20ms) Velocity_PID_Result = Position_PID_Cal(&Velocity_PID, Velocity);

      PID_Result = Balance_PID_Result + Velocity_PID_Result;
      Set_Motor_Speed(PID_Result, PID_Result);

  2.1.2 调参经验

根据上边的分析我们只需要分别调整直立环的Kp,kd和速度环的Kp,Ki

  1. 对于直立环的Kp,是调整最方便观察现象的,太小时小车没有足够的恢复力,太大时小车会在中值附近大幅震荡,调整到一个略微震荡的值即可
  2. 直立环的Kd作用是减小低频振荡,但Kd太大小车又会造成高频振动,从小到大增大Kd,直到小车出现小幅高频振荡
  3. 直立环调整结束后小车可以平衡,但受到扰动便会往一个方向疯跑,现在引入直立环
  4. 网上查到的资料对于速度环Ki = Kp/200 ,但在我的实际调整中最终确定了Ki = Kp/100,这个看自己小车了,可以先按照Ki = Kp/200去调
  5. 先将直立环Kp,Kd同时×0.8。调整速度环Kp,速度环Kp越大,小车便越不会出现向一个方向狂奔的情况(因为速度被速度环控住了),但会减弱直立环的控制效果,因此调整到一个车受到干扰会摇摇晃晃停下的一个状态。
  6. 摇摇晃晃的原因就是因为速度环Kp太大,回调速度环Kp,并且增大直立环Kd(想想Kd的作用是什么呢?)

以上就是我调参的经验,可以参考,最好可以理解原理再去上手实践。

  2.2 Mahony算法

参考一篇文章:基于Manony滤波算法的姿态解算

  2.2.1 IMU(以MPU6050举例)

MPU6050是一个集成了陀螺仪和加速度计的传感器,它能输出在直角坐标系下的x,y,z轴的角速度和加速度数据。

陀螺仪输出的格式为:绕x轴的旋转角速度,绕y轴的角速度,绕z轴的角速度(分别称为roll角速度,pitch角速度和yaw角速度)。

加速度计输出的格式为:x轴的加速度,y轴的加速度,z轴的加速度。

另外还需要关注传感器的其他参数如:

  • 陀螺仪的量程:eg.±2000dps
  • 加速度计的量程:eg.±2g
  • ADC转换精度为16bit
  • 传感器采样率4-1000hz:eg.1000hz

我们从IMU那就得到了陀螺仪数据gx,gy,gz,加速度数据az,ay,az

螺仪转换精度2^16=65536 , 65536/{2000-(-2000)}=16.4,实际1°等于ADC值16.4

采样率就是数据的更新率,也就是我们每次读取数据的频率。

首先将陀螺仪的数据转换成角度,这里封装成一个函数

  2.2.2 算法实现

static void Get_IMU_Values(float *values)
{
	int16_t gyro[3],acc[3];
	IMU_readGyro_Acc(&gyro[0],&acc[0]);
	for(int i=0;i<3;i++)
	{
        //gyro range +-2000; adc accuracy 2^16=65536; 65536/4000=16.4;
		values[i]=((float) gyro[i])/16.4f;	
		values[3+i]=(float) acc[i];
	}
}

然后编写函数实现计算姿态角的功能,使用四元数计算姿态角的公式在理论分析中推导:

其中α为绕x轴旋转角即roll,β为绕y轴旋转角即pitch,γ为绕z轴旋转角即yaw。a,b,c,dq0,q1,q2,q3.

void IMU_Update(void)
{
	static float q[4];
	float Values[6];	
	Get_IMU_Values(Values);	
	
	//change angle to radian,the calculate the imu with Mahony
	MahonyAHRSupdateIMU(Values[0] * PI/180, Values[1] * PI/180, Values[2] * PI/180,
 	                    Values[3], Values[4], Values[5]);		
	//save Quaternion
	q[0] = q0;
	q[1] = q1;
	q[2] = q2;
	q[3] = q3;
    
	imu.ax = Values[3];
	imu.ay = Values[4];
	imu.az = Values[5];
    
	imu.Pitch_v = Values[0];
	imu.Roll_v = Values[1];
	imu.Yaw_v = Values[2];

	//calculate the imu angle with quaternion
	imu.Roll = (atan2(2.0f*(q[0]*q[1] + q[2]*q[3]),1 - 2.0f*(q[1]*q[1] + q[2]*q[2])))* 180/PI;	
	imu.Pitch = -safe_asin(2.0f*(q[0]*q[2] - q[1]*q[3]))* 180/PI;
	imu.Yaw = -atan2(2 * q1 * q2 + 2 * q0 * q3, -2 * q2*q2 - 2 * q3 * q3 + 1)* 180/PI;
}

代码中MahonyAHRSupdateIMU()函数实现的就是四元数的更新算法。

逻辑上,首先用加速度计校准陀螺仪,方式是通过计算当前四元数姿态下的重力分量,与加速度计的重力分量作叉积,得到误差。
对误差作P(比例)和I(积分)运算后加到陀螺仪角速度上。最终由角速度计算新的四元数。

代码中的 sampleFreq 即执行姿态解算的频率,这里用定时器,以500HZ的频率调用get_angle();

void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az) {
	float recipNorm;	
	float halfvx, halfvy, halfvz;	//1/2 重力分量
	float halfex, halfey, halfez;	//1/2 重力误差
	float qa, qb, qc;
	//对加速度数据归一化
	recipNorm = invSqrt(ax * ax + ay * ay + az * az);
	ax *= recipNorm;
	ay *= recipNorm;
	az *= recipNorm;

	// 由四元数计算重力分量
	halfvx = q1 * q3 - q0 * q2;
	halfvy = q0 * q1 + q2 * q3;
	halfvz = q0 * q0 - 0.5f + q3 * q3;

	// 将四元数重力分量 与 加速度计重力分量 作叉积 得到误差
	halfex = (ay * halfvz - az * halfvy);
	halfey = (az * halfvx - ax * halfvz);
	halfez = (ax * halfvy - ay * halfvx);

	//对误差作积分
	integralFBx += twoKi * halfex * (1.0f / sampleFreq);	
	integralFBy += twoKi * halfey * (1.0f / sampleFreq);
	integralFBz += twoKi * halfez * (1.0f / sampleFreq);
	//反馈到角速度
	gx += integralFBx;	     gy += integralFBy;       gz += integralFBz;

	// 对误差作比例运算并反馈
	gx += twoKp * halfex;    gy += twoKp * halfey;    gz += twoKp * halfez;

	// 计算1/2 dt
	gx *= (0.5f * (1.0f / sampleFreq));		
	gy *= (0.5f * (1.0f / sampleFreq));
	gz *= (0.5f * (1.0f / sampleFreq));
	qa = q0;     qb = q1;      qc = q2;
	// 更新四元数
	q0 += (-qb * gx - qc * gy - q3 * gz);
	q1 += (qa * gx + qc * gz - q3 * gy);
	q2 += (qa * gy - qb * gz + q3 * gx);
	q3 += (qa * gz + qb * gy - qc * gx);

	// 四元数归一化
	recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
	q0 *= recipNorm;     q1 *= recipNorm;     q2 *= recipNorm;     q3 *= recipNorm;
}

由于加速度计对水平方向的旋转无能为力,故用此程序得到的yaw角数据会一直漂移,无法得到校准;通常的解决方法是增加一个磁场传感器,来获得一个准确的水平方向角来校准陀螺仪的漂移。MPU6050支持扩展一个IIC接口到磁场传感器,可通过配置MPU6050IIC MASTER 来读取磁场传感器的数据。

Mahony中提供了包含磁场数据的融合函数:

> void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, 
>                       float mx, float my, float mz);

3. 程序逻辑

首先看main函数:

int main(void)
{
	All_HardWare_init();
	while (1)
	{
		Protect_Check();
		LED_show_working();
		LCD_show_Brief_info();
	}
}

代码都封装在了函数里,因此主控的main函数非常简单。All_HardWare_init();包含了所有硬件、片内资源的初始化。因为Mahony每次上电融合解算姿态时需要几秒的自我校准,因此先打开定时器。

	TIM3_Int_Init(99, 7199); // 72M ÷7200 ÷100 = 10 ms

几秒过后再初始化PID控制器

	PID_init();              //直立环,速度环PID控制器初始化

定时器3中断服务函数control.c文件中,包含姿态解算和PID控制。

void TIM3_IRQHandler(void)
{
  if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) 
  {   TIM_ClearITPendingBit(TIM3, TIM_IT_Update);             
     /**
      *PID控制与姿态解算部分,详情请TP至
      *....../主控程序/HARDWARE/control/control.c
      *
      */
  }
}

死循环中目前三个函数分别是LED、LCD状态显示和 一个简易的过倾保护。

void Protect_Check(void)
{
	if (imu.Roll > 30 || imu.Roll < -30)
		Protect = 1;
	else
		Protect = 0;
}

4. 补充

还在更新,会做出更多的功能文章来源地址https://www.toymoban.com/news/detail-401890.html

到了这里,关于STM32平衡车的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于stm32的平衡小车

    目录 前言 一、电机驱动部分 1、TB6612FNG电机驱动模块接线方式: 2、代码使用定时器2的4路输出pwm 3、gpio引脚初始化,以及前进,后退引脚设置 二、MPU6050陀螺仪部分 三、编码器捕获部分 四、pid部分 1、直立环KD 2、速度环KI 3、转向环(PD) 五、蓝牙通信部分 总结 经过几天对

    2024年02月09日
    浏览(41)
  • 步进电机简单使用:STM32 PWM输出固定数目的脉冲数(基于CubeMX)

    使用步进电机之前,我们需要了解步距角的概念:步进电机接收到一个脉冲转动的角度,步进电机步距角通常 为1.8°,即步进电机接收到一个脉冲转动1.8°,则若步进电机接收到360°/1.8°=200个脉冲,步进电机就能转动一圈 步进电机通过驱动器控制,驱动器如下图所示(都比较

    2024年02月06日
    浏览(45)
  • 复刻stm32平衡小车(适合入门)

    目录 前言: 1.硬件部分 1.1 STM32最小系统 1.2 电源 1.3 TB6612电机驱动模块 1.4 串口通信 1.5 OLED模块 1.6 蓝牙模块 1.7 LED灯模块  1.8 MPU6050模块​编辑 1.9 硬件焊接与调试 1.10 组装 2.软件部分 2.1 代码 2.2 逻辑实现 2.2.1 control.c 2.2.2 usart.c 结尾 本文主要为复刻b站up主开源的平衡小车以及

    2024年02月13日
    浏览(56)
  • STM32两轮平衡小车原理详解(开源)

    关于STM32两轮平衡车的设计,我想在读者阅读本文之前应该已经有所了解,所以本文的重点是代码的分享和分析。至于具体的原理,我觉得读者不必阅读长篇大论的文章,只需按照本文分享的代码自己亲手制作一辆平衡车,其原理并不言而喻了。 源完整代码工程在文章末尾百

    2024年02月05日
    浏览(54)
  • 基于STM32-F401的平衡小车

    目录 一、控制系统设计 1.1机械结构设计 1.2传感系统设计 1.3执行器设计 1.4控制算法设计 二、控制系统的制作与调试 2.1机械结构的制作与调试 2.2电路系统的制作与调试 2.3控制程序的编写与调试 三、控制系统的测试与分析 3.1测试方法 3.2测试数据与现象 3.3结果分析 一个系统

    2024年02月06日
    浏览(50)
  • STM32 蓝牙平衡小车(一)硬件原理图

    第一篇文章首先介绍平衡小车的硬件组成,对硬件原理图进行详解。   1. 主控板:主控芯片(STM32F103C8T6)+电机驱动芯片(TB6612FNG)。 2. 小车框架:平衡车底盘、带编码器的电机、轮子 3. 电池:狮子航模电池2200mAh11.1V35C,T母头 4. DC-DC降压模块:MP1584EN,3A可调降压稳压电源模

    2024年02月14日
    浏览(41)
  • 基于STM32的平衡小车设计过程分享(1)

    一、简介 接触STM32开发一段时间了,想用STM32做一个有意思的项目,经历了无数的调参调参再调参,终于让它站稳了,接一下就一步步的跟大家介绍一下,项目的整体实现过程— 二、项目介绍     STM32平衡小车是一种基于STM32芯片的智能小车,它可以通过自动控制来保持平衡

    2024年02月05日
    浏览(59)
  • 毕业分享 stm32智能平衡小车设计与实现

    文章目录 0 前言 1 项目背景 2 设计思路 3 硬件设计 4 软件设计 4.2 直立控制程序设计 4.3 速度控制程序设计 4.4 方向控制程序设计 4.5 关键代码 5 最后 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这

    2024年02月02日
    浏览(54)
  • STM32平衡小车 TB6612电机驱动学习

    单片机引脚的电流一般只有几十个毫安,无法驱动电机,因此一般是通过单片机控制电机驱动芯片进而控制电机。TB6612是比较常用的电机驱动芯片之一。         TB6612FNG可以同时控制两个电机,工作电流1.2A,最大电流3.2A。  VM电机电源正极,是驱动电压输入端(10V), VCC为逻

    2024年02月06日
    浏览(49)
  • 毕业设计 STM32平衡车设计与实现

    Hi,大家好,学长今天向大家介绍一个 单片机项目, 大家可用于 课程设计 或 毕业设计 基于STM32的平衡车设计与实现 课题的研究主要是为了设计出可以在小范围内活动的轻巧灵活的绿色代步工具,并且在自平衡的功能上加上一些新功能, 如自跟随功能和遥控功能, 这样平衡

    2024年02月01日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包