搜索
bottom↓
楼主: zlstone

自己做的双轮自平衡小车

  [复制链接]

出0入0汤圆

发表于 2010-8-16 14:49:09 | 显示全部楼层
回复【195楼】haleycui
昨天天花了我一个下午的时间终于买到了铝型材。但并不是我最想要的铝方,只好将就了。
今天我将所有铝型材加工好并将其安装在了车底,比较顺利的将重达8公斤的铅酸蓄电池固定在了车底。所有电力线、信号线均已铺设好,经测试,电路正
-----------------------------------------------------------------------
你好,你的东东很酷,请问,电机与两个大轮,是在那里买的?

出0入0汤圆

发表于 2010-8-16 15:01:34 | 显示全部楼层

出0入0汤圆

发表于 2010-8-16 17:59:44 | 显示全部楼层
回复【203楼】cyxavr 又一天
-----------------------------------------------------------------------

http://item.taobao.com/item.htm?id=6352387926

出0入0汤圆

发表于 2010-8-16 18:55:24 | 显示全部楼层
轮子不错,有时间我也买一个玩玩

出0入0汤圆

发表于 2010-8-16 19:29:47 | 显示全部楼层
今天我又在底盘的四周加装了角铝,以增加车体的机械强度。将所有线缆接好后,终于下决心放地上测试了一下。我已做好大车突然失去控制的准备,在其底板上放了一个板凳,几本大厚书(差不多得5KG),真的平衡了!但过了一会我打算调一下电位器,突然,车体向前猛冲,吓我一大跳。幸好我手扶的紧,立即关闭了电源。没有出什么危险。后来发现是电位器的精度不够,在跟换了高精度电位器之后,细细调好,车体终于稳定了。


(原文件名:IMAG0117.jpg)


(原文件名:IMAG0118.jpg)


(原文件名:IMAG0122.jpg)

视频在这http://v.youku.com/v_show/id_XMTk4NDg2NDgw.html

出0入0汤圆

发表于 2010-8-17 10:32:12 | 显示全部楼层
LZ 你好,我对平衡车很感兴趣 自己也想弄一个,但是AVR单片机没用过 不太会。我想根据你的程序改一下应用到C8051F上,

所以苦读你的程序,也是看了个大概。其中最不理解的就是算法那部分。也就是AD采集数据后处理和计算PWM输出时的数据处理部分,

我实在是理解不了,恳求LZ给些提示。。或者哪位高人给予指点。

程序如下:

AD采集数据处理部分:
void AD_calculate(void)
{
       
        acceler=ADport(2)+28;                        //角度校正
        gyro=ADport(3);       
       
        acceler*=0.004069;                //系数换算:2.5/(1.2*512);
        acceler=asin(acceler);
        gyro*=0.00341;                        //角速度系数:(3.14/180)* 100/512=0.01364;       
       
        Kalman_Filter(acceler,gyro);
}

计算PWM部分:
void PWM_calculate(void)       
{
        if ( 0==(~PINA&BIT(1)) )        //左转
        {
                Turn_Need=-40;
        }
        else if ( 0==(~PINB&BIT(2)) )         //右转
        {
                Turn_Need=40;
        }
        else        //不转
        {
                Turn_Need=0;
        }
       
        if ( 0==(~PINC&BIT(0)) )        //前进
        {
                Speed_Need=-2;
        }
        else if ( 0==(~PINC&BIT(1)) )        //后退
        {
                Speed_Need=2;
        }
        else        //不动
        {
                Speed_Need=0;
        }
       
        K_angle_AD=ADport(4)*0.007;
        K_angle_dot_AD=ADport(5)*0.007;
        K_position_AD=ADport(6)*0.007;
        K_position_dot_AD=ADport(7)*0.007;

        position_dot=(speed_real_LH+speed_real_RH)*0.5;
       
        position_dot_filter*=0.85;                //车轮速度滤波
        position_dot_filter+=position_dot*0.15;       
       
        position+=position_dot_filter;
       
        position+=Speed_Need;
       
        if (position<-768)                //防止位置误差过大导致的不稳定
        {
                position=-768;
        }
        else if  (position>768)
        {
                position=768;
        }
       
        PWM = K_angle*angle *K_angle_AD + K_angle_dot*angle_dot *K_angle_dot_AD +
              K_position*position *K_position_AD + K_position_dot*position_dot_filter *K_position_dot_AD;
       
       
        speed_output_RH = PWM - Turn_Need;
        speed_output_LH = - PWM - Turn_Need ;
               
        PWM_output (speed_output_LH,speed_output_RH);       
}

出0入0汤圆

发表于 2010-8-17 10:39:10 | 显示全部楼层
我不是只要不会就问别人的选手。我会认真的学习和考虑的。实不相瞒LZ的程序我看了好多天,

从不懂的AVR程序一点点看的。遇到一个不会的就立马找资料,知道理解一二为止。。

卡尔曼没理解,实在是复杂,决定直接用现成的。

AVR的PWM输出没理解,希望有人指点下。

剩下的就是主要部分 算法。。LZ的算法是实在没看懂。。

在网上到处找算法,就是找不到合适或者说是能看懂的。

也恳求哪位高人能指点一二。

万分感激。。

出0入0汤圆

发表于 2010-8-17 11:36:43 | 显示全部楼层
【207楼】 haleycui
的速度真快。
果然强。

出0入0汤圆

发表于 2010-8-17 20:18:37 | 显示全部楼层
再上传清楚一点几张照片.后天就要军训了,然后就是开学,这个项目可能就要搁置一段时间,大概十一节的时候,我会继续完成剩下的工作。请大家到时继续关注,谢谢大家的支持!

(原文件名:DSC01361.JPG)


(原文件名:DSC01364.JPG)


(原文件名:DSC01366.JPG)




高清视频在这:http://v.youku.com/v_show/id_XMTk4Nzg2NDYw.html

http://v.youku.com/v_show/id_XMTk4Nzg4NTQ0.html

出0入0汤圆

发表于 2010-8-17 20:46:12 | 显示全部楼层
赞一个, 不错的

出0入0汤圆

发表于 2010-8-17 23:12:15 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-8-18 13:53:50 | 显示全部楼层
回复【209楼】icsundd
-----------------------------------------------------------------------

void PWM_calculate(void)       
{
        //这部分是由于我采用了遥控,输入高电平来控制车辆的转弯和前后;
        //如果没有遥控,这部分可以删除
        if ( 0==(~PINA&BIT(1)) )        //如果PortA1输入高电平则左转;
        {
                Turn_Need=-40;
        }
        else if ( 0==(~PINB&BIT(2)) )         //如果PortB2输入高电平则右转;
        {
                Turn_Need=40;
        }
        else        //如果无信号则不转
        {
                Turn_Need=0;
        }
       
        //这部分是来控制前后的,与上面转弯的相同;
        if ( 0==(~PINC&BIT(0)) )        //前进
        {
                Speed_Need=-2;
        }
        else if ( 0==(~PINC&BIT(1)) )        //后退
        {
                Speed_Need=2;
        }
        else        //不动
        {
                Speed_Need=0;
        }
       
        //接下来是采样四个电位器的值,也就是对所需的增益K值微调,方便调试;
        //如果确定好K值,可以删除下面的4句代码,则:PWM=K_angle*angle+....
        K_angle_AD=ADport(4)*0.007;
        K_angle_dot_AD=ADport(5)*0.007;
        K_position_AD=ADport(6)*0.007;
        K_position_dot_AD=ADport(7)*0.007;
   

        position_dot=(speed_real_LH+speed_real_RH)*0.5; //求车轮的平均速度;
       
        position_dot_filter*=0.85;                //车轮速度低通滤波
        position_dot_filter+=position_dot*0.15;       
       
        position+=position_dot_filter;  //求得车轮的位置;
        //position+=position_dot;       
        position+=Speed_Need;   //求得所期望的车轮位置
       
        if (position<-768)                //防止位置误差过大导致的不稳定,对其限制最大最小值
        {
                position=-768;
        }
        else if  (position>768)
        {
                position=768;
        }
       
        //求总体的PWM;
        PWM = K_angle*angle *K_angle_AD + K_angle_dot*angle_dot *K_angle_dot_AD +
              K_position*position *K_position_AD + K_position_dot*position_dot_filter *K_position_dot_AD;
       
       
        speed_output_RH = PWM - Turn_Need;  //转弯的PWM控制;
        speed_output_LH = - PWM - Turn_Need ;
       

               
        PWM_output (speed_output_LH,speed_output_RH);       
}

出0入0汤圆

发表于 2010-8-18 21:46:06 | 显示全部楼层
回复【214楼】zlstone
-----------------------------------------------------------------------

学习了。不过还是有不明白的地方。

acceler=ADport(2)+28; //角度校正
这句话是不是在小车直立的时候测得的电压值与加速度传感器中介绍的Zero g状态的差值?
若小于2.5V就另ADport(2)+X=2500 若大于2.5V就令ADport(2)-X=2500 这个X就是这里的28吗?

PWM = K_angle*angle *K_angle_AD + K_angle_dot*angle_dot *K_angle_dot_AD +  
      K_position*position *K_position_AD + K_position_dot*position_dot_filter *K_position_dot_AD;
不理解PWM是根据什么而来的呢?

还有做这个平衡的算法 :
已知的是小车的倾斜角度和加速度
是怎么算得如何控制电机的呢?

问的问题有些肤浅 还望多多指教!!

出0入0汤圆

 楼主| 发表于 2010-8-18 22:13:13 | 显示全部楼层
回复【215楼】icsundd
-----------------------------------------------------------------------

acceler=ADport(2)+28; //角度校正 ;你的理解没错;

PWM是根据PID算法来的,也就是P:比例、I:积分、D:微分进行误差控制的算法;
只是这里只采用了角度P,角速度作为D调节;另外车轮速度P调节,位置作为I调节;
如果不太明白请看看自动控制方面的书籍;

出0入0汤圆

发表于 2010-8-19 08:38:51 | 显示全部楼层
回复【216楼】zlstone
-----------------------------------------------------------------------

恩,这个PWM的是由PID算法得来的。一定是我对PID的理解太少。我还会在仔细看的。

可是还是没理解的是:
由已知条件(例如角度、角速度、车轮直径、车体高度等)
怎么样能得出如何控制车轮呢?(是控制车轮的速度?还是加速度?或者是行进位移?既未知条件)从而达到平衡的呢?

————————————————————————————————————————————————

主控制流程如下:

    下面对“过程一”和“过程二”作具体介绍:
&#61548; 过程一:加速度计算:
    如图:

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

我的理解是这样的:

这个控制的是单轮输出的功率。(也就是要求得的结果既未知条件)

而已知条件需要的有车体倾斜角度,角速度,质量,转速。

式中的K1 K2 M0是通过建模或者实际测试中得来的。

不知我的理解对还是不对。望指教。。

出0入0汤圆

发表于 2010-8-19 08:52:13 | 显示全部楼层
忘记了,还有一个关于第一次提的问题。

我觉得这部分也应该有没理解的人吧,要么我真的是太笨了。 5555

LZ也许是没注意到这段程序。现在贴出来,其中的注释也是这两天对它的追究而得的。

也不知对否。还请指教。

void AD_calculate(void)
{
  acceler=ADport(2)+28;        //角度校正(上有。。↑)
  gyro=ADport(3);                 //不必解释了吧*^_^*
       
  acceler*=0.004069;        //系数换算:2.5/(1.2*512); // 5/(1.2*1024);5为参考电压5V;1.2V灵敏度对应加速度1g;1024为AD精度
  acceler=asin(acceler);        //反正弦求角度,不是弧度

  gyro*=0.00341;                //角速度系数:(3.14/180)* 100/512=0.01364;//(3.14/180)*(200*0.025)/1024*0.025既5/1024*0.025
                        //理解同上。最后求得角速度。 单位 :角度/秒

  Kalman_Filter(acceler,gyro);//卡尔曼滤波 (带入角度。角速度)得出的一样是角度和角速度。就当它是施密特触发器吧- -!
        //complement_filter(acceler,gyro);
}

出0入0汤圆

 楼主| 发表于 2010-8-20 09:18:38 | 显示全部楼层
我之前也计算过并建模,具体的已经忘记了,本帖子里有我发的建模的资料,参考老外的,采用的拉格朗日动力学方程,并用状态方程来求解的,你可以参考,你发的推导我暂时没时间细看,挺复杂的把我吓到了,我数学不好;你自己要是觉得没问题,到时候实践一下就知道了;

acceler=asin(acceler); //反正弦求角度,不是弧度:
加速度计测出来的是sin(theta),系统建模用的是角度值,所以必须用asin函数求角度theta;

Kalman_Filter(acceler,gyro);//卡尔曼滤波 (带入角度。角速度)得出的一样是角度和角速度。就当它是施密特触发器吧;
这个不能当做施密特触发器,详细的上网找一下资料,我在这个帖子里也有发关于卡尔曼滤波器的资料,很厉害的一个滤波器,效果很强大;

出0入104汤圆

发表于 2010-8-20 10:03:04 | 显示全部楼层
我在网上找到以下资料供参考
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
几天没来,没想到被置顶了~
什么资料都没发布,却被置顶,有点囧。。。
很多网友问过我一些代码问题,虽然想回复,但是因为硬件差距太大,真的不好说。
熟话说,授之以鱼,不如授之以渔。
我在这里就说下大概的流程吧。
整个系统分为三大部分。
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作用。
现在以能立住为目标。
//先吃饭~
//PS:刚参加了全国机械大赛黑龙江省赛,所以没时间过来写。结果还行,一等奖;小庆祝一下~^_^
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)协议通讯。

这就是我目前的整体做法。更多功能请网友们自行加载。
最后希望各位的小车被推倒后还能自己立起来。^_^
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

出0入0汤圆

发表于 2010-8-20 10:08:42 | 显示全部楼层
回复【219楼】zlstone
-----------------------------------------------------------------------

确实有点复杂。

现在知道为啥要用acceler=asin(acceler); 这个了。原来是建模时用到的。。

哎!~~MATLAB不会用啊。。你发的建模资料也只能有时间具体研究了。。惭愧。

实在是不甘心啊。。不会的东西太多了。悲哀。。

其他的什么都好弄。就是算法困扰死个人那。。

出0入0汤圆

发表于 2010-8-20 10:31:34 | 显示全部楼层
回复【220楼】andy 红日
-----------------------------------------------------------------------

受益匪浅。。多谢。。学习了

出0入0汤圆

发表于 2010-8-20 20:03:20 | 显示全部楼层
楼主请问下陀螺仪在哪儿买的?多少钱

出0入0汤圆

 楼主| 发表于 2010-8-20 21:35:28 | 显示全部楼层
回复【223楼】kai2529
-----------------------------------------------------------------------

好像没得卖的了,要不你联系下【207楼】 haleycui?

出0入0汤圆

 楼主| 发表于 2010-8-20 21:44:51 | 显示全部楼层
回复【221楼】icsundd
-----------------------------------------------------------------------

慢慢来吧,你知道我做这个车用了多久才完成吗?2年,所以,坚持必会有所获,不要太急功近利:-)

出0入0汤圆

发表于 2010-8-21 08:05:19 | 显示全部楼层
回复【223楼】kai2529
-----------------------------------------------------------------------

ewts86也应该可以替换的。。出了封装不一样 别的都一样。86的精度还要比82高。。

出0入0汤圆

发表于 2010-8-21 08:07:29 | 显示全部楼层
回复【225楼】zlstone
-----------------------------------------------------------------------

有韧性。。值得学习。。

我也一定要自己做出自己的车。。

出0入0汤圆

发表于 2010-8-21 10:22:58 | 显示全部楼层
回复【220楼】andy 红日
-----------------------------------------------------------------------

十分精彩的阐述

有个问题 L298驱动电机正反转调速 PWM信号接EN端 2个IN端控制方向 是这样的么
有的电路把PWM信号接IN端 这样感觉不好控制正反转

出0入0汤圆

发表于 2010-8-21 10:35:46 | 显示全部楼层
MAKR

出0入0汤圆

发表于 2010-8-24 00:35:03 | 显示全部楼层
STM32主控板做好了,现在板有一个三轴陀螺。

(原文件名:board.jpg)

出0入0汤圆

发表于 2010-8-24 08:15:36 | 显示全部楼层
回复【230楼】ggq71
-----------------------------------------------------------------------

那是不是得用到外部AD啊?

我先前也想弄个C8051F的板子 , 后来考虑是3.3的 所以暂时就做了一块M16的。等弄熟以后再弄C8051F的。

STM32目前还没用过,只有开发板一块。还没时间掌握呢。

三轴陀螺仪那里买的?什么价位?我看淘宝上就几家有 ,还好贵好贵。。

出0入0汤圆

发表于 2010-8-24 08:27:55 | 显示全部楼层
我手里的控制板也发出去做了。

剩下的电机驱动和传感器板子画成单面的了(有几条跳线)。准备自己热转印然后腐蚀了(做板子费钱)。

MCU还是M16 电机驱动H桥。H桥前级IR2103 。买的二手的减速电机15块钱,100转/分。暂时没加编码器。

加速度MMA2260D 陀螺仪EWTS86N。

如果这个弄好了 准备换带编码器的电机。。

出0入0汤圆

发表于 2010-8-24 08:32:05 | 显示全部楼层
现在就想弄几个便宜的三轴数字(供电3.3)陀螺仪。。

哪位能提供个连接啊。。找不到。。

- -!!

出0入0汤圆

发表于 2010-8-24 13:54:13 | 显示全部楼层
回复【231楼】icsundd  
回复【230楼】ggq71
-----------------------------------------------------------------------
那是不是得用到外部ad啊?
我先前也想弄个c8051f的板子 , 后来考虑是3.3的 所以暂时就做了一块m16的。等弄熟以后再弄c8051f的。
stm32目前还没用过,只有开发板一块。还没时间掌握呢。
三轴陀螺仪那里买的?什么价位?我看淘宝上就几家有 ,还好贵好贵。。
-----------------------------------------------------------------------

STM32有内部AD。我是在这里买的http://shop35582006.taobao.com/, 买到的是LYPR540AH,当时是200元。

出0入0汤圆

发表于 2010-8-24 15:28:33 | 显示全部楼层
回复【234楼】ggq71
-----------------------------------------------------------------------

谢了 找到了。。呵呵。

我看这个传感器的资料了。不大明白。。

输出的电压范围没看到啊。? 是0-3.2V的吗?

看起来很不错哦。。 能不能把你的封装传上来啊?

我也准备买两个玩玩。。

出0入0汤圆

发表于 2010-8-24 17:37:26 | 显示全部楼层
回复【235楼】icsundd  
-----------------------------------------------------------------------

我测试过,输出是0-VDD。这个PCB我做了10块,只有5块是飞针测试过的,如果需要,邮费到付可发给你(只有两块PCB可发)。

既然楼主已开源了最核心的程序,我也开源一下。

点击此处下载 ourdev_577472.pdf(文件大小:1.04M) (原文件名:20100818.pdf)

出0入0汤圆

发表于 2010-8-24 18:57:01 | 显示全部楼层
回复【236楼】ggq71
-----------------------------------------------------------------------

多谢你的好意了。。暂时还没买。送我就浪费了。

还是留给有用的人吧,,再次谢过。。

出0入0汤圆

发表于 2010-8-24 22:15:32 | 显示全部楼层
很不错~顶一个

出0入0汤圆

发表于 2010-8-24 23:06:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-25 20:58:41 | 显示全部楼层
楼主很厉害啊

出0入8汤圆

发表于 2010-8-27 10:37:52 | 显示全部楼层
jihao

出0入0汤圆

发表于 2010-8-27 11:01:10 | 显示全部楼层
不知道mark了没有,再mark

出0入0汤圆

发表于 2010-8-27 13:08:48 | 显示全部楼层
mark ,备用

出0入0汤圆

发表于 2010-8-27 19:16:33 | 显示全部楼层
回复【236楼】ggq71
-----------------------------------------------------------------------

这位仁兄,我想买那个三轴的陀螺仪 可是卖家说没有货了 ,汗。。

你还有没有其他的货源啊?淘宝上没看到其他家卖的。。郁闷了。

还有顺便问下各位,若我要用三轴陀螺仪检测物体的旋转角度,需要怎么做啊?

是将检测到的值换算成 角度/秒 然后积分运算得出角度吗?

比如 5MS 读取一次X,Y,Z轴的值分别为A°/秒,B°/秒,C°/秒。

以下举X轴为例:

那么我第一次得到的角度是 (5*A1/1000)°

第二次得到的角度是(5*A1/1000)°+(5*A2/1000)°

第三次得到的角度是(5*A1/1000)°+(5*A2/1000)°+(5*A3/1000)°
.....
第N次得到的角度是(5*A1/1000)°+(5*A2/1000)°+(5*A3/1000)°+。。。+(5*An/1000)°

是这样求得的角度吗?这样的误差是不是会很大呢?有何办法?

新人求教。。望前辈指教

出0入0汤圆

发表于 2010-8-27 20:06:32 | 显示全部楼层
ding

出0入0汤圆

 楼主| 发表于 2010-8-27 20:23:36 | 显示全部楼层
回复【244楼】icsundd
-----------------------------------------------------------------------

角度计算推荐用倾角传感器,那么角度值就不用累加,就不会有累积误差了;
加上角速度传感器,二者联合进行滤波,就能得出较准确的角度和角速度值;

出0入0汤圆

发表于 2010-8-27 21:08:08 | 显示全部楼层
回复【246楼】zlstone
-----------------------------------------------------------------------

回的真快。呵呵。多谢多谢。。这就找找倾角传感器的资料去。。

出0入0汤圆

发表于 2010-8-27 21:17:05 | 显示全部楼层
回复【246楼】zlstone
-----------------------------------------------------------------------

好像没有三轴的。只能测量相对于水平面的夹角奥。。

我想能测得三轴的旋转角度。。

求教。。

出0入0汤圆

发表于 2010-8-27 21:18:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-27 21:30:32 | 显示全部楼层
好文章,MARK!

出0入0汤圆

 楼主| 发表于 2010-8-27 23:03:01 | 显示全部楼层
竖直方向因为重力可以测得,要想测在水平面的转动了多少角度,可能需要地磁传感器来获取;

出0入0汤圆

发表于 2010-8-27 23:54:58 | 显示全部楼层
做个记号吧。顺便请教一下高手们:我学的是51单片机,做小车必须要学AVR单片机吗?是因为它的速度快还是资源多啊?谢谢啦

出0入0汤圆

发表于 2010-8-28 00:13:28 | 显示全部楼层
真好玩,我也想弄一个,等有空的时候

出0入0汤圆

发表于 2010-8-28 08:32:05 | 显示全部楼层
回复【251楼】zlstone
-----------------------------------------------------------------------

明白了,谢了。。若我要求的精度不用太高是不是就可以用

双轴加速度传感器(解决与水平方向的夹角)+一个单轴陀螺仪(解决水平面上的旋转)

加速度的读取数值反正弦求得角度, 陀螺仪 积分求得角度呢?

这样可行吗?

出0入0汤圆

发表于 2010-8-28 14:14:02 | 显示全部楼层
它的原理是什么呢。。。。 。

出0入0汤圆

 楼主| 发表于 2010-8-28 20:58:43 | 显示全部楼层
回复【252楼】wgm_123
-----------------------------------------------------------------------

51的我没用过,应该也可以吧:-)

出0入0汤圆

 楼主| 发表于 2010-8-28 21:01:58 | 显示全部楼层
回复【254楼】icsundd
-----------------------------------------------------------------------
加速度的读取数值反正弦求得角度是没错,但是它的瞬时响应较差,所以角度值要和陀螺仪(瞬时响应好,但有飘移)结合起来滤波处理,才能得到理想的结果(倾角与角速度);

出0入0汤圆

发表于 2010-8-29 20:14:17 | 显示全部楼层
回复【257楼】zlstone
-----------------------------------------------------------------------

收到,十分感谢您的回复。。

出0入0汤圆

发表于 2010-8-31 15:06:54 | 显示全部楼层
回复【216楼】zlstone
如果不太明白请看看自动控制方面的书籍
-----------------------------------------------------------------------
推荐一本行吗!谢谢啦

出0入0汤圆

发表于 2010-8-31 15:19:36 | 显示全部楼层
刚刚回来,楼主的贴吧还是那么红火

出0入0汤圆

 楼主| 发表于 2010-8-31 21:30:10 | 显示全部楼层
回复【259楼】kai2529
-----------------------------------------------------------------------
可能要花些时间去看哦,我这里上传两本吧
点击此处下载 ourdev_579174.pdf(文件大小:15.24M) (原文件名:现代控制工程_K.Ogata_第3版.pdf)
点击此处下载 ourdev_579175.pdf(文件大小:10.10M) (原文件名:自动控制实用教程-good.pdf)

出0入0汤圆

发表于 2010-9-1 08:28:20 | 显示全部楼层
回复【261楼】zlstone
-----------------------------------------------------------------------

程序调试中。。怎么搞的。。为啥测得的数据经过运算都是小数。。比如大约旋转10度的时候 得到的值是0.10XXXXXX

总差100倍。。  

- -|||

出0入0汤圆

发表于 2010-9-1 09:49:26 | 显示全部楼层
应该COOL啦

出0入0汤圆

发表于 2010-9-1 17:14:23 | 显示全部楼层
回复【215楼】icsundd
回复【214楼】zlstone  
-----------------------------------------------------------------------
学习了。不过还是有不明白的地方。
acceler=adport(2)+28; //角度校正  
这句话是不是在小车直立的时候测得的电压值与加速度传感器中介绍的zero g状态的差值?
若小于2.5v就另adport(2)+x=2500 若大于2.5v就令adport(2)-x=2500 这个x就是这里的28吗?
-----------------------------------------------------------------------

弱弱地请教,算式中的2500是什么意思,10位最多才1024吧。
还有:这句话中,“小车直立的时候测得的电压值”和“加速度传感器介绍的zero值”不是一样的吗,为什么还要求两个差值呢?我以为算式应看成acceler=adport(2)-(-28),-28就是加速度传感器的零状态电压对应的数字量-0.137V。我老是想成这样了,好心人给指点指点啊。555555

出0入0汤圆

发表于 2010-9-1 19:56:20 | 显示全部楼层
回复【216楼】zlstone
-----------------------------------------------------------------------
这个数学模型的资料很好啊,我想用这个模型试试看,但还有很多要学呢!你的问题我可以尝试回答下:过程二计算的机械功率表达式有车轮质量、车轮半径、车轮速度、未知的k1,k2,要是小车的轮子是类似于摩托车那种轮胎的话,还得自己想办法测转动惯量,但实际上车轮质量,转动惯量不用知道,那个机械功率表达式只是告诉我们电机至少要多大的功率才能将车体拉起来,也就是关于电机额定功率的选型,楼主已经用过2342L012这款17W、1.72N.m大扭矩的电机是可行的,那就不用去计算机械功率了。只需考虑过程一,如何用PWM实现电机转速加速度,那个k1应该要自己调参数的吧。

出0入0汤圆

发表于 2010-9-1 21:36:53 | 显示全部楼层
回复【261楼】zlstone
-----------------------------------------------------------------------

K_position=0.8 * 0.209;                //换算系数:(256/10) * (2*pi/(64*12))=0.20944;//256/10:电压换算至PWM,256对应10V;
K_angle=34 * 25.6;                //换算系数:256/10 =25.6;
K_position_dot=1.09 * 20.9;                //换算系数:(256/10) * (25*2*pi/(64*12))=20.944;
K_angle_dot=2 * 25.6;                //换算系数:256/10 =25.6;

0.8,34,1.09,2这几个是matlab建模结果吧,但是后面的系数换算真的看不懂。有三个问题不解:
1、电机满电压是12V吧,为什么是10V呢?
2、position和编码器输出脉冲数64*12又有什么关系?
3、为什么要引入position位置变量,只用angle和angle_dot和position_dot还不能准确定位PWM控制量吗?
4、这款单片机是8位PWM吗?如果是8位的,那么PWM=这个表达式会不会大于256,造成OCR1AL和OCR1BL这两个PWM寄存器的溢出?
菜鸟一个,不耻下问。
快10点了,明天继续研究程序,永远的经典!

出0入0汤圆

发表于 2010-9-1 21:46:18 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-9-1 21:50:31 | 显示全部楼层
回复【264楼】YISIMA
回复【215楼】icsundd  
回复【214楼】zlstone   
-----------------------------------------------------------------------  
学习了。不过还是有不明白的地方。  
acceler=adport(2)+28; //角度校正   
这句话是不是在小车直立的时候测得的电压值与加速度传感器中介绍的zero g状态的差值?  
若小于2.5v就另adport(2)+x=2500 若大于2.5v就令adport(2)-x=2500 这个x就是这里的28吗?  
-----------------------------------------------------------------------
弱弱地请教,算式中的2500是什么意思,10位最多才1024吧。
还有:这句话中,“小车直立的时候测得......
-----------------------------------------------------------------------

你的理解是正确的,adport(2)+x=2500 这里的2500我想只是作为一个例子吧,我的程序里没有这个的;

出0入0汤圆

 楼主| 发表于 2010-9-1 22:23:33 | 显示全部楼层
回复【266楼】YISIMA
回复【261楼】zlstone  
-----------------------------------------------------------------------
1、电机满电压是12V吧,为什么是10V呢?
2、position和编码器输出脉冲数64*12又有什么关系?
3、为什么要引入position位置变量,只用angle和angle_dot和position_dot还不能准确定位PWM控制量吗?
4、这款单片机是8位PWM吗?如果是8位的,那么PWM=这个表达式会不会大于256,造成OCR1AL和OCR1BL这两个PWM寄存器的溢出?
-----------------------------------------------------------------------
1:我做了一个比例的放大,因为电源的电压实际没那么大;
2:编码盘是12个脉冲每转,齿轮的减速比是64,所以...
3:位置变量是为了控制车速的,当车速增大时,电机输出的扭矩就小了,车辆就不会稳定了,所以一定要对车辆的位置和速度进行控制;
4:这个在子程序PWM_output()时对其进行了限制;

出0入0汤圆

发表于 2010-9-2 08:33:15 | 显示全部楼层
回复【264楼】YISIMA
-----------------------------------------------------------------------

回复【264楼】YISIMA

-----------------------------------------------------------------------  
学习了。不过还是有不明白的地方。  
acceler=adport(2)+28; //角度校正   
这句话是不是在小车直立的时候测得的电压值与加速度传感器中介绍的zero g状态的差值?  
若小于2.5v就另adport(2)+x=2500 若大于2.5v就令adport(2)-x=2500 这个x就是这里的28吗?  
-----------------------------------------------------------------------
弱弱地请教,算式中的2500是什么意思,10位最多才1024吧。
还有:这句话中,“小车直立的时候测得......
-----------------------------------------------------------------------

这里的2500是传感器zero状态2.5V,的确是个例子。实际准确值应该是512才对。这里。 AD读取的值还未换算成电压值。
因为512(AD读取值)*5(比较电压)/1024(精度) = 2.5V(转换后的电压值)

小车直立 与 加速度ZERO 肯定是不会完全一样的。因为再好的手工都无法将加速度传感器摆放或者焊接的那么完美。
也就是小车直立的时候加速度传感器读回来的值并不一定是512。。

不知道这样解释对与不对。个人理解。希望与大家伙探讨

出0入0汤圆

发表于 2010-9-2 08:36:53 | 显示全部楼层
回复【265楼】YISIMA
-----------------------------------------------------------------------
这个数学模型的资料很好啊,我想用这个模型试试看,但还有很多要学呢!你的问题我可以尝试回答下:过程二计算的机械功率表达式有车轮质量、车轮半径、车轮速度、未知的k1,k2,要是小车的轮子是类似于摩托车那种轮胎的话,还得自己想办法测转动惯量,但实际上车轮质量,转动惯量不用知道,那个机械功率表达式只是告诉我们电机至少要多大的功率才能将车体拉起来,也就是关于电机额定功率的选型,楼主已经用过2342l012这款17w、1.72n.m大扭矩的电机是可行的,那就不用去计算机械功率了。只需考虑过程一,如何用pwm实现电机转速加速度,那个k1应该要自己调参数的吧。
-----------------------------------------------------------------------

你说的那个数学模型是我发的那个?

我也想根据这个弄一下。越来越崇拜这些高手了。。

出0入0汤圆

发表于 2010-9-2 09:48:12 | 显示全部楼层
回复【271楼】icsundd
-----------------------------------------------------------------------

你说的那个数学模型是我发的那个?

我也想根据这个弄一下。越来越崇拜这些高手了。。
-----------------------------------------------------------------------
是的,自己的一点理解。不过你模型的自由度是2,如果只想让小车站起来,没有问题;但如果想实现转弯,应该用LZ的拉格朗日建模方法,它才是3D的建模。我也想用这个“入门”的模型试试。

出0入0汤圆

发表于 2010-9-2 10:13:06 | 显示全部楼层
回复【270楼】icsundd
-----------------------------------------------------------------------

小车直立 与 加速度ZERO 肯定是不会完全一样的。因为再好的手工都无法将加速度传感器摆放或者焊接的那么完美。
也就是小车直立的时候加速度传感器读回来的值并不一定是512。。

不知道这样解释对与不对。个人理解。希望与大家伙探讨
-----------------------------------------------------------------------
很详细的解释,谢谢!

出0入0汤圆

发表于 2010-9-2 10:58:18 | 显示全部楼层
回复【261楼】zlstone
-----------------------------------------------------------------------
1:我做了一个比例的放大,因为电源的电压实际没那么大;
2:编码盘是12个脉冲每转,齿轮的减速比是64,所以...
3:位置变量是为了控制车速的,当车速增大时,电机输出的扭矩就小了,车辆就不会稳定了,所以一定要对车辆的位置和速度进行控制;
4:这个在子程序PWM_output()时对其进行了限制;
-----------------------------------------------------------------------
LZ辛苦了,致敬!仔细研究了您的回答,1,3,4我懂了,4其实在PWM_ouput子程序中有。但是第2个还没有消化掉~杯具~,编码盘是12个脉冲每转,齿轮减速比是64,那说明齿轮每转一圈,编码器就能输出64*12个正脉冲,这个我知道,但是计算这个脉冲数对定位小车的位置有什么意义呢?那个2pi*25的25又是什么意思?实在不明白。不知道icsundd又是怎么理解的。

出0入0汤圆

发表于 2010-9-2 11:15:48 | 显示全部楼层
回复【273楼】YISIMA
-----------------------------------------------------------------------

呵呵。学习中。。

出0入0汤圆

发表于 2010-9-2 11:19:37 | 显示全部楼层
回复【274楼】YISIMA
-----------------------------------------------------------------------

那个2pi*25的25又是什么意思?

我的理解是25是半径而已、2πR嘛。。哈哈、

(25*2*pi/(64*12))就是求得单位位移咯。

一圈64*12个脉冲。周长25*2*π。那么一个脉冲所经过的位移就是。。。

出0入0汤圆

发表于 2010-9-2 19:54:17 | 显示全部楼层
不错哦
等我完工后也全部送出来

出0入0汤圆

 楼主| 发表于 2010-9-2 22:40:04 | 显示全部楼层
回复【276楼】icsundd
回复【274楼】yisima  
-----------------------------------------------------------------------
那个2pi*25的25又是什么意思?
我的理解是25是半径而已、2πr嘛。。哈哈、
(25*2*pi/(64*12))就是求得单位位移咯。
一圈64*12个脉冲。周长25*2*π。那么一个脉冲所经过的位移就是。。。

-----------------------------------------------------------------------

我的备注错了,应该是100*2*π,:-)因为之前的系统没改过来;是这样的,速度是每秒侦测100次,所以每次测得的值是0.01秒时间内的位移,要乘以100才是每秒钟的位移(速度),结果20.944没错哈;

出0入0汤圆

发表于 2010-9-3 08:36:41 | 显示全部楼层
回复【278楼】zlstone
-----------------------------------------------------------------------

原来如北

出0入0汤圆

发表于 2010-9-3 08:58:56 | 显示全部楼层
回复【278楼】zlstone
-----------------------------------------------------------------------

受教了,^_^。

出0入0汤圆

发表于 2010-9-5 11:24:43 | 显示全部楼层
很强悍,学习了!

出0入0汤圆

发表于 2010-9-6 21:31:18 | 显示全部楼层
怎么?没有套版出来吗?等着呢?

出0入0汤圆

发表于 2010-9-6 23:53:15 | 显示全部楼层
很强大,学习了~!

出0入0汤圆

发表于 2010-9-9 03:14:23 | 显示全部楼层
标记一下  明天来看

出0入0汤圆

发表于 2010-9-9 15:38:30 | 显示全部楼层
回复【261楼】zlstone
-----------------------------------------------------------------------

太感谢了!楼主

出0入0汤圆

发表于 2010-9-10 07:19:33 | 显示全部楼层
我采用了zlstone大大发布的自平衡小车代码,试做了一台自平衡小车.
我使用了arduino168.在制作过程中发现小车前后摇晃幅度较大.

我怀疑是电机问题,但我换过了3种电机,有便宜的玩具电机,以及不错的减速电机,我发现问题依旧.

根据公式Torque = AngleError * Kangle + AngularRate * Krate + VelocityError * Kvel + IntegratedVelocityError * Kivel

我使用单轴加速度计和单轴陀螺仪来计算AngleError 和AngularRate ,使用霍尔元件来计算速度和位移.

在调节过程中,我发现随着Kangle的增大,小车会变得"坚挺",不会轻易地前后摇摆, 但Kangle 的增大也会让小车出现剧烈的自激震动
随着 Krate 的增大,小车的自激震动会得到一定程度的缓解,但怎么也调整不到很稳定的水平.

我试过100Hz\200Hz\500Hz的计算/调节pwm频率,但效果不明显.

究竟是我的加速度计\陀螺仪不够好,还是我在计算AngleError 和AngularRate 的时候因为参数不对导致无法调节平稳?

请各位大大帮我解惑!

出0入0汤圆

 楼主| 发表于 2010-9-10 19:21:40 | 显示全部楼层
可能是你的电机轮速采样不够高,可以改一下速度滤波器的值:
        position_dot_filter*=0.9;                //车轮速度滤波
        position_dot_filter+=position_dot*0.1;       
可改为:
        position_dot_filter*=0.8;                //车轮速度滤波
        position_dot_filter+=position_dot*0.2;       
试一下;

出0入0汤圆

发表于 2010-9-11 08:50:42 | 显示全部楼层
再来留个脚印

出0入0汤圆

发表于 2010-9-11 19:14:48 | 显示全部楼层
回复【287楼】zlstone
可能是你的电机轮速采样不够高,可以改一下速度滤波器的值:
-----------------------------------------------------------------------

Zlstone大哥,我的小车昨天不稳定的原因部分找到了,我认为是IDG300的角速度输出转换到小车的弧度角速度的时候出了问题.
我用的是arduino,传感器3.3V输入电压,单片机提供1024的分辨率(也就是说AD读取值0~1023)

根据IDG330 Mannual, 2mv= 1度/s 的角速率,ad读数1024,3.3v,那么每读数对应 3.223mV,所以每读数对应3.223/2/180*PI= 0.028123弧度/秒

我昨天按照5V输入电压算的,0.0258246,所以出现了很难稳定的情况.


此外,我发现电机扭矩不随PWM线性增长的问题.我的减速电机在pwm较小的情况下无法正常输出扭矩.
所以我在pwm输出的时候,对计算出来的Torque值增加了一个较大的增量.(电机转动-256~256,我加了40,也就是说电机最小值是-40,40,而不是0.然后慢慢朝256增长.)

增加了这个值以后,AngleError的K参数就可以调低不少,这样能减少自激震动.


以上是我觉得可能引起不稳定的问题.其实现在小车还是不太稳定,做不到各位大大录像上那么稳定.
我今天会贴上我的源码和录像,请Zlstone大哥和论坛的其他各位大大_参考一下,看能不能将小车的稳定性进一步提高.

出0入0汤圆

发表于 2010-9-11 23:53:07 | 显示全部楼层
[2010-9-11-23-43]自平衡小车Codeourdev_582247LOC5S7.txt(文件大小:8K) (原文件名:[2010-9-11-23-43]自平衡小车Code.txt)

这是我的自平衡小车的完整代码,单片机是arduino 168.

代码同时也贴在这里:
static const double SEMICIRCLE_ARC = 57.29578;  /*半圆对应的弧度值*/
static const double GYRO_OPERATOR = 0.028123;  /*AD读取的陀螺仪数值对应的弧度算子,IDG330 Mannual, 2mv= 1度/s 的角速率,ad读数1024,3.3v,那么每读数对应 3.223mV,所以每读数对应3.223/2/180*PI= 0.028123弧度/秒
*/
/*kalman*/
static const double C_0 = 1;
static const double Q_angle=0.001, Q_gyro=0.003, R_angle=0.5, dt=0.005;//注意:dt的取值为kalman滤波器采样时间
double P[2][2] = {{ 1, 0 },
                  { 0, 1 }};
double Pdot[4] ={ 0,0,0,0};
double q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;
double angle, angle_dot;

/*sensor*/
double sensorPort[6] = { 0, 1, 2, 3, 4, 5};/*传感器地址,电路决定.accZ,gyroX, AD1, AD2, AD3, AD4*/
double sensorValue[6];/*传感器的返回值*/
/*传感器零点 0:Z轴(平行轴) 1:陀螺仪中点*/
double sensorZero[2] = {499,505};
double sensorAdjusted[2];/*传感器的返回值重整*/
//double provAngle;
/*moto*/
int E1 = 6;
int E2 = 9;
int M1 = 7;
int M2 = 8;
double deadAreaCompensation1 = 45,deadAreaCompensation2 = 35;
/*balance*/
double RATE[4] = {  0,0,0,0};/*公式中的4个变量*/
double  K[4] = {  60.45, 1.27, 125, 0.75};/*公式中的4个常量*/
double  K_AD[4] = {  1, 1, 1, 1};/*公式中的4个常量*/
double wheel_ls[7];/*左轮:0:编码器 1:位移(position) 2:position_dot 3:position_dot_filter 4:speedNeed 5:turnNeed 6:speedOutPut */
double wheel_rs[7];/*右轮:0:编码器 1:位移(position) 2:position_dot 3:position_dot_filter 4:speedNeed 5:turnNeed 6:speedOutPut */

double Torque;/*扭矩*/
unsigned int count,count2;
boolean OK=false;//这个是误差达到一定程度后的系统关闭开关.
int bf,X,Y;//从无线端发来的命令

/*kalman*/
/*angle_m:经过atan2(ax,ay)方法计算的偏角,弧度值
gyro_m:经过初步减去零点的陀螺仪角速度值,弧度值
*/
void Kalman_Filter(double angle_m,double gyro_m)
{
  angle+=(gyro_m-q_bias) * dt;
  angle_err = angle_m - angle;
  Pdot[0]=Q_angle - P[0][1] - P[1][0];
  Pdot[1]=- P[1][1];
  Pdot[2]=- P[1][1];
  Pdot[3]=Q_gyro;
  P[0][0] += Pdot[0] * dt;
  P[0][1] += Pdot[1] * dt;
  P[1][0] += Pdot[2] * dt;
  P[1][1] += Pdot[3] * dt;
  PCt_0 = C_0 * P[0][0];
  PCt_1 = C_0 * P[1][0];
  E = R_angle + C_0 * PCt_0;
  K_0 = PCt_0 / E;
  K_1 = PCt_1 / E;
  t_0 = PCt_0;
  t_1 = C_0 * P[0][1];
  P[0][0] -= K_0 * t_0;
  P[0][1] -= K_0 * t_1;
  P[1][0] -= K_1 * t_0;
  P[1][1] -= K_1 * t_1;
  angle        += K_0 * angle_err;
  q_bias += K_1 * angle_err;
  angle_dot = gyro_m-q_bias;//也许应该用last_angle-angle
}

void do_balance() {
  while(Serial.available() > 0){//遥控器比例控制,X和Y各16个值,整合成一个BYTE.这样最简单,一个字节就能控制了.
    bf = Serial.read();
  }
  if(bf!=-1){//计算命令速度
      Y = bf/16;//bf最大255
      X = bf%16;//
  }
  
  wheel_ls[4] = (8>X)?1:(8==X?0:-1);//前进后退
  wheel_rs[4] = (8>X)?1:(8==X?0:-1);
  
  wheel_ls[5] = (8-Y)*16;//转弯
  wheel_rs[5] = (Y-8)*16;
  
  
  sensorValue[0] = analogRead(sensorPort[0]);//加速度:水平方向
  sensorValue[1] = analogRead(sensorPort[1]);//旋转(陀螺)
  sensorValue[2] = analogRead(sensorPort[2]);//旋钮1
  sensorValue[3] = analogRead(sensorPort[3]);//旋钮2
  sensorValue[4] = analogRead(sensorPort[4]);//旋钮3
  sensorValue[5] = analogRead(sensorPort[5]);//旋钮4

  //算出整理过的零点值
  sensorAdjusted[0] = sensorValue[0] - sensorZero[0];//水平方向的加速度值
  if(abs(sensorAdjusted[0]) > 70)//如果倾斜到一定程度,就停机
  {
    OK = false;
    sensorAdjusted[0] =sensorAdjusted[0]>0?70:-70;
  }  
  sensorAdjusted[1] = sensorZero[1] - sensorValue[1];/*陀螺仪读出的角速度值,减去初始零点*/

  
  /*根据可变电阻改变K的倍数*/
  //deadAreaCompensation = (sensorValue[4]+1)/10.24;
  //K_AD[0] = (sensorValue[2]+1)/256;//102.4;/*值在0.001~10之间变化.在AD=100的时候接近1 */
  //K_AD[1] = (sensorValue[3]+1)/256;//102.4;
  //K_AD[2] = (sensorValue[4]+1)/256;//102.4;
  //K_AD[3] = (sensorValue[5]+1)/256;//102.4;
  
  /*根据上一周期Torqu的值统计轮子转动积分*/
  wheel_ls[2] = Torque > 0?wheel_ls[0]:-wheel_ls[0];
  wheel_rs[2] = Torque > 0?wheel_rs[0]:-wheel_rs[0];
  wheel_ls[0] = wheel_rs[0] = 0;
/*************** balance *********************************************/

  /*小车初始状态*/
  {
    if(!OK)
    {
      if(abs(sensorAdjusted[0]) <= 3)//将小车竖立起来时就启动
      {
        count=0;
        OK = true;
      }
      for(int i = 0; i <7;i++)//不启动的时候,所有积分值都清零
      {
        wheel_ls = 0;
        wheel_rs = 0;
      }
    }
  }

  /*balance*/
  {
    /*GYRO_OPERATOR = 0.028123 AD读取的陀螺仪数值对应的弧度算子*/
    Kalman_Filter(atan2(sensorAdjusted[0], sqrt(6400-sensorAdjusted[0]*sensorAdjusted[0])), sensorAdjusted[1] * GYRO_OPERATOR);//6400:因为只有一轴加速度计,所以虚拟一个斜边.这可能是小车晃动的原因之一
    RATE[0] = angle * SEMICIRCLE_ARC;//SEMICIRCLE_ARC=57.29578;  /*半圆对应的弧度值*/
    RATE[1] = angle_dot * SEMICIRCLE_ARC;
    //RATE[1] = RATE[0] - provAngle;
    //provAngle = RATE[0];
  }

  /*计算速度  double wheel_ls[8];  0:编码器累加 1:位移(position) 2:position_dot 3:速度(position_dot_filter) 4:speedNeed 5:turnNeed 6:speedOutPut
  */
  {
    wheel_ls[3] *= 0.95;              /*车轮速度滤波,wheel_ls[3] : position_dot_filter*/
    wheel_ls[3] += wheel_ls[2]*0.05;  /*wheel_ls[2] : position_dot*/
    wheel_ls[1] += wheel_ls[3];       /*wheel_ls[1] : position*/
    wheel_ls[1] += wheel_ls[4];       /*wheel_ls[4] : speedNeed*/
    wheel_ls[1] = max(-50, wheel_ls[1]);
    wheel_ls[1] = min(50, wheel_ls[1]);
    /*
    wheel_rs[3] *= 0.85;
    wheel_rs[3] += wheel_rs[2]*0.15;
    wheel_rs[1] += wheel_rs[3];
    wheel_rs[1] += wheel_rs[5];
    wheel_rs[1] = max(-50, wheel_rs[1]);
    wheel_rs[1] = min(50, wheel_rs[1]);
*/
    RATE[2] = wheel_ls[3];//速度--滤波过了
    RATE[3] = wheel_ls[1];//位置
  }

  /*Torque 综合所有参数算出扭矩*/
  {
    Torque = (RATE[0]+(8-X)) * K[0] * K_AD[0] + RATE[1] * K[1] * K_AD[1] + RATE[2] * K[2] * K_AD[2] + RATE[3] * K[3]* K_AD[3];
   
    //根据扭矩算轮子的命令值
    wheel_ls[6] = abs(Torque+wheel_ls[5]) + deadAreaCompensation1;//wheel_ls[6]:扭矩输出   wheel_ls[5]:Turn_Need   deadAreaCompensation1:左轮的死区补偿
    wheel_ls[6] = min(255, wheel_ls[6]);//限制最大扭矩255
    wheel_ls[6] = OK?wheel_ls[6]:0;//当机体倾斜角大于60度的时候停止

    wheel_rs[6] = abs(Torque+wheel_rs[5]) + deadAreaCompensation2;
    wheel_rs[6] =  min(255, wheel_rs[6]);
    wheel_rs[6] = OK?wheel_rs[6]:0;
  }

  if(Torque > 0)
  {
    digitalWrite(M2, HIGH);
    digitalWrite(M1, LOW);
  }
  else
  {
    digitalWrite(M2, LOW);
    digitalWrite(M1, HIGH);
  }
  analogWrite(E1, wheel_ls[6]); //PWM调速a==0-255
  analogWrite(E2, wheel_rs[6]);
}
void do_msg(){
  if(count%100==0)//0.5秒刷新显示屏
  {
    Serial.print("$CLEAR\r\n");
    Serial.print("$GO 1 1\r\n");
    Serial.print("$PRINT ");

    Serial.print(wheel_ls[1]);
    Serial.print(" ");
    Serial.print(wheel_ls[3]);
    Serial.print("\r\n");

    Serial.print("$GO 2 1\r\n");
    Serial.print("$PRINT ");
    Serial.print(wheel_ls[5]);
    Serial.print(" ");
    Serial.print(wheel_rs[5]);
    Serial.print("\r\n");
  }
}
/***************** setup-loop *************************************************/
void setup() {
  count=0;
  X=Y=8;
  bf=-1;
  //init motos
  for (int i = 6; i <= 9; i++) {
    pinMode(i, OUTPUT);
  }
  Serial.begin(9600);//115200);
  analogReference(EXTERNAL); //设置模拟输入为外部参考3.3V

  attachInterrupt(0, blinkone, CHANGE); //设置为0号中断,中断函数blink,触发方式为CHANGE
  attachInterrupt(1, blinktwo, CHANGE); //设置为0号中断,中断函数blink,触发方式为CHANGE
}
void blinkone()//中断函数
{
  wheel_ls[0] ++;
}
void blinktwo()//中断函数
{
  wheel_rs[0] ++;
}

void loop() {
  do_balance();//计算平衡
  do_msg();
  delay(3);
  count++;
  if(count>=60000)
    count=0;
}

出0入0汤圆

发表于 2010-9-12 00:37:23 | 显示全部楼层
这些是我的小车的图片.小车是使用dfrobot的4WD改装的,换装了大轮子\好点的减速电机\加装了1602显示器等.电池是12V的.
这个小车都是用买来的成品稍加改装,其实可以不换轮子和电机,因为我已经肯定摇晃的问题不是电机和轮子引起的...
小车也没用自制的电路板,也没有焊接任何飞线在电路板上.缆线都是插接的.
无线模块使用了很奢侈的XBee pro.其实没必要,只是很早以前买的,不想让它们继续落灰罢了.

Zlstone大哥,各位论坛上的大大们,一定要帮忙啊~为什么俺的小车使劲的晃呀...


(原文件名:1.jpg) 小车俯视图


(原文件名:2.jpg) 小车站立,可以看到许多灯都亮着


(原文件名:3.jpg) 这是遥控器


(原文件名:4.jpg) 小车和遥控器


(原文件名:5.jpg) 电机轴末端的小磁铁和霍尔元件


(原文件名:6.jpg) 电路板

出0入0汤圆

发表于 2010-9-12 13:50:28 | 显示全部楼层
双轮自平衡小车视频 2010-9-12日拍摄.
主要问题:晃动 不稳定 前后行进的时候不顺畅 转弯不够稳定 在前进或后退的时候有时会一直加速到极限后跌倒

http://v.youku.com/v_show/id_XMjA1Nzg5OTg0.html

出0入0汤圆

 楼主| 发表于 2010-9-12 16:38:29 | 显示全部楼层
我想也许有以下影响:
1:你的电机转一圈才采集一次脉冲,我的是每圈12个脉冲;(试一下不用采样轮速,用PWM代替)
2:我的车轮很光滑的,没有你那样的颗粒;
3:也许你的PWM的初值真的有点大,适当调小点看看;
4:转弯是因为我的程序没有采用PID控制,你可以研究看看哦:-)

出0入0汤圆

发表于 2010-9-13 16:23:31 | 显示全部楼层
回复【290楼】qhunter
-----------------------------------------------------------------------

没看到有角度校正啊。

该不会在小车还没有直立的时候 系统就已经开始工作了吧?

那样加速度的变化非常大,也许会导致不停的抖动呢?

出0入0汤圆

发表于 2010-9-13 16:25:39 | 显示全部楼层
回复【293楼】zlstone
-----------------------------------------------------------------------

看图片好像真是一圈“霍尔”一次的奥。。

检测太少了吧?

出0入0汤圆

发表于 2010-9-13 19:46:17 | 显示全部楼层
回复【294楼】icsundd
回复【290楼】qhunter  
-----------------------------------------------------------------------
没看到有角度校正啊。
该不会在小车还没有直立的时候 系统就已经开始工作了吧?
那样加速度的变化非常大,也许会导致不停的抖动呢?
-----------------------------------------------------------------------

有陀螺的校正,否则根本站不起来
确实系统在没有直立的时候就已经在计算卡尔曼滤波了.不过收敛的较快,到不至于因为这个导致晃动.
这个晃动需要我更深入的研究.因为万一地面不平,小车晃动就很大,这样子也不好.

出0入0汤圆

发表于 2010-9-13 21:45:23 | 显示全部楼层
mark  自平衡小车  强贴

出0入0汤圆

发表于 2010-9-13 21:57:12 | 显示全部楼层
好贴

出0入104汤圆

发表于 2010-9-14 11:00:57 | 显示全部楼层
【290楼】 qhunter 到以下网站看制作

http://letsmakerobots.com/node/8261

源程式
http://code.google.com/p/protobot8261/source/browse/trunk/

你的陀螺器及加速度计是否这个?

(原文件名:IMU-v300.jpg)

出0入0汤圆

发表于 2010-9-14 12:29:30 | 显示全部楼层
回复【299楼】andy 红日
----------------------------------------

确实是这个传感器元件,不过我的那个已经烧毁了一半,只剩下1轴加速度和1轴陀螺,这也是小车不稳的原因,因为只有X轴加速度没有Y轴,所以只好用sqrt(1G加速度AD值的平方-AccX*AccX)来代替Y轴加速度.

andy给的网址真不错,我回去好好啃啃.

ourdev的四轴飞行源代码是更好的教材,我正在慢慢啃...

出0入104汤圆

发表于 2010-9-16 06:34:47 | 显示全部楼层
diy 车


(原文件名:车.JPG)

出0入0汤圆

发表于 2010-9-16 07:57:52 | 显示全部楼层
动作很快啊  羡慕加佩服!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-28 23:48

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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