使用零件的動作說明:
動作順序
一
二
使用零件
PS2無線控制器
Arduino UNO控制板
L298馬達驅動板
直流減速馬達
舵機
動作說明
1. PS2無線控制器為2.4G頻段的無線電器材。
2.透過操作PS2無線控制器上的按鈕及遙桿,發射對應的字元或類比讀值。
3.透過接收器將訊號連接至Arduino控制板上。
1.將所接收字元或類比讀值,撰寫程式碼對應相對的致動器(舵機或減速馬達)輸出,使其工作。
1. Arduino沒法輸出大電流,所以要透過L298來控制直流減速馬達的前進、後退或停止。
1.一般直流馬達轉速太快,需透過減速齒輪組成減速,降低轉速且提高扭力
1.可以精密地透過PWM訊號來控制舵機的轉動角度。
2.利用舵機的轉動來造成夾持器及手臂的機構動作變化。
三
四
五
.
電路接線圖:
主程式的程式說明:
定義各個輸出/輸入埠數、舵機的各個角度參數(例如最大、最小、起始及每次增減值)及直流減速馬達的最大及最小PWM值。
#include <PS2X_lib.h> //聲明PS2X庫檔
#include <Servo.h> //宣告舵機函式庫
PS2X ps2x; // 定義ps2x為PS2X類變數
int PS_LX; //儲存PS2手柄左搖桿X軸資料
int PS_RY; //儲存PS2手柄右搖桿Y軸資料
int flag; //儲存PS2手柄按鍵標識
const int servoMax=175; //定義舵機的最大角度
const int servoMin=5; //定義舵機的最小角度
const int servoAngle=5; //定義舵機每次的增減角度
const int motorThreshold=120; //定義直流減速馬達最低PWM值(避免馬達發出高頻聲)
const int motorMax=255; //定義直流減速馬達最高PWM值
#define motorIn1 17 //IN1 (即類比腳位pin3)
#define motorIn2 16 //IN2 (即類比腳位pin2)
#define motorEnA 5 //ENA
#define motorIn3 15 //IN3 (即類比腳位pin1)
#define motorIn4 14 //IN4 (即類比腳位pin0)
#define motorEnB 6 //ENB
Servo myservoA; // 建立一個myservoA的舵機物件
Servo myservoB; // 建立一個myservoB的舵機物件
Servo myservoC; // 建立一個myservoC的舵機物件
Servo myservoD; // 建立一個myservoD的舵機物件
int pwValue,drValue;
int valA=90,valB=90,valC=90,valD=90; //設定各個舵機的起始角度
setup()程式區段:
進行舵機的相關宣告,啟動串例通信,是為要使Arduino可以和電腦連線,可以Arduino IDE串列視窗檢視由PS2所傳輸的數據是否正確。
//初始化
void setup()
{
myservoA.attach(3); //設定myservoA連接到pin3
myservoA.write(valA); //myservoA執行起始角度
myservoB.attach(4); //設定myservoB連接到pin4
myservoB.write(valB); //myservoB執行起始角度
myservoC.attach(7); //設定myservoC連接到pin7
myservoC.write(valC); //myservoC執行起始角度
myservoD.attach(8); //設定myservoD連接到pin8
myservoD.write(valD); //myservoD執行起始角度
Serial.begin(9600); //啟動串列通信
//初始化PS2與Arduino控制器介面
ps2x.config_gamepad(13,11,10,12, true, true);
//13->colck,11->command,10->attention,12->data
}
loop()程式區段:
不斷地重複執行PS/2遙控器的按鈕及搖桿資訊讀入動作,並依照這二個資訊來驅動機械手臂(舵機)及小車進退((直流減速馬達)的變化。
void loop(){
ps2x.read_gamepad();//讀PS2數據
//如果按下PS2的綠色“三角”按鍵,標識為'A'
if(ps2x.NewButtonState(PSB_GREEN))
{ flag='A' ; }
//如果按下PS2的藍色“X”按鍵,標識為'B'
else if(ps2x.NewButtonState(PSB_BLUE))
{ flag='B' ; }
//如果按下PS2的粉紅色“O”按鍵,標識為'C'
else if(ps2x.NewButtonState(PSB_PINK))
{ flag='C' ; }
//如果按下PS2的紅色“[]”按鍵,標識為'D'
else if(ps2x.NewButtonState(PSB_RED))
{ flag='D' ; }
//如果按下PS2的“向上”按鍵,標識為'E'
else if(ps2x.NewButtonState(PSB_PAD_UP))
{ flag='E' ; }
//如果按下PS2的“向下”按鍵,標識為'F'
else if(ps2x.NewButtonState(PSB_PAD_DOWN))
{ flag='F' ; }
//如果按下PS2的“向右”按鍵,標識為'G'
else if(ps2x.NewButtonState(PSB_PAD_RIGHT))
{ flag='G' ; }
//如果按下PS2的“向左”按鍵,標識為'H'
else if(ps2x.NewButtonState(PSB_PAD_LEFT))
{ flag='H' ; }
//如果沒有按鍵按下,標識為'X'
else
{ flag='X' ; }
//把PS2手柄右搖杆Y軸資料讀到變數PS_RY
PS_RY=ps2x.Analog(PSS_RY);
//把PS2手柄左搖杆X軸資料讀到變數PS_LX
PS_LX=ps2x.Analog(PSS_LX);
//把PS2手柄運算元據從遙控器發到小車的接收端
Serial.print(flag);
Serial.print("/");
Serial.print(PS_RY);
Serial.print("/");
Serial.println(PS_LX);
delay(100); //等待資料發送與接收
moveCar(PS_RY,PS_LX); //執行直流馬達動作
valueServo(); //執行舵機動作
}
子程式valueServo()的程式程式區段:
針對Arduino控制板所接收到的字元指令,在不超過預設舵機角度最大175度及最小值5度的情況,讓舵機以每次5度增減幅度來變化。
void valueServo()
{
if(flag=='A' && valA<(servoMax-servoAngle)) //當接收"A"指令時,不大於舵機A最大角度時,增加舵機A的角度
{
valA=valA+servoAngle;
myservoA.write(valA); //寫入舵機A動作角度
}
if(flag=='B' && valA>(servoMin+servoAngle)) //當接收"B"指令時,不小於舵機A最小角度時,減少舵機A的角度
{
valA=valA-servoAngle;
myservoA.write(valA); //寫入舵機A動作角度
}
if(flag=='C' && valB<(servoMax-servoAngle)) //當接收"C"指令時,不大於舵機B最大角度時,增加舵機B的角度
{
valB=valB+servoAngle;
myservoB.write(valB); //寫入舵機B動作
}
if(flag=='D' && valB>(servoMin+servoAngle)) //當接收"D"指令時,不小於舵機B最小角度時,減少舵機B的角度
{
valB=valB-servoAngle;
myservoB.write(valB); //寫入舵機C動作
}
if(flag=='E' && valC<(servoMax-servoAngle)) //當接收"E"指令時,不大於舵機C最大角度時,增加舵機C的角度
{
valC=valC+servoAngle;
myservoC.write(valC); //寫入舵機C動作
}
if(flag=='F' && valC>(servoMin+servoAngle)) //當接收"F"指令時,不小於舵機C最小角度時,減少舵機C的角度
{
valC=valC-servoAngle;
myservoC.write(valC); //寫入舵機C動作
}
if(flag=='G' && valD<(servoMax-servoAngle)) //當接收"G"指令時,不大於舵機D最大角度時,增加舵機D的角度
{
valD=valD+servoAngle;
myservoD.write(valD); //寫入舵機D動作角
}
if(flag=='H' && valD>(servoMin+servoAngle)) //當接收"H"指令時,不小於舵機D最小角度時,減少舵機D的角度
{
valD=valD-servoAngle;
myservoD.write(valD); //寫入舵機D動作角
}
}
moveCar程式區段:
將PS2遙控器的左右搖桿當作四動遙控器來看待,將右側遙桿的Y軸讀值,轉換成為自走車的動力值PWM值、前進、後退及停止,將左側遙桿的X軸讀值,轉換成為自走車的左右輪速差,並依循執行直流減速馬達的相應動作。
void moveCar(int Y,int X)
{
//將右側遙桿的Y軸讀值,轉換成為自走車的動力值PWM值(0~motorMax)及前進後退
//當右側遙桿的Y軸往前時,自走車往前進,反之,即後退.
if(Y<117)
{
pwValue=map(Y,117,0,motorThreshold,motorMax);
}
else if(Y>137)
{
pwValue=map(Y,137,255,-1*motorThreshold,-1*motorMax);
}
else
{
pwValue=0;
}
//將左側遙桿的X軸讀值,轉換成為自走車的左右輪速差
if(X>137)
{
drValue=map(X,137,255,0,abs(pwValue));
}
else if(X<117)
{
drValue=map(X,0,117,abs(pwValue)*(-1),0);
}
else
{
drValue=0;
}
if(pwValue==0 && drValue==0) //自走車停止
{
digitalWrite(motorIn1,LOW);
digitalWrite(motorIn2,LOW);
digitalWrite(motorIn3,LOW);
digitalWrite(motorIn4,LOW);
}
else if(pwValue>0) //前進
{
digitalWrite(motorIn1,HIGH);
digitalWrite(motorIn2,LOW);
digitalWrite(motorIn3,HIGH);
digitalWrite(motorIn4,LOW);
if(drValue>0) //右轉
{
analogWrite(motorEnA,pwValue-drValue);
analogWrite(motorEnB,pwValue);
}
else if(drValue<0) //左轉
{
analogWrite(motorEnA,pwValue);
analogWrite(motorEnB,pwValue+drValue);
}
else if(drValue==0) //直行
{
analogWrite(motorEnA,pwValue);
analogWrite(motorEnB,pwValue);
}
}
else if(pwValue<0) //後退
{
digitalWrite(motorIn1,LOW);
digitalWrite(motorIn2,HIGH);
digitalWrite(motorIn3,LOW);
digitalWrite(motorIn4,HIGH);
if(drValue>0) //右轉
{
analogWrite(motorEnA,abs(pwValue+drValue));
analogWrite(motorEnB,abs(pwValue));
}
else if(drValue<0) //左轉
{
analogWrite(motorEnA,abs(pwValue));
analogWrite(motorEnB,abs(pwValue-drValue));
}
else if(drValue==0) //直行
{
analogWrite(motorEnA,abs(pwValue));
analogWrite(motorEnB,abs(pwValue));
}
}
{
Serial.print("pwValue = ");
Serial.print(pwValue);
Serial.print(";drValue = ");
Serial.println(drValue);
}
}
.