|
在此贴上以前做过的平衡小车资料,一来供众网友学习交流,二来申请stm32f429探索套件。。。 先上图3 g' D1 ~( e( M9 `" P& j+ k# p
原材料清单: ——————————————————————————————————————————$ A# @* u4 [1 U 主控:stm32f103rct6; O3 [+ U W7 u. h! j( J( _ 传感器:mpu6050(带陀螺仪和加速度)" \+ @. k9 C0 ^6 A 电机驱动芯片:l298n) f8 b5 q$ g% O3 \ 电机:冯哈伯2224 编码器:电机自带16线1 V1 b) o6 X! i9 U 电池:两节18650 轮子架子:淘宝店购买,减速比1:5 ——————————————————————————————————————————2 {' K# N# A! E0 b! y 处理过程: —————————————————————————————————————————— 其实程序过程很简单,先是采集传感器MPU6050的数据,并进行加工,获得当前小车倾斜角,然后根据此角度做PID调节,得到小车两个电机的PWM脉宽,调整轮子速度,使之回到倾角为0的状态,即保持平衡。然后就不停地重复采集->处理->调节->处理这一过程。& a2 p6 A* Q X0 I+ T) [) H 在此基础上,附加两电机的PWM值,即可实现前进,倒退,左转,右转动作 —————————————————————————————————————————— 难点分析:$ q) `: i3 n0 N \ —————————————————————————————————————————— 有两个难点. C4 C; u8 J' W+ g 1.传感器的数据处理是小车的最大难点。一是传感器受震动影响很大,很容易超量程;二是传感器数据漂移比较厉害。而关键的小车倾角就来源于此传感器数据。为此,参考网上数据滤波处理方式,采用卡尔曼滤波算法,融合陀螺仪和加速度传感器数据得出小车倾角。 2.PID,比例系数的调节不用多讲,需要耐心的测试和调节。我要说的是,单纯靠倾角做PID不能使小车平衡,因为当小车倾角接近0度时,改变的PWM值无法使小车越过平衡点,造成小车朝一边加速前进,所以要将速度也添加至PID调节中,做积分) r ^; P7 _+ L$ a9 Y0 b —————————————————————————————————————————— 制作心得: —————————————————————————————————————————— 关于平衡小车,大多数网友应该都曾做过或者想过要做。于是百度搜资料,其中最多的应该是飞思卡尔直立车的资料,当初我也看下下,平衡车的原理都懂了,但那时还没搞过PID调节和数据滤波,所以具体怎么写程序并不知道。至于平衡车的程序资料也非常少。后来在网上参考相关数据滤波,PID调节后,才渐渐掌握。在此我也就贴上我的程序代码,供大家学习交流,少走弯路。有什么问题,欢迎回帖。当然也希望大家多支持此贴,祝我申请F429套件成功!哈哈 / p! o: P% i8 j3 i; l" l——————————————————————————————————————————- K+ c$ r" N: N% U' {2 ?
å¡å°æ¼æ»¤æ³¢.rar
(2.76 MB, 下载次数: 12100)
|
微信公众号
手机版
回复:【MCU实战经验】+基于stm32两轮平衡车制作
回复:【MCU实战经验】+基于stm32两轮平衡车制作
问题:1,我快速改变板子倾角时Angle的变化正常吗?
2,Angle正常变化的时候是应该与Angle_ax的值相近吗?$ M* B3 \9 Q3 G) _6 K6 p* `: w; N- ~
现在情况就是,就算我是在减小倾角,只要我快速地改变,它显示的倾角都会先增大再减小,而如果我慢速改变的话,倾角就会缓慢减小而不会出现中间的角度增大
& _; @" ^+ r: {& `1 z2 u2 H! z
6 |* k, @$ ~0 j
*************读取数据********************
//定义MPU6050内部地址
#define SMPLRT_DIV 0x19 //陀螺仪采样率 典型值 0X07 125Hz
#define CONFIG 0x1A //低通滤波频率 典型值 0x00
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围 典型值 0x18 不自检 2000deg/s
#define ACCEL_CONFIG 0x1C //加速度计自检及测量范围及高通滤波频率 典型值 0x01 不自检 2G 5Hz
#define INT_PIN_CFG 0x37% Q% v, y" g% Q. Z9 z$ a, K
#define INT_ENABLE 0x38
#define INT_STATUS 0x3A //只读
#define ACCEL_XOUT_H 0x3B& \: n4 j' I. _% q8 O
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E; ]8 e& X5 ?. r) ?3 y8 z
#define ACCEL_ZOUT_H 0x3F4 \ C6 O) b; ^6 A5 ]/ M) k
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x413 z; T% G9 {1 x8 }1 z& w
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
0 W# t A! k c6 k0 T; B
//读取寄存器原生数据1 [+ T ?4 r1 i% K8 ]! G6 c/ }( t
9 {3 x T* j5 H; ?3 R2 E
MPU6050_Raw_Data.Accel_X = (buf[0]<<8 | buf[1]);% d W0 y9 q# ?6 v( E. D
MPU6050_Raw_Data.Accel_Y = (buf[2]<<8 | buf[3]);
MPU6050_Raw_Data.Accel_Z = (buf[4]<<8 | buf[5]);
MPU6050_Raw_Data.Temp = (buf[6]<<8 | buf[7]); , S1 T$ e9 ^* g1 c& \
MPU6050_Raw_Data.Gyro_X = (buf[8]<<8 | buf[9]);9 z/ z8 B5 O- Z
MPU6050_Raw_Data.Gyro_Y = (buf[10]<<8 | buf[11]);' |% ?. y+ S1 D0 M! ?0 O2 H
MPU6050_Raw_Data.Gyro_Z = (buf[12]<<8 | buf[13]);
2 Y4 w& z1 n- Z* W" i, o
//将原生数据转换为实际值,计算公式跟寄存器的配置有关1 G7 F( D1 O1 i1 Z
MPU6050_Real_Data.Accel_X = -(float)(MPU6050_Raw_Data.Accel_X)/8192.0; ! x2 u' z( w; p+ V; F1 @% `' ~" u
MPU6050_Real_Data.Accel_Y = -(float)(MPU6050_Raw_Data.Accel_Y)/8192.0;
MPU6050_Real_Data.Accel_Z = (float)(MPU6050_Raw_Data.Accel_Z)/8192.0; ! Y! g$ C& [, S U7 O; ~
MPU6050_Real_Data.Gyro_X=-(float)(MPU6050_Raw_Data.Gyro_X - gyroADC_X_offset)/65.5;
MPU6050_Real_Data.Gyro_Y=-(float)(MPU6050_Raw_Data.Gyro_Y - gyroADC_Y_offset)/65.5; ( I% ^' _7 L6 }( S3 `
MPU6050_Real_Data.Gyro_Z=(float)(MPU6050_Raw_Data.Gyro_Z - gyroADC_Z_offset)/65.5;
} 5 W% }; s2 k) N9 m: s, I
- `% ?$ s2 K. j, _5 o. U1 j) h
* @, u' r4 D* v. E* I, h
//******卡尔曼参数************
; ?4 p7 J4 w. k1 } R" a* J' b) O
const float Q_angle=0.001;
const float Q_gyro=0.003;
const float R_angle=0.5;
const float dt=0.01; //dt为kalman滤波器采样时间;
const char C_0 = 1;
float Q_bias, Angle_err;
float PCt_0, PCt_1, E;
float K_0, K_1, t_0, t_1;
float Pdot[4] ={0,0,0,0};
float PP[2][2] = { { 1, 0 },{ 0, 1 } };% b- X0 S2 Y5 A+ u
: i# a7 \5 R1 J3 Q# M( y! e7 {
/*****************卡尔曼滤波**************************************************/
void Kalman_Filter(float Accel,float Gyro) 5 J3 O0 `( g( y( e9 |
{
Angle+=(Gyro - Q_bias) * dt; //先验估计
Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分& V" p) r* O* ~
Pdot[1]= -PP[1][1];% @- Q! |0 `9 `* D4 C
Pdot[2]= -PP[1][1];8 ^% _3 h; e0 M' d1 \0 y
Pdot[3]=Q_gyro;
PP[0][0] += Pdot[0] * dt; // Pk-先验估计误差协方差微分的积分
PP[0][1] += Pdot[1] * dt; // =先验估计误差协方差& i" S6 i7 {! h; a5 |! ]8 f
PP[1][0] += Pdot[2] * dt;. z) T' D' X# w; Q% l) B J
PP[1][1] += Pdot[3] * dt;
: S; F. j7 T; f' C
Angle_err = Accel - Angle; //zk-先验估计
PCt_0 = C_0 * PP[0][0];
PCt_1 = C_0 * PP[1][0];
6 { _$ ?1 u a' [8 I1 ^. m
E = R_angle + C_0 * PCt_0;6 J! t2 q, O% L6 T" n" q9 L0 V
K_0 = PCt_0 / E;5 y0 ?, | E3 U# d& v; D( U* g c* _
K_1 = PCt_1 / E;6 Q$ g: ^8 y4 J% V* w
t_0 = PCt_0;# n1 {! ~# D9 r' e7 H
t_1 = C_0 * PP[0][1];
4 |4 |% N) O1 k6 p9 ?6 t4 X8 O
PP[0][0] -= K_0 * t_0; //后验估计误差协方差
PP[0][1] -= K_0 * t_1;
PP[1][0] -= K_1 * t_0;" z/ v$ H! T' t
PP[1][1] -= K_1 * t_1;
Angle += K_0 * Angle_err; //后验估计& B3 q$ F1 b9 ^# b( Q
Q_bias += K_1 * Angle_err; //后验估计/ b) s! V) A: J( M4 t# Y- r
Gyro_y = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
}; Y1 i, {5 O# {( p% N8 w
8 c e2 s8 f' ^( J# Q
******************倾角计算*****************7 y2 Z% l: x% w2 _
void Angle_Calculate(void); d( B4 B2 @8 [
{9 d, U# h) ], m/ J( t
/****************************加速度****************************************/6 z8 }' @1 m! `5 P% G! @2 r. Q- ^
Accel_x = MPU6050_Real_Data.Accel_X; //读取X轴加速度' d! _3 d" E5 n3 e d$ a* e/ I
Angle_ax = Accel_x*1.2*180/3.14; //弧度转换为度2 X5 H }% [+ X5 U& [7 E* r/ O
N3 U8 c* k" z; g, m
/****************************角速度****************************************/
Gyro_y = MPU6050_Real_Data.Gyro_Y; - d' u* C* Y- a1 x$ p$ R+ U' D0 Z9 Z
时间dt,所以此处不用积分
/***************************卡尔曼融合*************************************/ G% \ v) g9 G+ {' y1 p5 }5 _
Kalman_Filter(Angle_ax,Gyro_y); //卡尔曼滤波计算倾角
0 r m; s( B0 O: U) f
回复:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作
回复:【MCU实战经验】+基于stm32两轮平衡车制作
收了 感谢楼主 . u0 l9 `! Z7 ]
客气。。。
RE:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作
回复:【MCU实战经验】+基于stm32两轮平衡车制作
回复:【MCU实战经验】+基于stm32两轮平衡车制作
回复:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作
RE:【MCU实战经验】+基于stm32两轮平衡车制作