极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 46967|回复: 16

我也想做平衡车了,从0开始,来有点收集的资料!

[复制链接]
发表于 2012-3-26 10:01:12 | 显示全部楼层 |阅读模式
本帖最后由 taotao71 于 2012-3-26 10:03 编辑

我也想做平衡车了,从0开始,来有点收集的资料!
平衡算法  
扭距=角度误差*K1+角速度*K2+速度误差*K3+积分速度误差*K4
角度误差:(角度,平衡时此值为0)
角速度:(X度/秒)
速度误差:是在指挥速度和实际速度差,则功率补偿(如果无码盘,则此值为0),x=扭距(PWM)*转换常数-码盘速度
积分速度误差:是用来维持在不平坦的地形前进速度速度误差积累

关于取得平衡点之想法
利用角速度来取得平衡点:我计划的方法是不断修正角速度,当角速度为0时,有两种可能,一种是已达到平衡点,另一种可能是车子已倒下。车子是否已倒下可以用加速度传感器来检测倾角,现在预测是第一种可能,就是角速度为0时就是平衡点,再用加速度传感器把倾角作为0点,以此解决零点漂移问题,此方法有待实验。

关于双轮平衡小车的算法资料收集
整个系统分为三大部分。
1.角度采集   
2.电机数据运算   
3.电机驱动

先说第一部分:角度采集.
这里我采用两种传感器:一种是陀螺仪(ENC03),另一种是加速度计(MMA7260).其实任何其中一
种都可以得出现在的车体倾斜角度值。为什么我们要选择两种呢?原因是这里有一种思想在里面:互补。

先说下陀螺仪:
陀螺仪属于测量旋转运动的传感器,其输出的是角度变化速度。即旋转的越快,输出量越大(不能
无限大,传感器上有极限指标);旋转的越慢,输出量越小(最小为0,即静止时)。
我们可以通过积分运算(累加),得出相对角度数据,这里假设为A。但是我们知道,积分是有严重
的累积误差的。我们可以一句话概括:陀螺仪短时间准确,长时间不准确。
再说下加速度计:
加速度计属于测量线性运动的传感器,其输出的是传感器沿某个轴向直线运行时的速度变化量。即
速度变化的越快,输出量越大(不能无限大,传感器上有极限指标);速度变化的越慢,输出量越小(最小
为0,即静止时)。这种特性用来做惯导研究很好。但是如何和我们的角度倾斜量相关呢?
我们知道加速度计测量的是加速度量,而地球上的物体都是受万有引力制约的,即我们时刻都受到
一个大小为g的竖直向下的加速度的作用。我们通过反正弦运算,可以得到加速度计当前与重力方向的夹角数据,这里假设为B。
但是又有新的问题了。加速度计是测量线性运动的,即其对震动非常敏感。电机转动,所产生的震
动是不可小视的。所以其会有很大的噪声。而且当加速度计运动时,其输出量是运动加速度与重力加速度的
混合数据,这会严重影响角度计算的准确性。其特点用一句话概括:加速度计长时间较准确,短时间误差大。

现在我们重新审视一下,这两个传感器恰恰成互补关系。要得出比较准确的、长时间稳定的角度数
据,这两种传感器是缺一不可的。这也就是贯穿我整个数据采集过程的基本思想--互补。
我的具体做法是偏向于使用陀螺仪数据。原因是陀螺仪数据的噪声较小,短时间内误差小。而其长
时间的积分误差怎么解决呢?我的方法是使用加速度计角度数据B的平均值来校准陀螺仪的角度数据A.
直接伪代码如下:
A += (B-A)/k;
这里的K是衰减倍数。
其实就这么简单,这就实现了比较准确的角度数据的采集工作。

下面说下滤波问题。我们知道加速度计的噪声很大,我们这里采用卡尔曼的思想来滤波,另一种说法是数据融合。

其实这里就是两种传感器的典型互补了,用其算出来的角度数据相对来说很准了。
设加速度计换算出的角度数据为M,陀螺仪只采数据为s,陀螺仪相对加速度计的因子为k,上次加速度计经过滤波后的角度数据为M_2,卡尔曼
增益选择固定值为g.滤波后的角度数据为real_M;
那么滤波伪代码:
Temp=M_2+s*k;
real_M = Temp*g+(m-Temp)*(1-g);
M_2 = real_M ;

其实整个小车中,最关键、也最难的地方就是角度采集问题。准确的角度,只要一个P作用量就能轻松让小车站起来。


一部分:电机数据运算.
其实网上关于这部分的资料是最多的。我采用的是经典的PID算法。
理论我不讲了。我只讲讲实现过程。
这里如果先试试车体的稳定性,我们先只使用P作用。
现在以能立住为目标。

P,就是比例。假设当前角度偏差为error,目标角度为aim,比例系数为p,那么
PID计算伪代码为PID_result = (error-aim)*p;//(这里aim=0,即竖直状态)。
可以看出,如果车体倾斜度越大,那么计算出的PID的P值比例性的增大。

举实例说明(具体参数与车体和电机等有关):
我的电机为[email=200RPM@12V]200RPM@12V[/email],PWM的调制精度为-255~+255,那么当我的P参数p=30时,小车基本能够立住了(不足点就是总喜欢前后跑动)。

其实就这么简单。

剩下的I和D参数的调制方法,大家可以查阅网上的丰富的资料。I是减小误差的,D是阻碍小车姿态变化的。

3.电机驱动
这部分是最基础的。我才用的是L298驱动芯片。加了光耦隔离(原因是减速电机正反转切换时,产生的反电动势会造成单片机死机)。电机控制器为ATmega8,脉宽调制是使用的其内部自带的硬件PWM。为了简单起见,直接给两个轮子临时加上了码盘,而ATmega8也承担了由码盘数据得出电机转速和行程的数据任务。其与控制器ATmega168之间使用TWI(其实就是I2C)协议通讯。





主控制流程如下:
  
    下面对“过程一”和“过程二”作具体介绍:
? 过程一:加速度计算:
    如图:



  
(原文件名:新建图像.JPG)  引用图片
        点O为轮轴,点P为机体(系统)质心;
        假设已知:机体质量m , 重力加速度g ,
        机轴倾角θ(具体测法参见“实验报告”)。
        设机体以加速度a加速,
        则受到假想的惯性力F*= ma;
        要使机体回复平衡状态,就要使得:
        ΣM = 0 (M为力矩);
        如图以点O(即轮轴)为转轴,支持力N,过转轴,力矩为零;摩擦力为被动力,且轮胎不与机身固连,不需要考虑。
        即:mglsinθ+ F* = 0;
        ∴  a ≥ g?tanθ;
        从而可以令:a = k?tanθ?g (k≥1);
        进一步修正:
        又知a应与P点相对于点O的角(线)速度(ω=d θ/d  t)成正比以获得更好的回复效果;
        ∴可以令  a = k1 ?ω?tanθ?g; (★)
        其中:k1为常量,其取值可通过实验获得;ω为优化修正量,没有量纲。
            
  ?过程二:加速度实现:
    假设轮子与地面不发生相对滑动,
    ∴  a = at    (at为车轮的线加速度);
    ∴  a = R?d ω/d t    (R为车轮半径);
    而  J = ΣJi = ω?I    (J为角动量;I为车轮转动惯量。由于质点组(车轮)角动量方向相同,可以叠加。);
    ∴  at = R?d ω/d t = R/I?(d J/d t) = (R/I)?M ;
    其中:  M = M1 – M0    (其中M0为阻力力矩,设其为定值;M1为马达产生的力矩);
    ∴  M1 = at?I/R + M0;
    已知:M1M1与马达扭力F成正比,
    而:P = F?V    (其中,P为功率,V为车轮转速);
    ∴  可以令:M1 = k?P/V    (*);
    ∴  P = (1/k)?V?(atI/R + M0)    (其中V可以通过测定轮轴的转速来获得);
    进一步修正:
      车轮可以近似看作均匀圆盘,∴I ≈ 2mR2    (其中m为单个车轮的质量)
      a = at;       令:1/k = k2
    ∴  P = k2?V?(2mR?a + M0) ;
    ∴  单个车轮的输出功率为:P = k2?ma?V?R + 0.5 k2?V?M0 ;(★)
    其中:k2 、M0均为常量,可从实验中归纳。
    注明:由(*)可知,k的量纲为“m”,所以k2的量纲为“1/m”。
? 过程一与二的统一:
    将两(★)式联立,可以得到:
    P = k1 k2?tanθ?ω?mg?V?R + 0.5 k2?V?M0
    其中,ω为优化修正量,没有量纲,k2有量纲(1/m)。


[转1]

Torque = AngleError * Kangle + AngularRate * Krate + VelocityError * Kvel + IntegratedVelocityError * Kivel

•Angle error is the displacement from vertical (balance)
•Angular rate is the rate of rotation (deg/sec)
•Velocity Error is the difference between the commanded velocity and the actual velocity
Integral Velocity Error is an accumulation of velocity errors used to maintain the forward velocity over uneven terrain.
•The various Kxxx are the gains for each term.  The value range from 1-30 or so and are dependent upon lots of other factors like the mass of the robot, the resolution of the encoders, the loop rate for controlling the motors, etc.  I determined all of my values by trial and error.

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

 楼主| 发表于 2012-3-26 10:05:41 | 显示全部楼层
这些都是基础!先了解概念再说!
回复 支持 反对

使用道具 举报

发表于 2012-3-26 10:23:21 | 显示全部楼层
好贴,很全面啊

我的马达不太好加码盘,打算暂时不考虑码盘的问题

转动惯量或许可以测整体的自摆频率吧,还没到那一步,没细想

我还在消化PID库的代码,反正不赶进度,慢慢琢磨
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-3-26 10:25:20 | 显示全部楼层
形象解释PID算法+PID算法源代码(转)
小明接到这样一个任务:
有一个水缸点漏水(而且漏水的速度还不一定固定不变),
要求水面高度维持在某个位置,
一旦发现水面高度低于要求位置,就要往水缸里加水。

小明接到任务后就一直守在水缸旁边,
时间长就觉得无聊,就跑到房里看小说了,
每30分钟来检查一次水面高度。水漏得太快,
每次小明来检查时,水都快漏完了,离要求的高度相差很远
,小明改为每3分钟来检查一次,结果每次来水都没怎么漏
,不需要加水,来得太频繁做的是无用功。几次试验后,
确定每10分钟来检查一次。这个检查时间就称为采样周期。

开始小明用瓢加水,水龙头离水缸有十几米的距离,
经常要跑好几趟才加够水,于是小明又改为用桶加,
一加就是一桶,跑的次数少了,加水的速度也快了,
但好几次将缸给加溢出了,不小心弄湿了几次鞋,小明又动脑筋,
我不用瓢也不用桶,老子用盆,几次下来,发现刚刚好,不用跑太多次,
也不会让水溢出。这个加水工具的大小就称为比例系数。

小明又发现水虽然不会加过量溢出了,有时会高过要求位置比较多
,还是有打湿鞋的危险。他又想了个办法,在水缸上装一个漏斗,
每次加水不直接倒进水缸,而是倒进漏斗让它慢慢加。这样溢出的问题解决了,
但加水的速度又慢了,有时还赶不上漏水的速度。
于是他试着变换不同大小口径的漏斗来控制加水的速度
,最后终于找到了满意的漏斗。漏斗的时间就称为积分时间 。

小明终于喘了一口,但任务的要求突然严了,
水位控制的及时性要求大大提高,一旦水位过低,
必须立即将水加到要求位置,而且不能高出太多,否则不给工钱。
小明又为难了!于是他又开努脑筋,终于让它想到一个办法,常放一盆备用水在旁边,
一发现水位低了,不经过漏斗就是一盆水下去,这样及时性是保证了,但水位有时会高多了。
他又在要求水面位置上面一点将水凿一孔,再接一根管子到下面的备用桶里这样多出的水会从上面的孔里漏出来。
这个水漏出的快慢就称为微分时间。


大学时代做机器人时用的PID算法源代码:
#define PID_Uint struct pid_uint
PID_Uint
{
        int U_kk;
        int ekk;
        int ekkk;
        int Ur;                                //限幅输出值,需初始化
        int Un;                                //不灵敏区
        //int multiple;                //PID系数的放大倍数,用整形数据的情况下,提高PID参数的设置精度          固定为256
        int Kp;                                //比例,从小往大调
        int Ti;                                //积分,从大往小调
        int Td;                                //微分,用巡线板时设为0
        int k1;                                //
        int k2;
        int k3;
};

/********************************************************************
函 数 名:void Init_PID_uint(PID_uint *p)
功    能:初始化PID参数
说    明:调用本函数之前,应该先对Kp,Ti,Td做设置        ,简化了公式
入口参数:PID单元的参数结构体 地址
返 回 值:无
***********************************************************************/
void Init_PID_uint(PID_Uint *p)
{
        p->k1=(p->Kp)+(p->Kp)*1024/(p->Ti)+(p->Kp)*(p->Td)/1024;
        p->k2=(p->Kp)+2*(p->Kp)*(p->Td)/1024;
        p->k3=(p->Kp)*(p->Td)/1024;
}
/********************************************************************
函 数 名:void reset_Uk(PID_Uint *p)
功    能:初始化U_kk,ekk,ekkk
说    明:在初始化时调用,改变PID参数时有可能需要调用
入口参数:PID单元的参数结构体 地址
返 回 值:无
***********************************************************************/
void reset_Uk(PID_Uint *p)
{
        p->U_kk=0;
        p->ekk=0;
        p->ekkk=0;
}
/********************************************************************
函 数 名:int PID_commen(int set,int jiance,PID_Uint *p)
功    能:通用PID函数
说    明:求任意单个PID的控制量
入口参数:期望值,实测值,PID单元结构体
返 回 值:PID控制量
***********************************************************************/
int PID_common(int set,int jiance,PID_Uint *p)
{
        int ek,U_k=0;
        ek=jiance-set;
        if((ek>(p->Un))||(ek<-(p->Un)))                //积分不灵敏区
                U_k=(p->U_kk)+(p->k1)*ek-(p->k2)*(p->ekk)+(p->k3)*(p->ekkk);
        p->U_kk=U_k;
           p->ekkk=p->ekk;
        p->ekk=ek;
        if(U_k>(p->Ur))                                        //限制最大输出量,
                U_k=p->Ur;
        if(U_k<-(p->Ur))
                U_k=-(p->Ur);        
        return U_k/1024;
}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-3-26 10:59:05 | 显示全部楼层
http://wenku.baidu.com/view/1f7568edf8c75fbfc77db269.html
单轴双轮自平衡代步车的研究与设计(研究生的毕业论文)
回复 支持 反对

使用道具 举报

发表于 2012-7-25 19:50:37 | 显示全部楼层
很好很好的帖子!!!!
回复 支持 反对

使用道具 举报

发表于 2012-8-30 15:20:17 | 显示全部楼层
码盘不懂怎么用啊 啊啊
回复 支持 反对

使用道具 举报

发表于 2012-12-19 11:56:32 | 显示全部楼层
我也正在学习当中呢,真的没有想象中的简单呢
回复 支持 反对

使用道具 举报

发表于 2012-12-30 21:42:47 | 显示全部楼层
taotao71 神来着

够牛,这已经不算基础了
回复 支持 反对

使用道具 举报

发表于 2012-12-31 02:12:54 来自手机 | 显示全部楼层
好贴 标记学习
回复 支持 反对

使用道具 举报

发表于 2013-1-31 12:12:13 | 显示全部楼层
咨询FreeWay两轮平衡车(无刷电机+锂电池)
QQ:695118363
回复 支持 反对

使用道具 举报

发表于 2013-3-5 11:46:18 | 显示全部楼层
学习中,跟楼主共同进步
回复 支持 反对

使用道具 举报

发表于 2013-4-18 01:08:31 | 显示全部楼层
好贴。。。。
回复 支持 反对

使用道具 举报

发表于 2013-8-29 16:56:53 | 显示全部楼层
看到就顶一下
回复 支持 反对

使用道具 举报

发表于 2013-8-30 15:47:34 | 显示全部楼层
角度采集直接用一个“串口MPU6050”模块搞定,某宝上面已经有现成的姿态角度输出的模块了,据说用了动态卡尔曼滤波,精度还很高。
回复 支持 反对

使用道具 举报

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

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-9 16:34 , Processed in 0.069335 second(s), 30 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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