2016年2月20日 星期六

ROSA 系統開發 26 ─ P&B 6x2 Spider 妖怪手錶體操舞

http://4rdp.blogspot.com/2016/02/rosa-26-p-6x2-spider.html



P&B 6x2 Spider 妖怪手錶體操舞

續前文,在沒有動作編輯軟體的幫忙下,終於編出一段 66 秒妖怪手錶體操舞,舞不好編原因很多,例如跳舞動作要慢動作一看再看影片擷取精華,並且機器蜘蛛形體不同於人體,許多地方要修改,也許日後製作人形機器人就可以完全仿製動作更為傳神。

親自編舞之後,也可以更加了解,編舞創作者需要什麼工具與功能,才能提升創作速度,畢竟一般人耐性有限,過度繁雜的事,多數人容易半途而廢,現在 ROSA 有了 TEMPO 及 DANCE 指令,就很容易精準控制節拍,不用安插多餘的等待指令,並且快動作、慢動作自動配合節拍調整速度,讓舞蹈動作編輯簡單許多,這就是使用 ROSA 並且沒有動作編輯軟體,也很容易精準編舞創作。

// (C) 2015, Bridan Wang, CC BY-NC-SA 3.0 TW
// http://4rdp.blogspot.tw/search/label/ROSA%20(Arduino)


#define zeo 0           // zero
#define lif 45          // lift leg
#define ris 135         // rise 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 fd5 45          // forward 45
#define bk5 135         // backward 135
#define fd0 30          // forward 30
#define bk0 150         // backward 150

const byte RUN_5[] PROGMEM = {
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_TEMPO,  50, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //0
_DANCE, fd5, zeo, fd5, zeo, fwd, std, fwd, std, mid, std, mid, std,   //1  14-17
_DANCE, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //2
_LOOP,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //3
_DANCE, 255, lif, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //4
_DANCE, 255, zeo, 255, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //5
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //6
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //7
_DANCE, 255, zeo, 255, zeo, mid, 255, fd0, 255, bck, 255, fwd, 255,   //8  17-25
_DANCE, 255, lif, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //9
_DANCE, 255, zeo, 255, zeo, fd0, 255, mid, 255, fwd, 255, bck, 255,   //10
_DANCE, 255, lif, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //11
_DANCE, 255, zeo, 255, zeo, fwd, 255, fwd, 255, mid, bck, mid, bck,   //12
_DANCE, 255, lif, 255, lif, 255, 255, 255, 255, 255, std, 255, std,   //13
_DANCE, 255, zeo, 255, zeo, 255, 255, 255, 255, 255, bck, 255, bck,   //14
_DANCE, 255, lif, 255, lif, 255, 255, 255, 255, 255, std, 255, std,   //15
_NEXT,    9, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //16
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_DANCE, 255, lif, 255, zeo, mid, std, mid, std, fd5, hon, fd5, hon,   //17 25-29
_LOOP,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //18
_DANCE, 255, 255, mid, 255, 255, hon, 255, hon, 255,  70, 255, 110,   //19
_DANCE, 255, 255, fd5, 255, 255, hon, 255, hon, 255, 110, 255,  70,   //20
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //21 
_DANCE, fd5, zeo, fd5, zeo, fwd, std, fwd, std, mid, std, mid, std,   //22  
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_TEMPO,  25, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //23 29-33
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //24
_DANCE, fd5, zeo, bk5, zeo, fwd, std, fwd, std, 255, std, 255, std,   //25 
_DANCE, 255, 255, 255, lif, 255, hon, 255, hon, 255, 255, 255, 255,   //26
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //27
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //28
_DANCE, mid, zeo, fd5, zeo, 255, 255, 255, 255, 255, std, 255, std,   //29
_DANCE, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //30
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //31
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //32
_DANCE, fd5, zeo, mid, zeo, 255, 255, 255, 255, 255, std, 255, std,   //33 
_DANCE, 255, 255, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //34
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //35
_DANCE, bk5, zeo, fd5, zeo, mid, std, mid, std, mid, std, mid, std,   //36
_DANCE, fd5, zeo, bk5, zeo, 255, hon, 255, hon, mid, hon, mid, hon,   //37
_DANCE, bk5, zeo, fd5, zeo, 255, 255, 255, 255, mid, 255, mid, 255,   //38
_DANCE, bk5, lif, bk5, lif, mid, std, mid, std, fd5, 255, fd5, 255,   //39
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_LOOP,   12, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //40 33-37
_DANCE, bk5, 100, bk5,  80, mid, 100, mid,  80, fd5, 100, fd5,  80,   //41 
_DANCE, hon,  80, hon, 100, hon,  80, hon, 100, hon,  80, hon, 100,   //42
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //43
_TEMPO,  50, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //44
_DANCE, bk5, zeo, fd5, zeo, 255, std, 255, std, 255, std, 255, std,   //45
_DANCE, fd5, zeo, bk5, zeo, 255, std, 255, std, 255, std, 255, std,   //46
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12  
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //47
_DANCE, fd5, zeo, fd5, zeo, mid, std, mid, std, mid, std, mid, std,   //48 37-41
_DANCE, 255, std, 255, std, 255, 255, 255, 255, 255, 255, 255, 255,   //49
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //50
_DANCE, bk5, bk5, bk5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //51
_DANCE, 255, bk5, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //52
_DANCE, 255, bk5, 255, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //53
_DANCE, 255, bk5, 255, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //54
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_DANCE, bk5, zeo, bk5, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //55 41-45
_DANCE, 255, lif, 255, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //56
_DANCE, 255, zeo, 255, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //57
_DANCE, 255, bk5, 255, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //58
_TEMPO, 100, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //59
_DANCE, bk5, bk5, zeo, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //60
_DANCE, bk5, zeo, bk5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //61
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_DANCE, zeo, bk5, bk5, bk5, 255, 255, 255, 255, 255, 255, 255, 255,   //62 45-51
_DANCE, bk5, zeo, bk5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //63
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //64
_DANCE, fd5, lif, fd5, lif, 255, 255, 255, 255, 255, bck, 255, bck,   //65
_DANCE, fd5, zeo, fd5, zeo, 255, 255, 255, 255, 255, std, 255, std,   //66
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, hon, 255, hon,   //67
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_TEMPO,  25, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //68
_LOOP,    2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //69
_DANCE, mid, std, mid, zeo, 255, zeo, 255, std, 255, std, 255, std,   //70 51-53
_DANCE, mid, std, mid, std, 255, std, 255, std, 255, std, 255, std,   //71
_DANCE, mid, zeo, mid, std, 255, std, 255, zeo, 255, std, 255, std,   //72
_DANCE, mid, std, mid, std, 255, std, 255, std, 255, std, 255, std,   //73
_NEXT,    5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //74
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_TEMPO,  50, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //75
_DANCE, mid, std, mid, zeo, 255, zeo, 255, std, 255, std, 255, std,   //76 53-57
_DANCE, mid, std, mid, std, 255, std, 255, std, 255, std, 255, std,   //77
_TEMPO,  25, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //78
_LOOP,    5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //79
_DANCE, bk5, 100, bk5,  80, mid, 100, mid,  80, fd5, 100, fd5,  80,   //80 
_DANCE, hon,  80, hon, 100, hon,  80, hon, 100, hon,  80, hon, 100,   //81
_NEXT,    3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //82
_DANCE, bk5, 100, bk5,  80, mid, 100, mid,  80, fd5, 100, fd5,  80,   //83 
_DANCE, mid, zeo, mid, zeo, mid, std, mid, std, mid, std, mid, std,   //84
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_TEMPO,  50, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //85
_DANCE, fd0, zeo, bk5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //86 57-61
_DANCE, fd5, zeo, mid, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //87
_DANCE, mid, zeo, fd5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //88
_DANCE, fd5, zeo, fd5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //89
_TEMPO, 100, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //90
_DANCE, fd0, std, bk5, std, 255, 255, 255, 255, 255, 255, 255, 255,   //91
_DANCE, fd0, bk5, fd5, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //92
//   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12 
_DANCE, 255, 255, 255, lif, 255, 255, 255, 255, 255, 255, 255, 255,   //93 61-66
_DANCE, 255, 255, 255, zeo, 255, 255, 255, 255, 255, 255, 255, 255,   //94
_TEMPO,  10, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //95
_LOOP,    8, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //96
_DANCE, fd0, std, fd0, std, bk0, std, bk0, std, fd0, std, fd0, std,   //97
_DANCE, bk0, lif, bk0, hon, fd0, hon, fd0, lif, bk0, lif, bk0, hon,   //98
_DANCE, hon, std, hon, std, hon, std, hon, std, hon, std, hon, std,   //99
_DANCE, fd0, hon, fd0, lif, bk0, lif, bk0, hon, fd0, hon, fd0, lif,   //100
_NEXT,    5, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,   //101
_GOTO, 212,                              // goto RUN_P
};



void ACTION_SET(void){
  static byte loopn;
  byte i, j, k, m;

  //Serial.print(ir_code);

  //Serial.print(" - ");
  //Serial.print(step_no);
  //Serial.print(" - ");
  //Serial.println(pgm_read_byte(ACTION[ir_code] 
                   + step_no * SERVO_TABLE));

  tempo = 1;   

  switch (pgm_read_byte(ACTION[ir_code] + step_no*SERVO_TABLE)){
    case _SERVO:
      for (i = 1; i < SERVO_TABLE; i++){
j = pgm_read_byte(ACTION[ir_code]
            + step_no * SERVO_TABLE + i);
if (j == 250)
         servo_hold[i] = 0;         // hold off
else if (j == 251)
         servo_hold[i] = 255;       // hold on
else if (j >= 252 && j < 255)
         servo_set[i] = 90;
else if (j < 181)
         servo_set[i] = j;
      }
      break;
    case _DANCE:
      for (i = 1; i < SERVO_TABLE; i++){
j = pgm_read_byte(ACTION[ir_code]
            + step_no * SERVO_TABLE + i);
if (j == 250)
         servo_hold[i] = 0;         // hold off
else if (j == 251)
         servo_hold[i] = 255;       // hold on
        else if (j >= 252 && j < 255){ 
          servo_set[i] = j = 90; 
          goto set_speed; 
        } else if (j < 181){ 
          servo_set[i] = j; 
set_speed: 
          if (j >= servo_angle[i]) 
            k = j - servo_angle[i]; 
          else 
            k = servo_angle[i]-j; 
          m = tempo_time / 2 / SERVO_TABLE; 
          if (k % m == 0) 
            servo_speed[i] = k / m; 
          else 
            servo_speed[i] = k / m + 1; 
        }       
      }
      tempo = 0;
      break;
    case _TEMPO:
      tempo_set = pgm_read_byte(ACTION[ir_code]
          + step_no * SERVO_TABLE + 1);
      tempo_time = (unsigned int) 10 * tempo_set;
      break;
    case _HOLD:
      for (i = 1; i < SERVO_TABLE; i++){
j = pgm_read_byte(ACTION[ir_code]
           + step_no * SERVO_TABLE + i);
if (j != 255)
         servo_hold[i] = j;
      }
      break;
    case _SPEED:
      for (i = 1; i < SERVO_TABLE; i++){
j = pgm_read_byte(ACTION[ir_code]
           + step_no * SERVO_TABLE + i);
if (j != 255)
         servo_speed[i] = j;
      }
      break;
    case _WAIT:
      step_wait = pgm_read_byte(ACTION[ir_code]
          + step_no * SERVO_TABLE + 1);
      break;
    case _RETURN:
      ir_code = pre_ir;
      goto ret;
    case _NEXT:
      if (loopn != 255) {
if (loopn == 0) break;
loopn--;
      }
      step_no -= pgm_read_byte(ACTION[ir_code] + step_no * SERVO_TABLE + 1);
      break;
    case _GOTO:
      j = pgm_read_byte(ACTION[ir_code]
         + step_no * SERVO_TABLE + 1);
      if (j >= 200){
ir_code = j - 200;
ret:
step_no = 255;
      } else
step_no = j - 1;
      break;
    case _LOOP:
      loopn = pgm_read_byte(ACTION[ir_code]
             + step_no * SERVO_TABLE + 1) - 1;
      if (loopn == 254) loopn++;       // 0 or 255 always loop
      break;
    case _STOP:
      ir_code = 0;
  }
}


這一版新程式有兩個地方修改,一個是變數陣列名稱 servo_power[] 改成 servo_speed[],這是為了對應 ROSA SPEED 指令,統一名稱以避免玩家混淆,認為 servo_power[] 在控制馬達電力,前文的內容已經修正。

另一個是 NEXT 回跳位址指定,由絕對位址改成相對位址,現在本文顯示的是相對位址,為什麼要用相對位址?當你在動作編輯時,難免會有插入或刪除,如果採用絕對位址,一但動作次序更動,NEXT 回跳位址就要改來改去不勝其擾,因此 NEXT 改為相對位址就不會受迴圈外其它動作加入或刪除而影響,NEXT 數值為往回跳至 LOOP 的行數。

6 則留言:

  1. 哈哈哈~這個創作太讚了! 那歌曲是程式裡面的code嗎?

    回覆刪除
  2. 妖怪手錶體操舞是最近幼兒園與小學生比較流行的歌曲,以它作為背景音樂,而程式碼只是同步控制機器蜘蛛的動作,想要讓機器人跳舞與音樂同步不是一件容易的事,老師的學校不是要買 Arduino 套件嗎,到時候套件也可以轉用於這機器蜘蛛使用,不過需要再加購機器蜘蛛板材、雙孔 USB 行動電源、十幾顆伺服馬達以及一條 USB 電源線,約兩千多元,就可以玩很多有趣的東西。

    回覆刪除
  3. 回覆
    1. Kent您好,

      P&B Spider 是我與網友 Pizg 合作開發的,因此蜘蛛的機構木片零件在外面市場是買不到的,不過其它電子零組件在電子材料行或是網路商店可以買到。
      蜘蛛本體 http://pizgchen.blogspot.tw/2016/01/spider-6x2.html
      電子零組件 http://4rdp.blogspot.tw/2015/12/rosa-17-p-4-x-2-spider.html (SG90馬達要12顆)
      如果還有其它問題,歡迎以 idea22much@gmail.com 聯絡

      補充說明,花費兩千多元的條件是已經有 Arduino 套件(價值一千多元),因此總額約在四千多元

      刪除
    2. 所以這是based on arduino開發的嗎

      刪除
    3. 老師是的,ROSA 這系列是以 Arduino 開發,它是 Robot Operation System for Arduino,程式碼目前已開源。http://4rdp.blogspot.tw/2017/08/rosa-37-rwg-6x2-spider.html
      若想用它於教學,可分三層次,小學生把機器組起來,程式灌進去就可以玩。中學生可以微調動作程式碼。大學生應該學系統程式。
      先預告,我正在幫 maker 達人林益成改寫一個機器人,本月中之後會陸續釋出,有興趣可以參考。

      刪除