本章節介紹使用 bDesigner 實作「112學年度生科競賽搬運車」積木程式
教材目錄:
一、 bDesigner軟體安裝
二、 bDesigner操作介面和PS2積木簡介
三、 PS2搖桿對應搬運車功能
四、 馬達驅動板接線圖
五、 各功能程式撰寫
六、 程式燒錄
七、 取得「 伺服馬達靜止值」
八、完整程式(bDesigner積木程式、Arduino C程式)
九、參考資料
附錄一:Arduino 程式碼
附錄二:PS2搖桿延伸應用
一、bDesigner軟體安裝
請至bDesigner官方網站「 檔案下載」頁面
可下載 「 bDesigner(只有blockly) 、bDesigner3.0正式版 、bDesigner3.0正式版(加Arcade) 」任一套軟體都可以
如已安裝過bDesigner,請先移除再安裝
安裝過程如下:
a. 點選執行下載檔(setup30-19t10.19.exe)
b. 點選「Install for all user(recommend)」選項
c. 勾選在桌面建立捷徑,並按「下一步」
d. 點選「開始安裝」
e. 等待安裝
f. 安裝完成,並開始執行bDesigner
二、 bDesigner操作介面和PS2積木
執行後之版權宣告畫面,點選「進入主畫面」
軟體選擇「C Blockly」,點選「開啟程式」,此視窗在執行中不可關閉
ps.可先插入Arduino UNO 傳輸線,在此畫面的「其他功能」選擇「偵測Port」,可顯示目前使用的傳輸埠(燒錄程式時需選取傳輸埠)
三、PS2搖桿對應搬運車功能
PS. 當接收器進入省電模式,按下中間「MODE」鈕,可喚醒接收器。
如開機後欲加入解鎖功能請參考:「八、完整程式」下載。
四、 馬達驅動板接線圖
馬達驅動板背面的R24接點短路即可
五、 各功能程式撰寫
變數「伺服馬達靜止值」需測試後產生,請參考後面「第七段」內容
變數「左彎延遲」為左轉彎90度的延遲時間,單位豪秒
變數「右彎延遲」為右轉彎90度的延遲時間,單位豪秒
變數「MAX」為車子高速行駛時的最大速度值(0~255)
變數「MIN」為車子低速行駛時的最大速度值(0~255)
變數「SpeedMode」為車子的最高速度值
變數「前進中」為按住搖桿右側「△」 圖形鈕時,車子持續前進
變數「後退中」為按住搖桿右側「 X 」 圖形鈕時,車子持續後退。
「啟動」事件中設定馬達驅動板的全彩LED腳位(A1)
「啟動」事件中指定「伺服馬達靜止值 」,避免開機後轉動
「無限循環」事件,偵測四組按鈕函數
最後為讓藍芽信號有足夠時間傳輸,故延遲50ms
功能:
按住搖桿左側「上」 鈕,電磁鐵送電LED亮「 紫」色;按住搖桿左側「下」 鈕,電磁鐵斷電LED不亮,M2亦可用於夾爪。
如果按下左側方向「 上」鈕,則M2腳位輸出高電位,電磁鐵動作
馬達驅動板全彩LED亮「 紫」色
如果按下左側方向「 下」鈕,則M2腳位輸出低電位,電磁鐵不動作
馬達驅動板全彩LED熄滅
功能:
按住搖桿右側「△」 圖形鈕,車子持續前進;按住搖桿右側「 X 」 圖形鈕,車子持續後退,按一下「 □ 」圖形鈕車子左轉90度,按一下「 O 」圖形鈕車子右轉90度。
如果按住右側「△」圖形鈕,則變數「 前進中」設為1
如果放開右側「△」圖形鈕,則變數「 前進中」設為0
如果按住右側「 X 」圖形鈕,則變數「 後退中」設為1
如果放開右側「 X 」圖形鈕,則變數「 後退中」設為0
如果按住右側「 □ 」圖形鈕,則變數「 左轉」設為1
如果放開右側「 O 」圖形鈕,則變數「 右轉」設為1
功能:
執行圖形鈕所要求的動作。
如果變數「 前進中」為1,馬達3和馬達4「前進」
如果變數「 後退中」為1,馬達3和馬達4「後退」
如果變數「 左轉」為1,馬達3「後退」和馬達4「前進」,並持續至延遲時間到。
如果變數「 右轉」為1,馬達3「前進」和馬達4「後退」,並持續至延遲時間到。
功能:
搖桿前方四個按鈕,右前側上下按鈕控制伺服馬達抬升或下降抓臂;左前側上下按鈕控制爪子馬達抓住物品或放開物品。
如果按下搖桿右前側的「上面」按鈕(R1),則伺服馬達逆時針旋轉
如果放開搖桿右前側的「上面」按鈕(R1),則伺服馬達停止
如果按下搖桿右前側的「下面」按鈕(R2),則伺服馬達順時針旋轉
如果放開搖桿右前側的「下面」按鈕(R2),則伺服馬達停止
如果按下搖桿左前側的「上面」按鈕(L1),則馬達1(M1)逆時針旋轉
如果放開搖桿左前側的「上面」按鈕(L1),則馬達1(M1)停止
如果按下搖桿左前側的「下面」按鈕(L2),則馬達1(M1)順時針旋轉
如果放開搖桿左前側的「下面」按鈕(L2),則馬達1(M1)停止
ps.馬達順時針或逆時針旋轉,會因接線不同而異
功能:
左側搖桿前後拉動,控制左馬達前進或後退,左右拉動做為調整S2伺服馬達歸零使用。
使用左側搖桿左右拉動(LX),控制伺服馬達2(S2)正反轉,並將值透過序列埠顯示出來,用以取得360度伺服馬達之停止值
使用左側搖桿上下拉動(LY),控制左馬達(M3)等比例前進或後退
左側搖桿上下未拉動情形下,為避免影響單鍵前進與單鍵後退功能,左輪馬達(M3)停止前需先檢查,兩者目前未動作
如果按下左側搖桿(L3),則「SpeedMode」變數設為高速
ps.
使用「對應」積木,將搖桿拉動距離等比例轉成轉速
搖桿未拉動時其類比回傳值約為128,故設定類比回傳值在125~130不會動作(馬達停止轉動)。
最高速度會限制在「SpeedMode」變數值範圍中
功能:
右側搖桿前後拉動,控制右馬達前進或後退。
使用右側搖桿上下拉動(RY),控制右馬達(M4)等比例前進或後退
右側搖桿上下未拉動情形下,為避免影響單鍵前進與單鍵後退功能,右輪馬達(M4)停止前需先檢查,兩者目前未動作
如果按下右側搖桿(R3),則「SpeedMode」變數設為低速
ps.
使用「對應」積木,將搖桿拉動距離等比例轉成轉速
搖桿未拉動時其類比回傳值約為128,故設定類比回傳值在125~130不會動作(馬達停止轉動)。
最高速度會限制在「SpeedMode」變數值範圍中
下載完成檔 ps2forbDesigner.m
開啟完成檔至積木區
3. Arduino UNO 插上USB傳輸線
4. 點選「一鍵燒錄」
5. 選擇傳輸埠(不一定是COM3)
6. 需確認燒錄過程有出現此「使用多少記憶體視窗」,才有正確燒錄完成
ps.如果此視窗一閃就關閉,表示程式有錯誤
完成程式後,需先測試取得變數「伺服馬達靜止值」:(運輸車如未安裝360度伺服馬達可省略)
先將360度伺服馬達插至馬達驅動板S2
燒錄完整程式
開啟bDesigner C Block 「監看/序列埠監視」畫面
「序列埠監視」畫面顯示PS2左邊搖桿水平值(LX)
左右拉動PS2左邊搖桿
直至360度伺服馬達停止,並記錄「序列埠監視」畫面搖桿水平值(LX)
將該值填入變數「伺服馬達靜止值」中
重新燒錄完整程式
將360度伺服馬達插至馬達驅動板S1
bDesigner 積木程式下載(需使用bDesigner C Block開啟):
https://drive.google.com/file/d/1hK7VZnaFiUjdgWNwlemRdQbR7Zd8FIR5/view?usp=share_link
為防止搬運車被他人藍芽連接,以下程式加入鎖定功能,必須解鎖成功(左搖桿往左、右搖桿往右,可自行修改解鎖方式)才能啟動車子:
https://drive.google.com/file/d/1WLib7oMVCk0DF9weKwpUrhSkp92j0Utw/view?usp=drive_link
Arduino C++ 程式下載(需使用Arduino IDE開啟):
https://drive.google.com/file/d/1cwPHTdxys7nykf5gPX0H0DSDdvHskZJP/view?usp=drive_link
Arduino會使用到的函式庫:
MotorDriverBoard.zip
https://drive.google.com/file/d/1HqZjvmXZkRCTO45mgKSDIUY_vlY24fEP
PS2X_lib-master.zip
https://drive.google.com/file/d/1dhOZSSD0ciye0Nthu8R0D1EdNTTmpf8R/
Adafruit_NeoPixel 函式庫
https://drive.google.com/file/d/19Lex282vFZlxBxdP2fVHIhvpAPKkA5O_
安裝方式,下載壓縮檔,Arduino IDE 功能表:Sketch / Include Library / Add .ZIP Library , 選擇以上檔案安裝即可。
int ServoStaticValue = 98; //伺服馬達靜止值(第一次使用360度伺服馬達時需設定)
int DelayLeft = 730; //左彎90度馬達延遲時間(毫秒)
int DelayRight = 800; //右彎90度馬達延遲時間(毫秒)
int HighSpeedValue = 150; //高速模式馬達最大輸出(0-255)
int LowSpeedValue = 70; //低速模式馬達最大輸出(0-255)
int SpeedMode = HighSpeedValue; //預設馬達運行模式為高速模式
int ForwardMode = 0; //變數為1時,車子兩輪正在前進,避免使用左右搖桿控制
int BackMode = 0; //變數為1時,車子兩輪正在後退,避免使用左右搖桿控制
int TurnLeft = 0; //變數為1時,車子正在左轉90度,避免使用左右搖桿控制
int TurnRight = 0; //變數為1時,車子正在右轉90度,避免使用左右搖桿控制
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
#define NUMPIXELS 1
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS,15, NEO_GRB + NEO_KHZ800);
#include "Emakefun_MotorDriver.h"
Emakefun_MotorDriver mMotorDriver = Emakefun_MotorDriver(0x60);
Emakefun_Servo *mServo1 = mMotorDriver.getServo(1);
Emakefun_Servo *mServo2 = mMotorDriver.getServo(2);
Emakefun_DCMotor *DCMotor_3 = mMotorDriver.getMotor(M3);
Emakefun_DCMotor *DCMotor_4 = mMotorDriver.getMotor(M4);
#include "PS2X_lib.h"
PS2X ps2x;
int error;
int ps2_error_code;
Emakefun_DCMotor *DCMotor_2 = mMotorDriver.getMotor(M2);
Emakefun_DCMotor *DCMotor_1 = mMotorDriver.getMotor(M1);
//主程式
void setup(){
mMotorDriver.begin(50);
Serial.begin(9600);
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
pixels.begin();
mServo1->writeServo(ServoStaticValue);
mServo2->writeServo(ServoStaticValue);
DCMotor_3->run(BRAKE);
DCMotor_4->run(BRAKE);
error = ps2x.config_gamepad(13, 11, 10, 12, false, false);
}
void loop(){
ps2_error_code = ps2x.read_gamepad(false, 0);
ChecktDirectionButton();
CheckGraphButton();
ChecktFrontButton();
CheckLeftJoystick();
CheckRightJoystick();
delay(50);
}
/// 偵測方向紐
void ChecktDirectionButton() {
if (ps2x.ButtonPressed(PSB_PAD_UP)) { //按住[上]鈕
DCMotor_2->setSpeed(255);
DCMotor_2->run(FORWARD);
pixels.setPixelColor(0, pixels.Color(255,0,255)); //LED 亮[紫]色
pixels.show();
}
if (ps2x.ButtonPressed(PSB_PAD_DOWN)) { //按住[下]鈕
DCMotor_2->run(BRAKE);
pixels.setPixelColor(0, pixels.Color(0,0,0)); //LED 熄滅
pixels.show();
}
}
/// 偵測左側搖桿
void CheckLeftJoystick() {
if (ps2x.Analog(PSS_LX) >= 0) { //左側搖桿左右拉動時更改S2類比值輸出(70 ~ 110)
mServo2->writeServo((map((ps2x.Analog(PSS_LX)),0,255,70,110)));
Serial.println((map((ps2x.Analog(PSS_LX)),0,255,70,110))); //將類比值回傳至電腦序列埠視窗,藉此功能找出伺服馬達(S2)靜止值
}
//左側搖桿上下拉動時,更改馬達3類比值輸出(0 ~ HighSpeedValue or LowSpeedValue)
if (ps2x.Analog(PSS_LY) < 125) {
DCMotor_3->setSpeed((map((ps2x.Analog(PSS_LY)),128,0,0,SpeedMode)));
DCMotor_3->run(FORWARD);
}else if (ps2x.Analog(PSS_LY) > 130) {
DCMotor_3->setSpeed((map((ps2x.Analog(PSS_LY)),128,255,0,SpeedMode)));
DCMotor_3->run(BACKWARD);
} else {
//如果圖形鈕沒有在控制車子,則馬達3停止動作
if (ForwardMode == 0 && BackMode == 0) {
DCMotor_3->run(BRAKE);
}
}
//如果按下左側搖桿,切換為高速模式
if (ps2x.ButtonPressed(PSB_L3)) {
SpeedMode = HighSpeedValue;
}
}
/// 偵測右側搖桿
void CheckRightJoystick() {
//右側搖桿上下拉動時,更改馬達4類比值輸出(0 ~ HighSpeedValue or LowSpeedValue)
if (ps2x.Analog(PSS_RY) < 125) {
DCMotor_4->setSpeed((map((ps2x.Analog(PSS_RY)),128,0,0,SpeedMode)));
DCMotor_4->run(FORWARD);
}else if (ps2x.Analog(PSS_RY) > 130) {
DCMotor_4->setSpeed((map((ps2x.Analog(PSS_RY)),128,255,0,SpeedMode)));
DCMotor_4->run(BACKWARD);
} else {
//如果圖形鈕沒有在控制車子,則馬達4停止動作
if (ForwardMode == 0 && BackMode == 0) {
DCMotor_4->run(BRAKE);
}
}
//如果按下右側搖桿,切換為低速模式
if (ps2x.ButtonPressed(PSB_R3)) {
SpeedMode = LowSpeedValue;
}
}
/// 偵測前面側按鈕
void ChecktFrontButton() {
//如果按下前側右上按鈕,伺服馬達1正轉
if (ps2x.ButtonPressed(PSB_R1)) {
mServo1->writeServo(160);
}else if (ps2x.ButtonReleased(PSB_R1)) { //放開按鈕時伺服馬達1靜止
mServo1->writeServo(ServoStaticValue);
}
//如果按下前側右下按鈕,伺服馬達1反轉
if (ps2x.ButtonPressed(PSB_R2)) {
mServo1->writeServo(0);
}else if (ps2x.ButtonReleased(PSB_R2)) { //放開按鈕時伺服馬達1靜止
mServo1->writeServo(ServoStaticValue);
}
//如果按下前側左上按鈕,馬達1正轉
if (ps2x.ButtonPressed(PSB_L1)) {
DCMotor_1->setSpeed(255);
DCMotor_1->run(FORWARD);
}else if (ps2x.ButtonReleased(PSB_L1)) { //放開按鈕時馬達1停止
DCMotor_1->run(BRAKE);
}
//如果按下前側左下按鈕,馬達1反轉
if (ps2x.ButtonPressed(PSB_L2)) {
DCMotor_1->setSpeed(255);
DCMotor_1->run(BACKWARD);
}else if (ps2x.ButtonReleased(PSB_L2)) { //放開按鈕時馬達1停止
DCMotor_1->run(BRAKE);
}
}
/// 偵測圖形鈕
void CheckGraphButton() {
//如果按住[三角形]鈕,車子全速前進
if (ps2x.NewButtonState(PSB_TRIANGLE)) {
if (ps2x.ButtonPressed(PSB_TRIANGLE)) {
ForwardMode = 1;
} else {
ForwardMode = 0;
}
}
//如果按住[X]鈕,車子全速後退
if (ps2x.NewButtonState(PSB_CROSS)) {
if (ps2x.ButtonPressed(PSB_CROSS)) {
BackMode = 1;
} else {
BackMode = 0;
}
}
//如果按住[正方形]鈕,車子90度左轉
if (ps2x.NewButtonState(PSB_SQUARE)) {
if (ps2x.ButtonReleased(PSB_SQUARE)) {
TurnLeft = 1;
}
}
//如果按住[O]鈕,車子90度右轉
if (ps2x.NewButtonState(PSB_CIRCLE)) {
if (ps2x.ButtonReleased(PSB_CIRCLE)) {
TurnRight = 1;
}
}
RunGraphButton(); //執行車子前進、後退、左轉、右轉函式
}
/// 執行車子前進、後退、左轉、右轉函式
void RunGraphButton() {
if (TurnLeft) { //車子90度左轉
DCMotor_3->setSpeed(255);
DCMotor_3->run(BACKWARD);
DCMotor_4->setSpeed(255);
DCMotor_4->run(FORWARD);
TurnLeft = 0;
delay(DelayLeft); //左轉彎延遲
}else if (TurnRight) { //車子90度右轉
DCMotor_3->setSpeed(255);
DCMotor_3->run(FORWARD);
DCMotor_4->setSpeed(255);
DCMotor_4->run(BACKWARD);
TurnRight = 0;
delay(DelayRight); //右轉彎延遲
}else if (ForwardMode) { //車子全速前進
DCMotor_3->setSpeed(255);
DCMotor_3->run(FORWARD);
DCMotor_4->setSpeed(255);
DCMotor_4->run(FORWARD);
}else if (BackMode) { //車子全速後退
DCMotor_3->setSpeed(255);
DCMotor_3->run(BACKWARD);
DCMotor_4->setSpeed(255);
DCMotor_4->run(BACKWARD);
}
}
=============================================================================================
以上程式使用Arduino IDE時需安裝以下函式庫:
Adafruit_NeoPixel : https://drive.google.com/file/d/19Lex282vFZlxBxdP2fVHIhvpAPKkA5O_/view?usp=drive_link
MotorDriverBoard: https://drive.google.com/file/d/1HqZjvmXZkRCTO45mgKSDIUY_vlY24fEP/view?usp=drive_link
PS2X_lib: https://drive.google.com/file/d/1dhOZSSD0ciye0Nthu8R0D1EdNTTmpf8R/view?usp=drive_link
函式庫安裝方式,下載上述三個壓縮檔:Arduino IDE 功能表:Sketch / Include Library / Add .ZIP Library , 選擇以上檔案安裝即可。
=============================================================================================
開啟線上版Makecode Microbit
在積木區中點選「擴展」
積木區就會出現 「Ps2controller」積木
再依PS2積木上的腳位設置連接microbit
需使用USB或藍芽連線的PS2搖桿+Chrome瀏覽器開啟Scratch
安裝Chrome的PS2外掛(scratchaddons.com/zh-tw/ )
Chrome瀏覽器開啟Scratch
依以下步驟開啟PS2外掛