How can we help you today?
【運動】APP控制模式 | dual2s (2025)
簡介
GoX系列機器人(GoSUMO、GoARM、GoJoga足球….)的核心控制器為dual2s。我們提供的程式範例中,控制GoX系列機器人的通訊模式主要有三種:【APP控制模式、PS2x控制模式(速配式)、PS3x控制模式(鎖址式)】,如圖所示。
👉本單元將針對【APP控制模式】提供程式範例。

APP程式範例資源
GoX輪型運動基礎概念

APP控制架構
撰寫程式之前,先建立兩端(APP、dual2s控制器)之間的控制命令關係,如圖,APP每個按鍵各自定義著獨有的【控制字元/字母】,透過【控制字元】協定GoX機器人的指定運動,例如前進、後退、抬手臂、夾爪閉合…等運動。

積木程式 – 【抓地胎】模式
我們基於yesioBlockly積木程式編輯器,提供此程式範例(XML)【抓地胎-APP模式,程式傳送門】。

積木程式 – 【麥克納姆輪】模式
我們基於yesioBlockly積木程式編輯器,提供此程式範例(XML)【麥克納姆輪-APP模式,程式傳送門】。

Arduino C語言
我們提供完整的程式範例,將dual2s函數庫匯入ArduinoIDE編輯器後(請參考此文),在範例可找到相關檔案,👉檔名:dual2s_Bluetooth.ino,如下圖。

#include <dual2s.h>
#include "BluetoothSerial.h"
//DC電機GPIO
#define PIN_MOTO_1A 14
#define PIN_MOTO_1B 32
#define PIN_MOTO_2A 12
#define PIN_MOTO_2B 33
#define PIN_MOTO_3A 25
#define PIN_MOTO_3B 26
#define PIN_MOTO_4A 23
#define PIN_MOTO_4B 22
//蜂鳴器GPIO
#define PIN_BUZZER 15
//超音波GPIO
#define PIN_USC_FRONT_ECHO 13
#define PIN_USC_FRONT_TRIG 27
#define PIN_USC_RIGHT_ECHO 5
#define PIN_USC_RIGHT_TRIG 4
#define PIN_USC_LEFT_ECHO 19
#define PIN_USC_LEFT_TRIG 18
//短距紅外線GPIO
#define PIN_IR_LEFT 34
#define PIN_IR_MIDDLE 35
#define PIN_IR_RIGHT 39
//供電偵測GPIO
#define PIN_BATTERY 36
//預設使用的PWM通道
#define PWM_CH_BUZZER 7
#define PWM_CH_M1A 8
#define PWM_CH_M1B 9
#define PWM_CH_M2A 10
#define PWM_CH_M2B 11
#define PWM_CH_M3A 12
#define PWM_CH_M3B 13
#define PWM_CH_M4A 14
#define PWM_CH_M4B 15
BluetoothSerial SerialBT; //藍牙串列物件
char BTCMD[3] = {0}; //儲存藍牙串列接收到的指令
int PWMspeed = 950; //儲存藍牙串列接收到的PWM speed數值
int SeekCnt = 0;
GoSUMO gs;
Buzzer bz(PIN_BUZZER, PWM_CH_BUZZER);
Power volt(PIN_BATTERY);
IR3CH ir(PIN_IR_LEFT, PIN_IR_MIDDLE, PIN_IR_RIGHT);
HCSR04 us_F(PIN_USC_FRONT_ECHO, PIN_USC_FRONT_TRIG);
HCSR04 us_R(PIN_USC_RIGHT_ECHO, PIN_USC_RIGHT_TRIG);
HCSR04 us_L(PIN_USC_LEFT_ECHO, PIN_USC_LEFT_TRIG);
void setup(){
Serial.begin(115200);
SerialBT.begin("yesio10"); //啟動藍牙串列並設定藍牙裝置名稱
bz.alarm();
}
void loop(){
if (Serial.available()) { SerialBT.write(Serial.read()); }
if (SerialBT.available()) {
int i;
for (i=0; i<4; i++){ BTCMD[i] = SerialBT.read(); }
}
if(atoi(BTCMD)>1) { PWMspeed = atoi(BTCMD);}
BTCMD[0] = 'D';
if(BTCMD[0] == 'F') { gs.act(GoSUMO::FORWARD, PWMspeed); } //GoSUMO 前進
else if(BTCMD[0] == 'B') { gs.act(GoSUMO::BACKWARD, PWMspeed); } //GoSUMO 後退
else if(BTCMD[0] == 'L') { gs.act(GoSUMO::GO_LEFT, PWMspeed); } //GoSUMO 左旋轉
else if(BTCMD[0] == 'R') { gs.act(GoSUMO::GO_RIGHT, PWMspeed); } //GoSUMO 右旋轉
else if(BTCMD[0] == 'l') { gs.act(GoSUMO::L_TVL, PWMspeed); } //GoSUMO 左橫移
else if(BTCMD[0] == 'r') { gs.act(GoSUMO::R_TVL, PWMspeed); } //GoSUMO 右橫移
else if(BTCMD[0] == 'q') { gs.act(GoSUMO::RF_TVL, PWMspeed); } //GoSUMO 右前橫移
else if(BTCMD[0] == 'e') { gs.act(GoSUMO::LB_TVL, PWMspeed); } //GoSUMO 左後橫移
else if(BTCMD[0] == 'w') { gs.act(GoSUMO::LF_TVL, PWMspeed); } //GoSUMO 左前橫移
else if(BTCMD[0] == 't') { gs.act(GoSUMO::RB_TVL, PWMspeed); } //GoSUMO 右後橫移
else if(BTCMD[0] == 'Z') { gs.stop(); }
else if(BTCMD[0] == 'H') { bz.alarm(); }
/*Servo Control, start here. */
else if(BTCMD[0] == 'A') { } //ServoBase Rising
else if(BTCMD[0] == 'a') { } //ServoBase Declining
else if(BTCMD[0] == 'P') { } //ServoPaw OPEN
else if(BTCMD[0] == 'p') { } //ServoPaw CLOSE
else if(BTCMD[0] == 'z') { } //ARM Homing
else if(BTCMD[0] == 'C') {
Serial.print(us_F.ObjDistance());
Serial.print(", ");
Serial.print(us_R.ObjDistance());
Serial.print(", ");
Serial.println(us_L.ObjDistance());
delay(500);
Serial.println("--");
}
else if(BTCMD[0] == 'y') {
Serial.println(ir.ReadTCRT(1000, 1));
delay(1000);
}
}