# Robot Control (arduino_track_car) ###### tags: `控制系統` `arduino` `mbot` `606A` **組別 : 我現在要出診~** :::info :mega: 架構流程圖直接跳Lab10 :mega: :mega: 正常功能直接跳Lab9 :mega: ::: complete code : https://github.com/yee11111/mbot-Track-car/blob/master/Track_car_V7.0.c ## Lab 1 學習發出YEE的叫聲 ![](https://i.imgur.com/6AbiqCA.png) (其實是測試開迴路控制,但很快結束,所以來學習發出YEE的叫聲) ## Lab 2 Min-Max Normalization ### (1) pin value ![](https://i.imgur.com/oDlO7vy.png) ### (2) normalization 前面突波的部分是未完全normalization造成的 ![](https://i.imgur.com/VAHWMyH.png) ### (3) code ``` java void Maxmin_norml_V2() { int L2r,L1r,Mr,R1r,R2r; L2r=analogRead(L2); if(L2r>=L2Max){L2Max=L2r;} if(L2r<=L2min){L2min=L2r;} L2n=double(analogRead(L2)-L2min)/(L2Max-L2min); L1r=analogRead(L1); if(L1r>=L1Max){L1Max=L1r;} if(L1r<=L1min){L1min=L1r;} L1n=double(analogRead(L1)-L1min)/(L1Max-L1min); Mr= analogRead(Mid); if(Mr>=MMax){MMax=Mr;} if(Mr<=Mmin){Mmin=Mr;} Mn =double(analogRead(Mid)-Mmin)/(MMax-Mmin); R1r=analogRead(R1); if(R1r>=R1Max){R1Max=R1r;} if(R1r<=R1min){R1min=R1r;} R1n=double(analogRead(R1)-R1min)/(R1Max-R1min); R2r=analogRead(R2); if(R2r>=R2Max){R2Max=R2r;} if(R2r<=R2min){R2min=R2r;} R2n=double(analogRead(R2)-R2min)/(R2Max-R2min); } ``` ### (4) vedio [mbot] Lab2 Min-Max Normalization {%youtube sPUSPxawxC8 %} ## Lab 3 error detect ### (1) error output output = -3 ~ +3 ![](https://i.imgur.com/EGCgCiv.png) ### (2) code ``` java void take_err() { double d2=2,d1=1,d0=0,dd2=1,dd4=1,dd1=1,dd5=1; int Hs=700,Ls=200,ttt=3; np=((L2n*-d2*dd1)+(L1n*-d1*dd2)+(Mn*d0)+(R1n*d1*dd4)+(R2n*d2*dd5)); error=np-hop; } ``` ### (3) vedio [mbot] Lab 3 error detector {%youtube BKKq-HrHXXE %} :::info :mega: 由於數據回傳會影響到時間響應,以下數據可能失真~ :mega: ::: ## Lab 4 P control ### (1) Picture for output ![](https://i.imgur.com/JDuqYs5.png) ![](https://i.imgur.com/cBtyygT.png) ### (2) code ``` java /**kp!=0 ki=kd=0**/ void crtl_V5() { double motorSpeed,leftSpeed,rightSpeed; motorSpeed = kp*error + kd*(error - pre_error) + ki*(sum_error); leftSpeed = baseSpeed + motorSpeed; rightSpeed = baseSpeed - motorSpeed; if(leftSpeed > maxSpeed) leftSpeed = maxSpeed; if(rightSpeed > maxSpeed) rightSpeed = maxSpeed; if(leftSpeed < minSpeed) leftSpeed = minSpeed; if(rightSpeed < minSpeed) rightSpeed = minSpeed; if(rightSpeed<0){digitalWrite(7, 0);}else{digitalWrite(7, 1);} if(leftSpeed<0) {digitalWrite(4, 1);}else{digitalWrite(4, 0);} analogWrite(6,abs(rightSpeed));analogWrite(5,abs(leftSpeed)); pre_error = error; sum_error += error; } ``` ### (3) Vedio [mbot] Lab 4 P control first test {%youtube 85bugT9owVY %} [mbot] Lab 4 P control second test {%youtube 8olCp6TWPgQ %} ## Lab 5 PD control ### (1) Picture for Obtuse angle ![](https://i.imgur.com/qWMSM7u.png) ![](https://i.imgur.com/aAKSHPs.png) ### (2) Picture for Right angle ![](https://i.imgur.com/OuWYjbL.png) ![](https://i.imgur.com/GPzyJSf.png) ### (3) code ``` java /**kp!=0 ki=0 kd!=0**/ void crtl_V5() { double motorSpeed,leftSpeed,rightSpeed; motorSpeed = kp*error + kd*(error - pre_error) + ki*(sum_error); leftSpeed = baseSpeed + motorSpeed; rightSpeed = baseSpeed - motorSpeed; if(leftSpeed > maxSpeed) leftSpeed = maxSpeed; if(rightSpeed > maxSpeed) rightSpeed = maxSpeed; if(leftSpeed < minSpeed) leftSpeed = minSpeed; if(rightSpeed < minSpeed) rightSpeed = minSpeed; if(rightSpeed<0){digitalWrite(7, 0);}else{digitalWrite(7, 1);} if(leftSpeed<0) {digitalWrite(4, 1);}else{digitalWrite(4, 0);} analogWrite(6,abs(rightSpeed));analogWrite(5,abs(leftSpeed)); pre_error = error; sum_error += error; } ``` ### (4) Vedio [mbot] Lab 5 PD control first test {%youtube c3ZKoDau2MY %} [mbot] Lab 5 PD control second test {%youtube wog7tKJHn1U %} ## Lab 6 PID control :::info :mega: 加入數據回傳後失真~ 影片沒加所以看起來不是這樣QQ :mega: Max basespeed=150 ::: ### (1) Picture for output ![](https://i.imgur.com/1Gd9bK3.png) ![](https://i.imgur.com/u8XSNzM.png) ### (2) code ``` java /**kp!=0 ki!=0 kd!=0**/ void crtl_V5() { double motorSpeed,leftSpeed,rightSpeed; motorSpeed = kp*error + kd*(error - pre_error) + ki*(sum_error); leftSpeed = baseSpeed + motorSpeed; rightSpeed = baseSpeed - motorSpeed; if(leftSpeed > maxSpeed) leftSpeed = maxSpeed; if(rightSpeed > maxSpeed) rightSpeed = maxSpeed; if(leftSpeed < minSpeed) leftSpeed = minSpeed; if(rightSpeed < minSpeed) rightSpeed = minSpeed; if(rightSpeed<0){digitalWrite(7, 0);}else{digitalWrite(7, 1);} if(leftSpeed<0) {digitalWrite(4, 1);}else{digitalWrite(4, 0);} analogWrite(6,abs(rightSpeed));analogWrite(5,abs(leftSpeed)); pre_error = error; sum_error += error; } ``` ### (3) Vedio [mbot] Lab 6 PID control first test {%youtube W75-OO2svvQ %} ## Lab 7 increase base speed :::info :mega: Max basespeed=250 :mega: ::: ### (1) Performence for add judgment hint : YEE ![](https://i.imgur.com/aNXsVjC.png) ### (2) code ``` java void take_err() { double d2=2,d1=1,d0=0,dd2=1,dd4=1,dd1=1,dd5=1; int Hs=700,Ls=200,ttt=3; if(analogRead(L2)>Hs&&analogRead(L1)>Hs&&analogRead(Mid)>Hs&&analogRead(R1)>Hs&&analogRead(R2)<Ls) {dd4=0;dd5=0; } //11110 if(analogRead(L2)<Ls&&analogRead(L1)>Hs&&analogRead(Mid)>Hs&&analogRead(R1)>Hs&&analogRead(R2)>Hs) {dd2=0;dd1=0; } //01111 if(analogRead(L2)<Ls&&analogRead(L1)<Ls&&analogRead(Mid)<Ls&&analogRead(R1)<Ls&&analogRead(R2)<Ls) { delay(0.25); if(pre_error>=0){error =ttt;} else{error =-ttt;} }else {np=((L2n*-d2*dd1)+(L1n*-d1*dd2)+(Mn*d0)+(R1n*d1*dd4)+(R2n*d2*dd5)); error=np-hop;} } ``` ### (3) Vedio [mbot] Lab 7 PID control second test (3分鐘後的才正常一點) {%youtube 3ZtbmnJ2xm8 %} ## Lab 8 Ultrasonic obstacle avoidance ### (1) Ultrasonic ![](https://i.imgur.com/SdunBLs.png) ### (2) code ``` java void take_dist_V3() { pinMode(trigPin, OUTPUT); digitalWrite(trigPin, HIGH); delayMicroseconds(5); digitalWrite(trigPin, LOW); pinMode(trigPin, INPUT); duration = pulseIn(trigPin, HIGH); cm = (duration/2) / 29.1; } ``` ### (3) Vedio [mbot] Lab 8 Ultrasonic obstacle avoidance PID control first test {%youtube iNBR9Mw5WDs %} ## Lab 9 Ultrasonic PID with initial ### (1) initial ![](https://i.imgur.com/lqnvRog.png) ### (2) code ``` java void init_V5() { Serial.println("Inital....."); int Hs=700,Ls=200,Op=100,mt=0; analogWrite(5, 150);analogWrite(6, 150); digitalWrite(4, 0);digitalWrite(7, 0); while(mt<850){Maxmin_norml_V2();mt++;} whelstop(); } ``` ### (3) Vedio [mbot] Lab 9 line following car by PID with initial first test {%youtube xfr2BkmXl5g %} ## Lab 10 Summary ### (1) Architecture diagram ![](https://i.imgur.com/a5Hck32.png) ### (2) tuning rule Ziegler–Nichols method | Control Type | Kp | Ki |Kd | |:------:|:-----------:|:-----------:|:-----------:| | P | 0.50Kc | 0 |0 | | PI | 0.45Kc | 1.2KpdT/ Pc |0 | | PID | 0.60Kc | 2KpdT / Pc |KpPc / (8dT) | ### (3) flow chart #### (1) main() ![](https://i.imgur.com/jpbQ90t.png) #### (2) init_V5() ![](https://i.imgur.com/XDXHuZy.png) #### (3) fontline_V3() ![](https://i.imgur.com/AHd9MZd.png) #### (4) take_dist_V3() ![](https://i.imgur.com/uJbPhLg.png) #### (5) rond_V2() ![](https://i.imgur.com/v351j0X.png) #### (6) Maxmin_norml_V2() ![](https://i.imgur.com/yGbj5Kn.png) #### (7) take_err() ![](https://i.imgur.com/uSS5TVz.png) #### (8) crtl_V5() ![](https://i.imgur.com/Zb7vTNw.png) ### (4) All code Protected by MIT license ``` java /*Track_car_V7.0 20191225 by yee11111*/ int trigPin = 12; //Trig Pin long duration, cm, inches; int R1=A0,R2=A1,Mid=A3,L2=A4,L1=A2; //ledin double R1Max=500,R2Max=500,MMax=500,L1Max=500,L2Max=500; //Max double R1min=90,R2min=90,Mmin=90,L1min=90,L2min=90; //min double R1n,R2n,Mn,L1n,L2n; float ffix=0.97,bfix=0.97; //fix num double hop=0,kp=150,ki=0.001,kd=1000,error=0,np=0; double pre_error=0,sum_error=0,maxSpeed=250,minSpeed=-250,baseSpeed=230; void font(int sp,float ffix) { analogWrite(5, sp);analogWrite(6, sp*ffix); digitalWrite(4, 0);digitalWrite(7, 1); } void ltrnS(int sp,float ffix){ analogWrite(5, 0);analogWrite(6, sp*ffix); digitalWrite(4, 1);digitalWrite(7, 1); } void rtrnS(int sp,float ffix){ analogWrite(5, sp);analogWrite(6, 0); digitalWrite(4, 0);digitalWrite(7, 0); } void whelstop() { analogWrite(5, 0);analogWrite(6, 0); digitalWrite(4, 0);digitalWrite(7, 0); } void Maxmin_norml_V2() { int L2r,L1r,Mr,R1r,R2r; L2r=analogRead(L2); if(L2r>=L2Max){L2Max=L2r;} if(L2r<=L2min){L2min=L2r;} L2n=double(analogRead(L2)-L2min)/(L2Max-L2min); L1r=analogRead(L1); if(L1r>=L1Max){L1Max=L1r;} if(L1r<=L1min){L1min=L1r;} L1n=double(analogRead(L1)-L1min)/(L1Max-L1min); Mr= analogRead(Mid); if(Mr>=MMax){MMax=Mr;} if(Mr<=Mmin){Mmin=Mr;} Mn =double(analogRead(Mid)-Mmin)/(MMax-Mmin); R1r=analogRead(R1); if(R1r>=R1Max){R1Max=R1r;} if(R1r<=R1min){R1min=R1r;} R1n=double(analogRead(R1)-R1min)/(R1Max-R1min); R2r=analogRead(R2); if(R2r>=R2Max){R2Max=R2r;} if(R2r<=R2min){R2min=R2r;} R2n=double(analogRead(R2)-R2min)/(R2Max-R2min); } void init_V5() { Serial.println("Inital....."); int Hs=700,Ls=200,Op=100,mt=0; analogWrite(5, 150);analogWrite(6, 150); digitalWrite(4, 0);digitalWrite(7, 0); while(mt<850){Maxmin_norml_V2();mt++;} whelstop(); } void take_err() { double d2=2,d1=1,d0=0,dd2=1,dd4=1,dd1=1,dd5=1; int Hs=700,Ls=200,ttt=3; if(analogRead(L2)>Hs&&analogRead(L1)>Hs&&analogRead(Mid)>Hs&&analogRead(R1)>Hs&&analogRead(R2)<Ls) {dd4=0;dd5=0; } //11110 if(analogRead(L2)<Ls&&analogRead(L1)>Hs&&analogRead(Mid)>Hs&&analogRead(R1)>Hs&&analogRead(R2)>Hs) {dd2=0;dd1=0; } //01111 if(analogRead(L2)<Ls&&analogRead(L1)<Ls&&analogRead(Mid)<Ls&&analogRead(R1)<Ls&&analogRead(R2)<Ls) { delay(0.25); if(pre_error>=0){error =ttt;} else{error =-ttt;} }else {np=((L2n*-d2*dd1)+(L1n*-d1*dd2)+(Mn*d0)+(R1n*d1*dd4)+(R2n*d2*dd5)); error=np-hop;} } void crtl_V5() { double motorSpeed,leftSpeed,rightSpeed; motorSpeed = kp*error + kd*(error - pre_error) + ki*(sum_error); leftSpeed = baseSpeed + motorSpeed; rightSpeed = baseSpeed - motorSpeed; if(leftSpeed > maxSpeed) leftSpeed = maxSpeed; if(rightSpeed > maxSpeed) rightSpeed = maxSpeed; if(leftSpeed < minSpeed) leftSpeed = minSpeed; if(rightSpeed < minSpeed) rightSpeed = minSpeed; if(rightSpeed<0){digitalWrite(7, 0);}else{digitalWrite(7, 1);} if(leftSpeed<0) {digitalWrite(4, 1);}else{digitalWrite(4, 0);} analogWrite(6,abs(rightSpeed));analogWrite(5,abs(leftSpeed)); pre_error = error; sum_error += error; } void take_dist_V3() { pinMode(trigPin, OUTPUT); digitalWrite(trigPin, HIGH); delayMicroseconds(5); digitalWrite(trigPin, LOW); pinMode(trigPin, INPUT); duration = pulseIn(trigPin, HIGH); cm = (duration/2) / 29.1; } void rond_V2() { int cc2=20,Ls=200,tt=1; while(cm<cc2) { take_dist_V3(); whelstop(); while(cm<25) { take_dist_V3(); rtrnS(150,ffix); } rtrnS(150,ffix); delay(100); font(150,ffix); delay(450); analogWrite(6,abs(200));analogWrite(5,abs(50)); delay(800); while(analogRead(L2)<Ls&&analogRead(L1)<Ls&&analogRead(Mid)<Ls&&analogRead(R1)<Ls&&analogRead(R2)<Ls) {font(150,ffix);} } } void fontline_V3() {int rg=1; if(error<rg&&error>-rg&&analogRead(Mid)>700){take_dist_V3(); rond_V2(); } Maxmin_norml_V2(); take_err(); crtl_V5(); } void setup() { Serial.begin(9600); pinMode(4, OUTPUT);pinMode(5, OUTPUT);pinMode(6, OUTPUT);pinMode(7, OUTPUT); //motor pinput pinMode(A0, INPUT); pinMode(A1, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(A4, INPUT);pinMode(A7, INPUT); //ledin pinMode(trigPin, OUTPUT); //Define inputs and outputs of vol hop=0; Maxmin_norml_V2(); take_err(); } void loop() { if(analogRead(A7)==0) { init_V5(); while(1) { if(analogRead(A7)==0) { while(1) { fontline_V3();} } } } } ``` ### (5) Experience Sharing #### Q1 沒讀書 1. 高頻抖動須消除 2. PID參數調的不佳 3. 時序問題須練習改善 4. 理論不熟 #### Q2 沒錢 5. 攝影品質不佳 6. 相機需要防手震 7. 輪子打滑須注意