|
LEGO MINDSTORMS NXT的控制器能够同时驱动三组伺服马达,
伺服马达与一般马达主要差异在它多了回授系统。
LEGO Servo Motor能够回报马达转动角度讯息给控制器,
并且可以像步进马达一样控制旋转角度,解析达1度角,这真是不错的设计!
本文先讨论马达转速控制,
NXT玩家们控制马达时,应该会发现用NXT控制马达的角度或转数蛮容易,所以用NXT精确马达定位,不成问题。
但是想控制马达定速运转,这不是一件容易的事,
因为NXT使用不同电池或者换个地点(负载状况不同),相同的程式产出的结果会不同。
马达转速惯用单位为rpm (Revolution(s) Per Minute,每分钟转数),NXT马达转速不高,Power = 100,全速运转时约133 rpm。
使用NXC (BricxCC)程式,可以每秒计数NXT马达转角,所以133 rpm = 133 x 360° / 60 seconds = 800° / second。
我使用六颗一般充电电池,充饱电后全速可达850° / second,但是快没电时,全速运转约750° / second。
现在介绍PID Control,属于系统控制的领域,这方法可消弭一些外界变异或干扰影响,
让系统控制可预测,参数设定得好,就可以又快又稳又准。
PID (Proportional Integrative Derivative)
E(t) = R(t) – Y(t) // a set point R(t) to reach, measuring value Y(t)
P(t) = E(t)
I(t) = I(t-1) + E(t)
D(t) = E(t) – E(t-1)
U(t) = Kp*P(t) + Ki*I(t) + Kd*D(t)
以上为一般方程式,适用于任何可控制回授系统,
而下列两式为NXT马达特有方程式。
Power = U(t) / 8
Y(t) = U(t-2)
U(t)为系统估算出的转速,依据实验数据所知,Power = 100时,全速转速约为800° / second,因此Power = U(t) / 8。
而Y(t) = U(t-2),是因为NXT马达转速回应有一秒延迟的现象(1 second deadtime)。
有兴趣的朋友试试这个程式,只用马达A不需组装:-
- #define Kp 40
- #define Ki 40
- #define Kd 8
- task main(){
- long power;
- long set_speed,speed;
- long e0,e1; //error
- long x0,x1; //input
- long P,I,D,U;
- long time;
- string str;
- ResetAllTachoCounts(OUT_A);
- x0 = 0;
- e0 = 0;
- power = 0;
- set_speed = 500; // degree/second
- I = 0;
- time = 0;
- while (1) {
- OnFwdRegEx(OUT_A, power, OUT_REGMODE_IDLE, RESET_NONE);
- x1 = MotorRotationCount(OUT_A);
- Wait(1000); // wait 1 second
- speed = x1 - x0;
- x0 = x1;
- e1 = set_speed - speed;
- P = e1;
- I = I + e1;
- D = e1 - e0;
- e0 = e1;
- U = (Kp*P + Ki*I + Kd*D) / 100;
- power = U / 8;
- if (power>100)
- power = 100;
- else if (power<-100)
- power = -100;
- str = NumToStr(speed);
- str = StrCat("Speed = ",str);
- TextOut(0, LCD_LINE1, str, true);
- str = NumToStr(time);
- str = StrCat("t = ",str);
- TextOut(0, LCD_LINE3, str, false);
- time += 1;
- str = NumToStr(P);
- str = StrCat("P = ",str);
- TextOut(0, LCD_LINE4, str, false);
- str = NumToStr(I);
- str = StrCat("I = ",str);
- TextOut(0, LCD_LINE5, str, false);
- str = NumToStr(D);
- str = StrCat("D = ",str);
- TextOut(0, LCD_LINE6, str, false);
- str = NumToStr(power);
- str = StrCat("Power = ",str);
- TextOut(0, LCD_LINE8, str, false);
- }
- }
复制代码 PS.为了让程式码排版正常,程式中使用了全形空格当空行以及全形<>,编译前请留意修改。
另外附上网上试算表可以模拟试算,电机系学自动控制的同学,可以藉由这个实验把PID搞懂。
最后提醒各位,网路上有许多PID control文章,大家对一般方程式的定义有些许不同,
所以Kp、Ki、Kd数值没搞清楚定义前不要乱用一通,通常使用0 <= K <= 2。 NXT马达反应速度并不快,因此Kd = 0就可以了。
本程式的K值很大,是因为NXC无法使用小数,所以K = 40,代表K = 40 / 100 = 0.4。 |
|