(請開啟字幕觀賞)
P&B 4x2 Spider
這款機器蜘蛛姑且稱為 P&B 4 x 2 Spider,設計理念很簡單,要讓 Maker 玩家除了蜘蛛機構本體,其它所需零組件都盡可能在現有通路買的到,以方便無電子電路基礎玩家入門學習,減少製作電路障礙,清單如下:
1. Arduino UNO x 1
2. Arduino IO 擴充板 x 1
3. SG-90 伺服馬達 x 8
4. 雙孔 USB 行動電源 (Output 5V 2.1A) x 1
5. KEYES 紅外線遙控器及模組 x 1
6. 3-pin 母對母杜邦線 x 1
7. USB 轉 TTL 傳輸線 (或是自製 USB 電源線 ) x 1
8. 超音波模組 (可略,目前當眼睛裝飾,也可以其它物件替代) x 1
好不多說,先看 ROSA 程式怎麼寫,
// (C) 2015, Bridan Wang, CC BY-NC-SA 3.0 TW
// http://4rdp.blogspot.tw/search/label/ROSA%20(Arduino)
#define LAST_SERVO 8 // for 4 x 2 spider
#define SERVO_TABLE 13
#define zeo 0 // zero
#define lif 45 // lift leg
#define std 90 // stand
#define hon 251 // hold on
#define hof 250 // hold off
#define fwd 60 // forward
#define mid 90 // middle
#define bck 120 // backward
#define lif 45 // lift leg
#define std 90 // stand
#define hon 251 // hold on
#define hof 250 // hold off
#define fwd 60 // forward
#define mid 90 // middle
#define bck 120 // backward
byte servo_pin[] =
{ 0, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 17 };
byte servo_revse[] =
{ 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1 };
{ 0, 4, 5, 6, 7, 9, 10, 11, 12, 14, 15, 16, 17 };
byte servo_revse[] =
{ 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1 };
byte servo_angle[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte servo_set[] =
{ 0, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90 };
byte servo_speed[] =
{ 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
byte servo_hold[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
const byte RUN_0[] PROGMEM = { // spider start
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SPEED, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, //0
_SERVO,fwd,lif,255,255,255,255,255,255,255,255,255,255, //1
_SERVO,mid,std,255,255,255,255,255,255,255,255,255,255, //2
_SERVO,hon,hon,fwd,lif,255,255,255,255,255,255,255,255, //3
_SERVO,255,255,mid,std,255,255,255,255,255,255,255,255, //4
_SERVO,255,255,hon,hon,fwd,lif,255,255,255,255,255,255, //5
_SERVO,255,255,255,255,mid,std,255,255,255,255,255,255, //6
_SERVO,255,255,255,255,hon,hon,fwd,lif,255,255,255,255, //7
_SERVO,255,255,255,255,255,255,mid,std,255,255,255,255, //8
_SERVO,255,255,255,255,255,255,hon,hon,fwd,lif,255,255, //9
_SERVO,255,255,255,255,255,255,255,255,mid,std,255,255, //10
_SERVO,255,255,255,255,255,255,255,255,hon,hon,fwd,lif, //11
_SERVO,255,255,255,255,255,255,255,255,255,255,mid,std, //12
_GOTO, 212, // goto RUN_P //13
};
const byte RUN_P[] PROGMEM = { // spider stand
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,255,std,255,std,255,std,255,std,mid,std,mid,std, //0
_HOLD, 250,250,250,250,250,250,250,250,250,250,250,250, //1
_STOP, //2
};
const byte RUN_1[] PROGMEM = { // spider wave
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_LOOP, 3,255,255,255,255,255,255,255,255,255,255,255, //0
_SERVO,255,lif,255,255,255,255,255,255,255,255,255,255, //1
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //2
_NEXT, 1,255,255,255,255,255,255,255,255,255,255,255, //3
_RETURN, //4
};
const byte RUN_2[] PROGMEM = { // spider hello
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,255,lif,255,255,255,255,255,255,255,255,255,255, //0
_LOOP, 3,255,255,255,255,255,255,255,255,255,255,255, //1
_SERVO,fwd,255,255,255,255,255,255,255,255,255,255,255, //2
_SERVO,mid,255,255,255,255,255,255,255,255,255,255,255, //3
_NEXT, 2,255,255,255,255,255,255,255,255,255,255,255, //4
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //5
_RETURN, //6
};
const byte RUN_3[] PROGMEM = { // spider dance-1
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,bck,std,bck,std,fwd,std,fwd,std,fwd,std,fwd,std, //0
_HOLD, 150,255,150,255,150,255,150,255,150,255,150,255, //1
_LOOP, 3,255,255,255,255,255,255,255,255,255,255,255, //2
_SERVO,255, 60,255,120,255, 60,255,120,255, 60,255,120, //3
_SERVO,255,std,255,std,255,std,255,std,255,std,255,std, //4
_NEXT, 3,255,255,255,255,255,255,255,255,255,255,255, //5
_LOOP, 3,255,255,255,255,255,255,255,255,255,255,255, //6
_SERVO,255,120,255, 60,255,120,255, 60,255,120,255, 60, //7
_SERVO,255,std,255,std,255,std,255,std,255,std,255,std, //8
_NEXT, 7,255,255,255,255,255,255,255,255,255,255,255, //9
_GOTO, 0, //10
};
const byte RUN_4[] PROGMEM = { // spider dance-2
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,mid,std,mid,std,mid,std,mid,std,mid,std,mid,std, //0
_SERVO,255,zeo,255,255,255,hon,255,255,255,255,255,255, //1
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //2
_SERVO,255,hon,255,255,255,255,255,255,255,255,255,255, //3
_SERVO,255,255,255,zeo,255,255,255,255,255,255,255,255, //4
_SERVO,255,255,255,std,255,255,255,255,255,255,255,255, //5
_SERVO,255,255,255,hon,180,255,255,255,mid,std,mid,std, //6
_SERVO,255,255,255,255,255,255,255,zeo,255,255,255,255, //7
_SERVO,255,255,255,255,mid,255,255,std,255,255,255,255, //8
_SERVO,255,255,255,255,255,255,180,hon,255,255,255,255, //9
_SERVO,255,255,255,255,255,zeo,255,255,255,255,255,255, //10
_SERVO,255,255,255,255,255,std,255,255,255,255,255,255, //11
_GOTO, 0, //12
};
const byte RUN_5[] PROGMEM = {};
const byte RUN_6[] PROGMEM = {};
const byte RUN_7[] PROGMEM = { // spider speed slow
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SPEED, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //0
_RETURN, //1
};
const byte RUN_8[] PROGMEM = { // spider speed normal
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SPEED, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, //0
_RETURN, //1
};
const byte RUN_9[] PROGMEM = { // spider speed fast
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SPEED, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, //0
_RETURN, //1
};
const byte RUN_U[] PROGMEM = { // spider forward x 6 steps
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,255,hon,255,lif,255,lif,255,hon,255,hon,255,lif, //0
_SERVO,bck,255,255,255,255,255,bck,255,bck,255,255,255, //1
_SERVO,hon,255,fwd,255,fwd,255,hon,255,hon,255,fwd,255, //2
_SERVO,255,255,255,std,255,std,255,255,255,255,255,std, //3
_SERVO,255,lif,255,hon,255,hon,255,lif,255,lif,255,hon, //4
_SERVO,fwd,255,255,255,255,255,fwd,255,fwd,255,255,255, //5
_SERVO,255,255,bck,255,bck,255,255,255,255,255,bck,255, //6
_SERVO,255,std,hon,255,hon,255,255,std,255,std,hon,255, //7
_GOTO, 0, //8
};
const byte RUN_D[] PROGMEM = { // spider backward x 6 steps
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,255,hon,255,lif,255,lif,255,hon,255,hon,255,lif, //0
_SERVO,fwd,255,255,255,255,255,fwd,255,fwd,255,255,255, //1
_SERVO,hon,255,bck,255,bck,255,hon,255,hon,255,bck,255, //2
_SERVO,255,255,255,std,255,std,255,255,255,255,255,std, //3
_SERVO,255,lif,255,hon,255,hon,255,lif,255,lif,255,hon, //4
_SERVO,bck,255,255,255,255,255,bck,255,bck,255,255,255, //5
_SERVO,255,255,fwd,255,fwd,255,255,255,255,255,fwd,255, //6
_SERVO,255,std,hon,255,hon,255,255,std,255,std,hon,255, //7
_GOTO, 0, //8
};
const byte RUN_R[] PROGMEM = { // spider turn right
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_LOOP, 4,255,255,255,255,255,255,255,255,255,255,255, //0
_SERVO,fwd,lif,255,255,255,hon,255,255,255,255,255,255, //1
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //2
_SERVO,255,hon,bck,lif,255,255,255,255,255,255,255,255, //3
_SERVO,255,255,255,std,255,255,255,255,255,255,255,255, //4
_SERVO,255,255,255,hon,255,255,bck,lif,255,255,255,255, //5
_SERVO,255,255,255,255,255,255,255,std,255,255,255,255, //6
_SERVO,255,255,255,255,fwd,lif,255,hon,255,255,255,255, //7
_SERVO,255,255,255,255,255,std,255,255,255,255,255,255, //8
_SERVO,bck,255,fwd,255,bck,hon,fwd,255,bck,255,fwd,255, //9
_NEXT, 1,255,255,255,255,255,255,255,255,255,255,255, //10
_RETURN, //11
};
const byte RUN_L[] PROGMEM = { // spider turn left
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_LOOP, 4,255,255,255,255,255,255,255,255,255,255,255, //0
_SERVO,255,255,fwd,lif,255,255,255,255,255,255,255,255, //1
_SERVO,255,255,255,std,255,255,255,255,255,255,255,255, //2
_SERVO,bck,lif,255,hon,255,255,255,255,255,255,255,255, //3
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //4
_SERVO,255,hon,255,255,bck,lif,255,255,255,255,255,255, //5
_SERVO,255,255,255,255,255,std,255,255,255,255,255,255, //6
_SERVO,255,255,255,255,255,hon,fwd,lif,255,255,255,255, //7
_SERVO,255,255,255,255,255,255,255,std,255,255,255,255, //8
_SERVO,fwd,255,bck,255,fwd,255,bck,hon,fwd,255,bck,255, //9
_NEXT, 1,255,255,255,255,255,255,255,255,255,255,255, //10
_RETURN, //11
};
const byte RUN_K[] PROGMEM = { // spider forward-2 x 6 steps
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,fwd,lif,hon,255,hon,255,hon,255,hon,255,hon,255, //0
_SERVO,255,std,255,255,255,255,255,255,255,255,255,255, //1
_SERVO,255,hon,fwd,lif,255,255,255,255,255,255,255,255, //2
_SERVO,255,255,255,std,255,255,255,255,255,255,255,255, //3
_SERVO,255,255,255,hon,fwd,lif,fwd,lif,255,255,255,255, //4
_SERVO,255,255,255,255,255,std,255,std,255,255,255,255, //5
_SERVO,255,255,255,255,255,hon,255,hon,fwd,lif,fwd,lif, //6
_SERVO,255,255,255,255,255,255,255,255,255,std,255,std, //7
_SERVO,bck,255,bck,255,bck,255,bck,255,bck,hon,bck,hon, //8
_GOTO, 0, //9
};
const byte RUN_S[] PROGMEM = { // spider sit
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_SERVO,255,lif,255,lif,255,lif,255,lif,255,lif,255,lif, //0
_GOTO, 200, // goto RUN_N //1
};
const byte RUN_N[] PROGMEM = { // spider stop
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
_HOLD, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, //0
_STOP, //1
};
const byte *ACTION[] = {
RUN_N, // none,
RUN_1, // 1
RUN_2, // 2
RUN_3, // 3
RUN_4, // 4
RUN_5, // 5
RUN_6, // 6
RUN_7, // 7
RUN_8, // 8
RUN_9, // 9,
RUN_0, // 0
RUN_S, // *
RUN_P, // #
RUN_U, // up
RUN_D, // down
RUN_R, // right
RUN_L, // left
RUN_K // ok
};
// X, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, *, #,up,dn,rt,lf,ok
0,22,25,13,12,24,94, 8,28,90,82,66,74,70,21,67,68,64,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
void(*FUNC_JUMP[])(void) = {
FUNC_N, // none
FUNC_N, // FUNC_1, // 1
FUNC_N, // FUNC_2, // 2
FUNC_N, // FUNC_3, // 3
FUNC_N, // FUNC_4, // 4
FUNC_N, // FUNC_5, // 5
FUNC_N, // FUNC_6, // 6
FUNC_N, // FUNC_7, // 7
FUNC_N, // FUNC_8, // 8
FUNC_N, // FUNC_9, // 9
FUNC_N, // FUNC_0, // 0
FUNC_N, // FUNC_S, // *
FUNC_N, // FUNC_P, // #
FUNC_N, // FUNC_U, // up
FUNC_N, // FUNC_D, // down
FUNC_N, // FUNC_R, // right
FUNC_N, // FUNC_L, // left
FUNC_N, // FUNC_K // ok
};
void SYS_TIMER(void) {
static byte tm_10ms = 0;
static byte tm_100ms = 0;
static byte tm_1sec = 0;
while (millis() - now >= 2) {
now += 2;
tm_10ms++;
tm_100ms++;
PROCESS_SERVO();
}
if (tm_10ms >= 5) {
tm_10ms -= 5;
PROCESS_10ms();
}
if (tm_100ms >= 50) {
tm_100ms -= 50;
PROCESS_100ms();
tm_1sec++;
}
if (tm_1sec >= 10) {
tm_1sec -= 10;
PROCESS_1sec();
}
}
IR_CHECK();
}
// system timer0
now = millis();
// pin 0,1
// Open serial communications and wait for port to open:
Serial.begin(BAUD);
while (!Serial) {}; // wait for serial port to connect.
// pin 2,3
ir.begin(); // open IR
ir_code = 10;
step_no = 0; // spider start
}
使用了 ROSA,對機器蜘蛛的動作控制就變成動作編輯,只要更動程序內容,不再需要大幅修改程式了。 #define LAST_SERVO 8 表示使用八顆伺服馬達,雖然這隻四腳蜘蛛只用到八顆馬達,不過變數仍預留十二顆馬達記憶空間,因為下周將介紹另一隻六腳蜘蛛會用到。
將所有紅外線遙控碼對應的 FUNC_X[] 改成 FUNC_N[],也就是執行空指令,並執行 RUN_X[] 內的程序設定。
RUN_0[] 為蜘蛛一開機的預設動作,讓每個馬達停位在 90 度角,這也方便組裝者馬達定位用,_GOTO 有兩種跳法,數值 200 以內會跳到自身程序內的行號,其它會跳到外部對應的紅外線遙控碼程序,像那 212 去掉 200 等於12,對應 *ACTION[] 是 RUN_P[],它就會接下去執行 RUN_P[] 站起來的動作。
RUN_1[] 前肢抬腿三次,
RUN_2[] 揮手跟你說 Hello,
RUN_3[]、RUN_4[] 跳舞,
RUN_5[]、RUN_6[] 空白無作用,
RUN_7[] 慢速動作,
RUN_8[] 正常速度動作,
RUN_9[] 快速動作,
RUN_U[] 前進,
RUN_D[] 後退,
RUN_R[] 右轉,
RUN_L[] 左轉,
RUN_K[] 蛙泳前進,
RUN_S[] 坐下,
RUN_N[] 停止。
結尾動作放一個 _RETURN 可以當一個副程式,例如原本動作正在前進中,按下遙控器右轉鍵,原地右轉後,會自動繼續之前前進動作,目前安排蜘蛛的打招呼、調速、左右轉等動作都有 _RETURN,而跳舞及前進後退等動作有 _GOTO 0,除非被中斷停止不然會持續動作。
另外 _SERVO 動作編輯也定義一些常數,zeo 零度角、 lif 抬腿、 std 站立、 hon 持續通電、 hof 停止通電、 fwd 前進、 mid 中間 90 度角、 bck 後退,數值 255 表示不更動狀態,其它數值表示特定角度。因為伺服馬達增多了,分時控制的時間修改成 2 ms,因此 SYS_TIMER()內的數值配合修正。
對機器蜘蛛製作有興趣的朋友可以與我們聯絡。
我想學
回覆刪除請問這樣的組合要多少錢?
您好,
刪除很高興看到你的留言,因為你是前期試用戶,會給予客製化服務及價格優惠。
我與 Pizg 的聯絡信箱是idea22much@gmail.com,請將型號、數量,姓名,電話,寄送地址,或特殊需求列明,若有 Line 帳號歡迎提供以便緊急聯繫處理,相關明細亦將回信答覆你。
謝謝