搜索
bottom↓
回复: 39

两轮小车走直线是要分别对左右两个电机进行PID控制吗

[复制链接]

出0入0汤圆

发表于 2012-7-28 08:15:11 | 显示全部楼层 |阅读模式
我正在做一个小车,前面一个轮子是万向轮做的,后面两个轮子分别用两个电机进行控制,
现在的情况是左右两个电机给相同大小的pwm,但是两个电机稳定后的转速不同,
我的电机转速测量是用光电开关测频率的方法得到的,用示波器检测过比较准确的,
现在通过这样一个算法:
如果左轮比右轮速度快,那么左轮pwm-1,右轮pwm+1,空载的情况下,小车左右两个轮子速度接近,一会儿左面的大些,一会儿右面的大些,但放到地上以后就直接跑偏了,
我现在想知道如果我用PID算法的话,是不是分别对两个小车进行PID控制呢?

出0入0汤圆

发表于 2012-7-28 08:25:27 | 显示全部楼层
用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。

出0入0汤圆

 楼主| 发表于 2012-7-28 08:29:59 | 显示全部楼层
tiancaigao7 发表于 2012-7-28 08:25
用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。 ...


就是给一个转速差定值,然后用PID去控制使转速差趋于这个定值?楼主,我是新手,您仔细说说,得到的PID控制参量叠加在哪一个轮子的pwm上呢?现在就是想找一个恒定的转速,左右两轮转速不一样啊

出0入0汤圆

发表于 2012-7-28 09:40:24 | 显示全部楼层
恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候PID控制器会降低左轮速度(假设PWM-n),同时增加右轮速度(假设PWM+n)。这样就可以实现左转,但是同时小车还需要前进,因此在保证小车的前进速度需要给PWM M,因此左轮的PWM占空比为M-n,右轮为M+n这样就能保证小车在前进过程中,左转。而PID控制器控制的是n的大小。当然如果你需要同时控制前进速度的话,就需要增加一个PID控制器。

出0入0汤圆

发表于 2012-7-28 22:10:05 | 显示全部楼层
我最近也在做这个,请问有没有相关例程可以参考一下?

出0入0汤圆

 楼主| 发表于 2012-7-29 09:32:16 | 显示全部楼层
tiancaigao7 发表于 2012-7-28 09:40
恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候PID控制器会降低左 ...

其实,我还是不大懂,您看一下,我是这个意思,我想把做右轮速度偏差控制成0,所以在
void IncPIDInit(void)
{
        sptr->SumError=0;
        sptr->LastError=0;
        sptr->PrevError=0;
        sptr->Proportion=3;
        sptr->Integral=0;
        sptr->Derivative=0;
        sptr->SetPoint=0;
}

int IncPIDCalc(int NextPoint)
{
        int iError,iIncpid;
        iError=sptr->SetPoint-NextPoint;
        iIncpid=sptr->Proportion*iError        -sptr->Integral*sptr->LastError+sptr->Derivative*sptr->PrevError;
        sptr->PrevError=sptr->LastError;
        sptr->LastError=iError;
        return(iIncpid);
}
里面 SetPoint=0;
然后我随便用一个参数sptr->Proportion=3,这样我每次采样50ms,然后把数据送到上面的结构体里计算,得到iIncpid我要怎么处理,它对应的到底是什么,我是直接用这个参数当做pwm是用还是左轮的pwm+iIncpid当做pwm ,这上面输入的Nextpoint是当前的左轮减去右轮的差值

希望您帮一下,我不大懂怎么去控制这个

出0入0汤圆

发表于 2012-7-29 09:43:46 | 显示全部楼层
同求高人详解该问题...

出0入0汤圆

发表于 2012-7-29 09:58:42 | 显示全部楼层
首先你的PID公式有问题,看你的公式,用的应该是位置式PID,但是这个PID的积分应该是历次的偏差的积分。如果你用的是相对PID,那么比例部分,应该是本次偏差和上一次偏差之差。另外,在你这里,PID的输出当成PWM占空比的变化量是可以的,不过P I D这三个参数需要自己调试,这个只能通过实验来看自己调整。

出0入0汤圆

 楼主| 发表于 2012-7-29 11:15:55 | 显示全部楼层
tiancaigao7 发表于 2012-7-29 09:58
首先你的PID公式有问题,看你的公式,用的应该是位置式PID,但是这个PID的积分应该是历次的偏差的积分。如 ...

谢谢您,那错误我明白了,那您看我这个问题适合用增量式还是位置式?

出0入0汤圆

发表于 2012-8-11 16:51:46 | 显示全部楼层
tiancaigao7 发表于 2012-7-28 09:40
恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候PID控制器会降低左 ...

控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定是6,还是会在6±1波动,1s计算500次,误差累积还是相当快,转一圈最大就可能有500个脉冲误差,一圈总共才700个脉冲。如何才能稳定地控制?

出0入0汤圆

发表于 2012-8-11 16:53:53 | 显示全部楼层
werren 发表于 2012-8-11 16:51
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...

对了,我点击控制的pwm使用100hz,想起来好像跟这个关系很大。

出0入0汤圆

发表于 2012-8-21 17:05:36 | 显示全部楼层
werren 发表于 2012-8-11 16:51
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...

我想问您一下 编码器的数据 是怎么得到的呢?

出0入0汤圆

发表于 2012-8-24 10:25:43 | 显示全部楼层
ldh0504 发表于 2012-8-21 17:05
我想问您一下 编码器的数据 是怎么得到的呢?

ETR 外部脉衝計數(紅外對射管+齒輪盤輸出)得到。每隔2ms就去讀取一次。

出0入0汤圆

发表于 2012-9-23 09:34:15 | 显示全部楼层
tiancaigao7 发表于 2012-7-28 08:25
用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。 ...


如果这样的话只有一个轮子性能好的。控制速度差只能一个轮子跟另外一个轮子。
/ ==============        car  blance modulation       
// ==============   car  blance modulation       
// =======================================================  PID compute       
                        if(motion)
                        {
                                IRSensor_ON();                                                    //turn on the ir sensor
                    pwm = IncPIDCalc(&A,(LDelta+RDelta)/2);
                                dDpwm = LDelta-RDelta;           //两轮速度差
                                dtpwm = IncPIDCalc(&B,dDpwm);
                                Lpwm = pwm+dtpwm;
                                if(Lpwm>250)Lpwm = 250;
                                if(Lpwm<0)Lpwm = 0;

                                Rpwm = pwm-dtpwm;
                                 if(Rpwm>250)Rpwm = 250;

                                if(Rpwm<0)Rpwm = 0;
                                HB = 1;
                        }       
// =======================================================PID compute
// ==========================================movement handle
                    Pre_motion = motion;      //记录上一次的运动状态,若有改变运动状态则根据相应的动作来协调计数
        if(motion==FORWARD)
        CarMove(250+Lpwm,250+Rpwm);//<<======用手抓左轮,这样结果是左轮pid马上起作用,控制速度差;用手抓右轮左轮却偏快了。原因是左轮明显右边轮子慢下来。有没有办法右轮也ok?

出0入0汤圆

发表于 2012-9-23 10:23:00 | 显示全部楼层
顶一下让更多的高手出来参加讨论。

出0入0汤圆

发表于 2012-9-23 14:29:30 | 显示全部楼层
werren 发表于 2012-9-23 09:34
如果这样的话只有一个轮子性能好的。控制速度差只能一个轮子跟另外一个轮子。
/ ==============        car  bla ...

你的目的是要控制小车走直线,而不是控制两个轮子速度相同,我说的分别施加转速差,输入应该是你的小车的偏角,而不是轮子的速度差。

出0入0汤圆

发表于 2012-10-11 01:40:33 | 显示全部楼层
werren 发表于 2012-8-11 16:51
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...

可以采用位置差(及两轮行走距离差)作为误差来进行PID运算,最近我也在做

出0入0汤圆

发表于 2012-10-11 12:08:25 | 显示全部楼层
ldh0504 发表于 2012-8-21 17:05
我想问您一下 编码器的数据 是怎么得到的呢?

我现在用的传感器是用角度传感器和 加速度传感器融合一体的~  现在角度已经测出来了 加速度求出来了 之后PID部分 怎么样控制 PID 我用位置式的PID 电机是用12V的直流电机 没有用到编码器 请问一下  电机输出的PID 应该怎么去调节呢 您用的PID 是什么式的呢

出0入0汤圆

发表于 2012-10-11 15:30:25 | 显示全部楼层
风烟雨风 发表于 2012-10-11 01:40
可以采用位置差(及两轮行走距离差)作为误差来进行PID运算,最近我也在做 ...

是 的,我後來也是這樣處理,這樣就沒有累積誤差。

出0入0汤圆

发表于 2012-10-11 22:21:57 | 显示全部楼层
werren 发表于 2012-10-11 15:30
是 的,我後來也是這樣處理,這樣就沒有累積誤差。

但是现在一直没有调出来,不知道怎么调试参数   急求啊   希望指教一下

出0入0汤圆

发表于 2012-10-16 08:53:45 | 显示全部楼层
风烟雨风 发表于 2012-10-11 22:21
但是现在一直没有调出来,不知道怎么调试参数   急求啊   希望指教一下


調試時候可以將PID計算結果實時show出來(這樣就可以直觀看出數據變化,然後需要將參數加大還是減小),先調節P再調節I。
只用P的話已經能夠達到不錯的效果了。你可以試試先往大的調,能穩定轉起來后再將P調小,直到轉速穩定或者振盪,加入I參數。再湊一下基本上可以用了。

以上是我的調試經驗。。。。我也是第一次用PID

出0入0汤圆

发表于 2012-10-18 17:07:31 | 显示全部楼层
werren 发表于 2012-10-16 08:53
調試時候可以將PID計算結果實時show出來(這樣就可以直觀看出數據變化,然後需要將參數加大還是減小), ...

你调的误差有多少
能仔细请教一下吗
我的QQ号是505800119

出0入0汤圆

发表于 2012-10-19 13:11:53 | 显示全部楼层
风烟雨风 发表于 2012-10-18 17:07
你调的误差有多少
能仔细请教一下吗
我的QQ号是505800119

誤差跟你的轉速設定有關係,我的電機是經過變速箱的。但是我測試的是沒有經過變速箱的原始轉速。我使用外部中斷,上升沿和下降沿都能觸發中斷。車輪轉一圈可以計數約700個脉衝,中斷上升下降沿都計數可以計到1400次。我10ms 讀一次轉速,將讀出轉速做參數給pid計算,計算結果直接作為pwm控制電機。假設我設定速度是每10ms  20個脉衝  那麼基本上可以穩定在20±3   ,手去抓車輪 機會不會感到轉速慢下來,扭力很大,看串口輸出結果也是在短時間內看到比較大的轉速波動而已。

出0入0汤圆

发表于 2012-10-20 16:37:05 | 显示全部楼层
我的情况跟你差不多,车轮转一圈大约700个脉冲,然后我是记700次,采样周期是20ms.
现在主要情况是我使用PID调时,(不放在地上)左右轮差距最多为20左右,但是放在地上后偏差很大。
不知道你的在正常情况下左右轮计数的差值最大大概多大?

出0入0汤圆

发表于 2012-10-20 16:37:28 | 显示全部楼层
werren 发表于 2012-10-19 13:11
誤差跟你的轉速設定有關係,我的電機是經過變速箱的。但是我測試的是沒有經過變速箱的原始轉速。我使用外 ...

我的情况跟你差不多,车轮转一圈大约700个脉冲,然后我是记700次,采样周期是20ms.
现在主要情况是我使用PID调时,(不放在地上)左右轮差距最多为20左右,但是放在地上后偏差很大。
不知道你的在正常情况下左右轮计数的差值最大大概多大?

出0入0汤圆

发表于 2012-10-22 09:05:26 | 显示全部楼层
风烟雨风 发表于 2012-10-20 16:37
我的情况跟你差不多,车轮转一圈大约700个脉冲,然后我是记700次,采样周期是20ms.
现在主要情况是我使用 ...

可能我們的做法還是有差異。
PID我分為兩部份 一部份計算控制小車的前進速度的pwm ,一部份做左右輪子平衡的pwm,我記得大概前進的時候是一般是在±4內波動,因為我是用累積的,所以沒有誤差積分。
但是這個情況下不一定能走直,想了好久,加了一個平衡誤差的虛參數,終於走直線了。見一下部份代碼
                        if(motion)
                        {
                    pwm = IncPIDCalc(&SPEED,(LDelta+RDelta)/2);        //小车恒定速度计算
                               
                                switch(motion){
                                case FORWARD:dSPEED.SetPoint = 0x00;                                                        //DIF是纠正参数  ,在小车前进或后退,没有传感器的状况下为保证
                                         dTotal = TotalCntL*DIFF- TotalCntR;                                                //运动路径为直线,必须做平衡去掉机械误差       
                                         //dTotal = TotalCntL*Line- TotalCntR;
                                         dtpwm = dtIncPIDCalc(&dSPEED,dTotal/8);break;                                //切此处用的速度计算是使用当前计数总和减去上一次计数总和,避免误差的累积                                       
                                case REVERSE:dSPEED.SetPoint = 0x00;
                                         dTotal = TotalCntL*DIFR- TotalCntR;                                                //DIF是纠正参数
                                         dtpwm = dtIncPIDCalc(&dSPEED,dTotal/8);break;
                                default:
                                          dTotal = TotalCntL- TotalCntR;
                                          dSpd = LDelta-RDelta;                                                                                //左右转速差值
                                          dtpwm = dtIncPIDCalc(&dSPEED,dSpd);break;
                                }               
                                Lpwm = pwm+dtpwm;                                                        //恒定速度控制+差分速度控制
                                if(Lpwm>250)Lpwm = 250;                                                //小车PWM的控制范围为0-250 所以要做限制
                                if(Lpwm<0)Lpwm = 0;

                                Rpwm = pwm-dtpwm;
                                 if(Rpwm>250)Rpwm = 250;
                                if(Rpwm<0)Rpwm = 0;                                                        //使能H桥
                                HB = 1;
                        }
                        if(!(motion&0x0f))
                                HB = 0;//如果不在运动状态就把H桥进入休眠,避免电机狂转




                                                                                ……

出0入0汤圆

发表于 2012-10-29 19:35:49 | 显示全部楼层
果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了

出0入0汤圆

发表于 2012-11-5 22:37:55 | 显示全部楼层
werren 发表于 2012-10-22 09:05
可能我們的做法還是有差異。
PID我分為兩部份 一部份計算控制小車的前進速度的pwm ,一部份做左右輪子平 ...

果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了

出0入0汤圆

发表于 2012-11-6 08:46:10 | 显示全部楼层
风烟雨风 发表于 2012-11-5 22:37
果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了 ...

標準的增量式PID 寫法
int dtIncPIDCalc(PID *sptr,int NextPoint)
{
  register int iError, iIncpid;
   //当前误差
  iError = sptr->SetPoint - NextPoint;
   //增量计算

  iIncpid  = sptr->Proportion * iError               //E[k] 项
            - sptr->Integral   * sptr->LastError     //E[k-1]项
            + sptr->Derivative * sptr->PrevError;   //E[k-2]项
   //存储误差,用于下次计算
  sptr->PrevError = sptr->LastError;
  sptr->LastError = iError;
   //返回增量值
return(iIncpid);
}
//////////////////////////////////////////////////////////////////////////
        //数据结构
        typedef struct PID
        {
          int  SetPoint;     // 设定目标 Desired Value
          long  SumError;                //误差累计  
         
          float  Proportion;         // 比例常数 Proportional Const
          float  Integral;           // 积分常数 Integral  Const
          float  Derivative;         // 微分常数 Derivative Const
       
          int LastError;               //Error[-1]
          int PrevError;               //Error[-2]
        } PID;

出0入0汤圆

发表于 2012-11-7 00:50:11 | 显示全部楼层
werren 发表于 2012-11-6 08:46
標準的增量式PID 寫法
int dtIncPIDCalc(PID *sptr,int NextPoint)
{

恩  多谢了
我的小车跟你的基本要求一样。就是让小车能沿直线行走固定的距离。
现在走直线问题不大,行走固定的步数又是新问题了,不知能否指教一下?

出0入0汤圆

发表于 2012-11-9 10:08:08 | 显示全部楼层
风烟雨风 发表于 2012-11-7 00:50
恩  多谢了
我的小车跟你的基本要求一样。就是让小车能沿直线行走固定的距离。
现在走直线问题不大,行走 ...

我的做法是設置計數比如兩萬次走直線,然後測量實際走的距離最後求平均每計數一次小車移動的距離,把這個當做參數來用咯。

出0入0汤圆

发表于 2012-11-9 11:43:30 | 显示全部楼层
我也想知道,两电机如果其中一个电机在运动过程中遇到有障碍物,怎样做同步控制,就是一个慢了另外一个快的怎样慢下来

出0入0汤圆

发表于 2012-11-10 09:21:06 | 显示全部楼层
werren 发表于 2012-11-9 10:08
我的做法是設置計數比如兩萬次走直線,然後測量實際走的距離最後求平均每計數一次小車移動的距離,把這個 ...

太谢谢了   麻烦你这么多

出0入0汤圆

发表于 2012-11-10 09:22:27 | 显示全部楼层
dmjkun 发表于 2012-11-9 11:43
我也想知道,两电机如果其中一个电机在运动过程中遇到有障碍物,怎样做同步控制,就是一个慢了另外一个快的 ...

我是用 光电编码器检测,然后调整PWM参数

出0入0汤圆

发表于 2013-10-4 22:24:17 | 显示全部楼层
werren 发表于 2012-10-22 09:05
可能我們的做法還是有差異。
PID我分為兩部份 一部份計算控制小車的前進速度的pwm ,一部份做左右輪子平 ...

看了你们的讨论,我感觉收获很大啊!太感谢了!
但是我有个问题,IncPIDCalc(……)和dtIncPIDCalc(……)有什么区别吗,难道不是增量式PID调节?能看看这个函数的具体定义吗? 谢谢了!

出0入0汤圆

发表于 2013-12-11 23:44:23 | 显示全部楼层
mark mark mark

出0入0汤圆

发表于 2014-4-17 12:50:20 | 显示全部楼层
cool 收藏,正好需要用

出0入0汤圆

发表于 2016-7-4 16:32:52 | 显示全部楼层
mark下,以后慢慢琢磨,正在想这个问题,谢谢

出0入0汤圆

发表于 2016-7-6 09:17:50 | 显示全部楼层
好贴  mark一下

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-20 12:15

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

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