两轮小车走直线是要分别对左右两个电机进行PID控制吗
我正在做一个小车,前面一个轮子是万向轮做的,后面两个轮子分别用两个电机进行控制,现在的情况是左右两个电机给相同大小的pwm,但是两个电机稳定后的转速不同,
我的电机转速测量是用光电开关测频率的方法得到的,用示波器检测过比较准确的,
现在通过这样一个算法:
如果左轮比右轮速度快,那么左轮pwm-1,右轮pwm+1,空载的情况下,小车左右两个轮子速度接近,一会儿左面的大些,一会儿右面的大些,但放到地上以后就直接跑偏了,{:mad:}
我现在想知道如果我用PID算法的话,是不是分别对两个小车进行PID控制呢?{:3_57:} 用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。 tiancaigao7 发表于 2012-7-28 08:25 static/image/common/back.gif
用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。 ...
就是给一个转速差定值,然后用PID去控制使转速差趋于这个定值?楼主,我是新手,您仔细说说,得到的PID控制参量叠加在哪一个轮子的pwm上呢?现在就是想找一个恒定的转速,左右两轮转速不一样啊 恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候PID控制器会降低左轮速度(假设PWM-n),同时增加右轮速度(假设PWM+n)。这样就可以实现左转,但是同时小车还需要前进,因此在保证小车的前进速度需要给PWM M,因此左轮的PWM占空比为M-n,右轮为M+n这样就能保证小车在前进过程中,左转。而PID控制器控制的是n的大小。当然如果你需要同时控制前进速度的话,就需要增加一个PID控制器。 我最近也在做这个,请问有没有相关例程可以参考一下? tiancaigao7 发表于 2012-7-28 09:40 static/image/common/back.gif
恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候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是当前的左轮减去右轮的差值
希望您帮一下,我不大懂怎么去控制这个 同求高人详解该问题... 首先你的PID公式有问题,看你的公式,用的应该是位置式PID,但是这个PID的积分应该是历次的偏差的积分。如果你用的是相对PID,那么比例部分,应该是本次偏差和上一次偏差之差。另外,在你这里,PID的输出当成PWM占空比的变化量是可以的,不过P I D这三个参数需要自己调试,这个只能通过实验来看自己调整。 tiancaigao7 发表于 2012-7-29 09:58 static/image/common/back.gif
首先你的PID公式有问题,看你的公式,用的应该是位置式PID,但是这个PID的积分应该是历次的偏差的积分。如 ...
谢谢您,那错误我明白了,那您看我这个问题适合用增量式还是位置式? tiancaigao7 发表于 2012-7-28 09:40 static/image/common/back.gif
恒定的速度就是你的前进速度,假设你的两个轮子速度一样,现在你发现需要左转,这个时候PID控制器会降低左 ...
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定是6,还是会在6±1波动,1s计算500次,误差累积还是相当快,转一圈最大就可能有500个脉冲误差,一圈总共才700个脉冲。如何才能稳定地控制? werren 发表于 2012-8-11 16:51 static/image/common/back.gif
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...
对了,我点击控制的pwm使用100hz,想起来好像跟这个关系很大。 werren 发表于 2012-8-11 16:51 static/image/common/back.gif
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...
我想问您一下 编码器的数据 是怎么得到的呢?
ldh0504 发表于 2012-8-21 17:05 static/image/common/back.gif
我想问您一下 编码器的数据 是怎么得到的呢?
ETR 外部脉衝計數(紅外對射管+齒輪盤輸出)得到。每隔2ms就去讀取一次。 tiancaigao7 发表于 2012-7-28 08:25 static/image/common/back.gif
用PID专门控制左右两个轮子的转速差,这个转速差叠加在一个恒定的转速上就可以实现转向和直行控制。 ...
如果这样的话只有一个轮子性能好的。控制速度差只能一个轮子跟另外一个轮子。
/ ============== carblance modulation
// ============== carblance 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? 顶一下让更多的高手出来参加讨论。 werren 发表于 2012-9-23 09:34 static/image/common/back.gif
如果这样的话只有一个轮子性能好的。控制速度差只能一个轮子跟另外一个轮子。
/ ============== carbla ...
你的目的是要控制小车走直线,而不是控制两个轮子速度相同,我说的分别施加转速差,输入应该是你的小车的偏角,而不是轮子的速度差。 werren 发表于 2012-8-11 16:51 static/image/common/back.gif
控制转速差误差累积很快。我使用700线的编码。每2ms计数一次让转速稳定控制在6,但是这个不可能保证一定 ...
可以采用位置差(及两轮行走距离差)作为误差来进行PID运算,最近我也在做 ldh0504 发表于 2012-8-21 17:05 static/image/common/back.gif
我想问您一下 编码器的数据 是怎么得到的呢?
我现在用的传感器是用角度传感器和 加速度传感器融合一体的~现在角度已经测出来了 加速度求出来了 之后PID部分 怎么样控制 PID 我用位置式的PID 电机是用12V的直流电机 没有用到编码器 请问一下电机输出的PID 应该怎么去调节呢 您用的PID 是什么式的呢
风烟雨风 发表于 2012-10-11 01:40 static/image/common/back.gif
可以采用位置差(及两轮行走距离差)作为误差来进行PID运算,最近我也在做 ...
是 的,我後來也是這樣處理,這樣就沒有累積誤差。 werren 发表于 2012-10-11 15:30 static/image/common/back.gif
是 的,我後來也是這樣處理,這樣就沒有累積誤差。
但是现在一直没有调出来,不知道怎么调试参数 急求啊 希望指教一下 风烟雨风 发表于 2012-10-11 22:21 static/image/common/back.gif
但是现在一直没有调出来,不知道怎么调试参数 急求啊 希望指教一下
調試時候可以將PID計算結果實時show出來(這樣就可以直觀看出數據變化,然後需要將參數加大還是減小),先調節P再調節I。
只用P的話已經能夠達到不錯的效果了。你可以試試先往大的調,能穩定轉起來后再將P調小,直到轉速穩定或者振盪,加入I參數。再湊一下基本上可以用了。
以上是我的調試經驗。。。。我也是第一次用PID werren 发表于 2012-10-16 08:53 static/image/common/back.gif
調試時候可以將PID計算結果實時show出來(這樣就可以直觀看出數據變化,然後需要將參數加大還是減小), ...
你调的误差有多少
能仔细请教一下吗
我的QQ号是505800119 风烟雨风 发表于 2012-10-18 17:07 static/image/common/back.gif
你调的误差有多少
能仔细请教一下吗
我的QQ号是505800119
誤差跟你的轉速設定有關係,我的電機是經過變速箱的。但是我測試的是沒有經過變速箱的原始轉速。我使用外部中斷,上升沿和下降沿都能觸發中斷。車輪轉一圈可以計數約700個脉衝,中斷上升下降沿都計數可以計到1400次。我10ms 讀一次轉速,將讀出轉速做參數給pid計算,計算結果直接作為pwm控制電機。假設我設定速度是每10ms20個脉衝那麼基本上可以穩定在20±3 ,手去抓車輪 機會不會感到轉速慢下來,扭力很大,看串口輸出結果也是在短時間內看到比較大的轉速波動而已。 我的情况跟你差不多,车轮转一圈大约700个脉冲,然后我是记700次,采样周期是20ms.
现在主要情况是我使用PID调时,(不放在地上)左右轮差距最多为20左右,但是放在地上后偏差很大。
不知道你的在正常情况下左右轮计数的差值最大大概多大? werren 发表于 2012-10-19 13:11 static/image/common/back.gif
誤差跟你的轉速設定有關係,我的電機是經過變速箱的。但是我測試的是沒有經過變速箱的原始轉速。我使用外 ...
我的情况跟你差不多,车轮转一圈大约700个脉冲,然后我是记700次,采样周期是20ms.
现在主要情况是我使用PID调时,(不放在地上)左右轮差距最多为20左右,但是放在地上后偏差很大。
不知道你的在正常情况下左右轮计数的差值最大大概多大? 风烟雨风 发表于 2012-10-20 16:37 static/image/common/back.gif
我的情况跟你差不多,车轮转一圈大约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桥进入休眠,避免电机狂转
…… 果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了 werren 发表于 2012-10-22 09:05 static/image/common/back.gif
可能我們的做法還是有差異。
PID我分為兩部份 一部份計算控制小車的前進速度的pwm ,一部份做左右輪子平 ...
果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了 风烟雨风 发表于 2012-11-5 22:37 static/image/common/back.gif
果然不太一样,
dtIncPIDCalc(&dSPEED,dTotal/8); 再问一句,能看一下你这个函数是怎么写的吗
多谢了 ...
標準的增量式PID 寫法
int dtIncPIDCalc(PID *sptr,int NextPoint)
{
register int iError, iIncpid;
//当前误差
iError = sptr->SetPoint - NextPoint;
//增量计算
iIncpid= sptr->Proportion * iError //E 项
- sptr->Integral * sptr->LastError //E项
+ sptr->Derivative * sptr->PrevError; //E项
//存储误差,用于下次计算
sptr->PrevError = sptr->LastError;
sptr->LastError = iError;
//返回增量值
return(iIncpid);
}
//////////////////////////////////////////////////////////////////////////
//数据结构
typedef struct PID
{
intSetPoint; // 设定目标 Desired Value
longSumError; //误差累计
floatProportion; // 比例常数 Proportional Const
floatIntegral; // 积分常数 IntegralConst
floatDerivative; // 微分常数 Derivative Const
int LastError; //Error[-1]
int PrevError; //Error[-2]
} PID; werren 发表于 2012-11-6 08:46 static/image/common/back.gif
標準的增量式PID 寫法
int dtIncPIDCalc(PID *sptr,int NextPoint)
{
恩多谢了
我的小车跟你的基本要求一样。就是让小车能沿直线行走固定的距离。
现在走直线问题不大,行走固定的步数又是新问题了,不知能否指教一下? 风烟雨风 发表于 2012-11-7 00:50 static/image/common/back.gif
恩多谢了
我的小车跟你的基本要求一样。就是让小车能沿直线行走固定的距离。
现在走直线问题不大,行走 ...
我的做法是設置計數比如兩萬次走直線,然後測量實際走的距離最後求平均每計數一次小車移動的距離,把這個當做參數來用咯。 我也想知道,两电机如果其中一个电机在运动过程中遇到有障碍物,怎样做同步控制,就是一个慢了另外一个快的怎样慢下来
werren 发表于 2012-11-9 10:08 static/image/common/back.gif
我的做法是設置計數比如兩萬次走直線,然後測量實際走的距離最後求平均每計數一次小車移動的距離,把這個 ...
太谢谢了 麻烦你这么多 dmjkun 发表于 2012-11-9 11:43 static/image/common/back.gif
我也想知道,两电机如果其中一个电机在运动过程中遇到有障碍物,怎样做同步控制,就是一个慢了另外一个快的 ...
我是用 光电编码器检测,然后调整PWM参数 werren 发表于 2012-10-22 09:05 static/image/common/back.gif
可能我們的做法還是有差異。
PID我分為兩部份 一部份計算控制小車的前進速度的pwm ,一部份做左右輪子平 ...
看了你们的讨论,我感觉收获很大啊!太感谢了!
但是我有个问题,IncPIDCalc(……)和dtIncPIDCalc(……)有什么区别吗,难道不是增量式PID调节?能看看这个函数的具体定义吗? 谢谢了! mark mark mark cool 收藏,正好需要用 mark下,以后慢慢琢磨,正在想这个问题,谢谢{:smile:} 好贴mark一下 不错的贴,收起来
页:
[1]