Masahiro Mizuno
Published © GPL3+

4-Legged Walking Robot Control Software

4-Legged Walking Robot software that can control music and motion synchronously.

IntermediateFull instructions provided10 hours899
4-Legged Walking Robot Control Software

Things used in this project

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Ir Remote Controller

Story

Read more

Schematics

Control board Schematic

Code

Software

Arduino
// ============================================
//  4-Legged walking robot "Chappi" Control Software
//  Arduino nano
// ============================================
//  PORT ASSIGNMENT
// ============================================
// D2:BUZZ       
// D3:SONAR ECHO D4:SONAR TRIG
// D5:SERVO FR   D6:SERVO FL
// D7:SERVO RR   D8:SERVO RL
// D9:SERVO TABLE
// D10:LED       D11:RGB
// D12:IR
// A0:PHOTO TR   A1:CHARGING
// ============================================
//  FILE INCLUDE 
// ============================================
  #include "Notes.h"                                   // 
  #include <Servo.h>  
  #include <Ultrasonic.h> 
   Servo FRsvo; Servo FLsvo; Servo RRsvo; Servo RLsvo; // 4 legs
   Servo TBL;                                          // Turntable
   Ultrasonic ultrasonic(4,3);                         // (Trig PIN,Echo PIN)    
// ============================================
//  CONTROL VALUABLES
// ============================================ 
   int stepp = 0;                               // walking sequence step
   boolean autom = true;                        // IR controller/auto mode
   int part = 0;                                // voice part on qualtet
// ============================================
//  SETUP
// ============================================
void setup() {
  Serial.begin(9600);                // Serial Monitor  
  pinMode(10, OUTPUT);               // LED
  pinMode(13, OUTPUT);               // nano on board LED
  pinMode(12, INPUT_PULLUP);         // IR
  pinMode(A1, INPUT);                // Charge voltage 0-560
  TBL.attach(9);                     // Table Servo Attach
  SVOattach(1);                      // 4-Legs Servo attach
  pause(0);                          // Set home position
  delay(300);   
}
// ============================================
//  LOOP
  int inter = 1000; 
  int zone;                                 // 0: short 1:middle 2:long
  long itime1, itime2, itime3;              // event timer  
  boolean tgll, tg;                         // led tggle
// ============================================
void loop() {
  IRreceiver(); if(autom) {
    if(millis() - itime2 > 200) { itime2 = millis();                       // 200ms loop
      ultras();                                                            // measure distance
      if(!zone) { SVOattach(1); FR(65*tg+10); FL(65*!tg+10); noTone(2); }  // short distance                                                                       // 15cm RED
      else if(zone == 1 || stepp) { go(); }                                // middle distance
      else if(zone == 2) { noTone(2); SVOattach(0); }                      // long distance Servo detach
    } tablecontrol();                                                      // Turntable control
  } 
  if(millis() - itime1 > inter) { itime1 = millis(); tgll = !tgll;         // table/charge check
    int vol = analogRead(A1);                                              // Serial.print("A1 voltage: "); Serial.println(vol);
    inter = 1000; if(vol > 300) { inter = 400; } digitalWrite(13,  tgll);  // ON board LED flash
  }   
  if(millis() - itime3 > 1800) { itime3 = millis(); tg = !tg; }            // near distance pause interval timer
}
// ============================================
//  TURNTABLE control
  int Rstate, Rtim;
  int dstep = 90; int ddir = 1;                // Table Control parameters  
  long itime1t, itime2t;
// ============================================
void tablecontrol() {
   if(inter < 1000) {                                                 // table activate mode 
     if(millis() - itime1t > 300 && zone == 2) { itime1t = millis();  // table rotation 300ms loop 
        if(ddir) { if(dstep < 150) dstep++; } else { if(dstep > 60) dstep--; } TBL.write(dstep);
     }   
     if(millis() - itime2t > Rtim) { itime2t = millis();              // table random pose
        Rtim = random(5000*2, 12000*2); ddir = !ddir;                 // random interval time/direction change
        Rstate++; if(Rstate > 7) { Rstate = 0; }
        switch(Rstate) {
             case 0: pause(0);                     break;  // Home
             case 1: pause(8);                     break;  // Right stretch
             case 2: pause(0);                     break;  // Home
             case 3: pause(1);                     break;  // Rear stretch!! 
             case 4: pause(0);                     break;  // Home             
             case 5: pause(9);                     break;  // Left stretch
             case 6: pause(0);                     break;  // Home
             case 7: pause(2); CloseEncounters();  break;  // ful stretch!! 
        }           
     }  
   }    
}

// ============================================
//  IR RECEIVER
// ============================================
void IRreceiver() { // command decode
   char foo = IRdrcv();
   if(foo) {
     switch(foo) {
       case '1':  Serial.print("charge voltage level(0-600): ");      
                  Serial.println(analogRead(A1));          break;  // light/charge sensor test
       case '2':  Serial.print("ultrasonic distance measurement(cm): ");
                  Serial.println(ultrasonic.Ranging(CM));  break;  // ultrasonic test
       case '3':  DanceoftheRead();            break;  // buzz test
       case '4':  pause(1);                    break;  // Rear ful stretch
       case '5':  pause(2);                    break;  // Ful stretch
       case '6':  pause(3);                    break;  // Front stretch
       case '7':  pause(4);                    break;  // Rear fuse
       case '8':  pause(5);                    break;  // Ful fuse
       case '9':  pause(6);                    break;  // Front fuse 
       case '0':  //pause(7); 
                  CloseEncounters(); break;  // Square Home position  
       case '*':  ImperialMarch1();            break;  // * small steps
       case '#':  ImperialMarch2();            break;  // #
       case 'U':  go();                        break;  // UP    forward steps
       case 'D':  goback();                    break;  // DOWN  reverse steps
       case 'L':  ImperialMarch3();            break;  // LEFT  left direction
       case 'R':  LadyMaddonna();              break;  // RIGTH right direction
       case 'K':  Serial.print("auto mode:");  autom = !autom; digitalWrite(10, !autom);  
                  Serial.println(autom);       break;  // OK    auto or manual
     }
   }    
}

// ============================================
// Servo Control
// Front leg         
// 10<-------- |--..
//     25-------90
//           <80>    Rear leg
//         ..--| -------->180
//           <53>
//              75---120
//           45---90                                      
 void FR(int posi) { if(posi != zzz) { posi = constrain(posi, 5, 95);   FRsvo.write(180-posi); } } // 10(Fstretch), 25-90(swing), 80(*)
 void FL(int posi) { if(posi != zzz) { posi = constrain(posi, 5, 95);   FLsvo.write(posi);     } } //             
 void RR(int posi) { if(posi != zzz) { posi = constrain(posi, 40, 180); RRsvo.write(180-posi); } } // 53(*), 45-75(swing1), 90-120(swing2), 180(Rstretch)
 void RL(int posi) { if(posi != zzz) { posi = constrain(posi, 40, 180); RLsvo.write(posi);     } } // *Square Position   
// ============================================
int pause(int pp) {
    SVOattach(1);  // SVO ON
    switch(pp) {
       case 0:  Serial.println("Base position:"); FR(70); FL(70); RR(110); RL(110); break;  // Base postion
       case 1:  Serial.println("Rear stretch:");  FR(90); FL(90); RR(180); RL(180); break;  // Rear ful stretch
       case 2:  Serial.println("Ful stretch:");   FR(10); FL(10); RR(180); RL(180); break;  // Ful stretch
       case 3:  Serial.println("Front stretch:"); FR(10); FL(10); RR(90);  RL(90);  break;  // Front stretch
       case 4:  Serial.println("Rear fuse:");     FR(90); FL(90); RR(120); RL(120); break;  // Rear fuse
       case 5:  Serial.println("Ful fuse:");      FR(25); FL(25); RR(120); RL(120); break;  // Ful fuse
       case 6:  Serial.println("Front fuse: ");   FR(25); FL(25); RR(75);  RL(75);  break;  // Front fuse 
       case 7:  Serial.println("Home postion:");  FR(80); FL(80); RR(53);  RL(53);          // 
                TBL.attach(9); dstep = 90; TBL.write(dstep); noTone(2);             break;  // Square Home position  
       case 8:  Serial.println("Right stretch:"); FR(10); FL(90); RR(90);  RL(180); break;  // Right stretch;
       case 9:  Serial.println("Left stretch:");  FR(90); FL(10); RR(180); RL(90);  break;  // Left stretch;
    }  delay(300); SVOattach(0); // SVO OFF
}
int go() {     tone(2, 200  + 200*stepp); stepp++; if(stepp > 5) { stepp = 0; } mogaki(stepp); } // normal steps
int goback() { tone(2, 2000 + 200*stepp); stepp--; if(stepp < 0) { stepp = 5; } mogaki(stepp); } // reverse steps
void mogaki(int para) { // walking sequence
   SVOattach(1);        // Serial.print("step:"); Serial.println(para);
   switch(para) {
     case 0: FL(90);     FR(25);         //  -   ^  (-)  ^
             RL(75);     RR(120);        // (-)  v   -   v
             break;
     case 1: FL(25);     FR(25);         // (^)  ^   ^  (^)
             RL(75-30);  RR(120);        //  -   v   -   v
             break;
     case 2: FL(25);     FR(90);         //  ^  (-)  ^   -
             RL(120-30); RR(120);        // (v)  v   v  (v)  
             break; 
           
     case 3: FL(25);     FR(90);         //  ^   -   ^  (-)
             RL(120);    RR(75);         //  v  (-)  v   - 
             break;     
     case 4: FL(25);     FR(25);         //  ^  (^) (^)  ^ 
             RL(120);    RR(75-30);      //  V   -   V   -  
             break;   
     case 5: FL(90);     FR(25);         // (-)  ^   -   ^
             RL(120);    RR(120-30);     //  V  (V) (V)  V   
             break;    
   }
}   

// ============================================
//  - Dance of the Reed Flutes data
//  - Lady Madonna data 
//  - The Imperial March data
//  - Theme from Close Encouters of the Third Kind
  int unitt = 40; // tempo
  long Ttime;     // 
// ============================================
void DanceoftheRead()  {  humming(xcountI, xtoneIa, xtoneIb, xtoneIc, xtoneId, xlegIa, xlegIb, xlegIc, xlegId,  8);   // Dance of the Reed Flutes data Intro
                          humming(xcountA, xtoneAa, xtoneAb, xtoneAc, xtoneAd, xlegAa, xlegAb, xlegAc, xlegAd, 16);   // Dance of the Reed Flutes data 1
                          humming(xcountB, xtoneBa, xtoneBb, xtoneBc, xtoneBd, xlegBa, xlegBb, xlegBc, xlegBd, 13); } // Dance of the Reed Flutes data 2
void LadyMaddonna()    {  humming(xcountC, xtoneCa, xtoneCb, xtoneCc, xtoneCd, xlegCa, xlegCb, xlegCc, xlegCd, 19);   // Lady Maddonna 19
                          humming(xcountD, xtoneDa, xtoneDb, xtoneDc, xtoneDd, xlegDa, xlegDb, xlegDc, xlegDd, 15); } // 14
void ImperialMarch1()  {  humming(count1,   tone1a,  tone1b,  tone1c,  tone1d,  leg1a,  leg1b,  leg1c,  leg1d,  9); } // The Imperial March data 1/3
void ImperialMarch2()  {  humming(count2,   tone2a,  tone2b,  tone2c,  tone2d,  leg2a,  leg2b,  leg2c,  leg2d,  9); } // The Imperial March data 2/3
void ImperialMarch3()  {  humming(count3,   tone3a,  tone3b,  tone3c,  tone3d,  leg3a,  leg3b,  leg3c,  leg3d, 10);   // The Imperial March data 3/3
                          humming(count4,   tone4a,  tone4b,  tone4c,  tone4d,  leg4a,  leg4b,  leg4c,  leg4d,  8);
                          humming(count5,   tone5a,  tone5b,  tone5c,  tone5d,  leg5a,  leg5b,  leg5c,  leg5d, 12); }
void CloseEncounters() {  humming(count6,   tone6a,  tone6b,  tone6c,  tone6d,  leg6a,  leg6b,  leg6c,  leg6d,  9); } // Theme from Close Encouters of the Third Kind               

void humming(const int *countn, const int *tonena, const int *tonenb, const int *tonenc, const int *tonend, 
             const int *legna,  const int *legnb,  const int *legnc,  const int *legnd, int len) {          
  digitalWrite(13, 0);
  for(int n = 0; n < len; n++)  { Ttime = millis();
     SVOattach(1);
     FR(pgm_read_word_near(legna + n)); 
     FL(pgm_read_word_near(legnb + n)); 
     RR(pgm_read_word_near(legnc + n)); 
     RL(pgm_read_word_near(legnd + n));
     switch(part) { // select voice part
       case 0: setTone(pgm_read_word_near(tonena + n));  break;
       case 1: setTone(pgm_read_word_near(tonenb + n));  break;
       case 2: setTone(pgm_read_word_near(tonenc + n));  break;
       case 3: setTone(pgm_read_word_near(tonend + n));  break;
     }      
     while(millis() - Ttime < unitt * pgm_read_word_near(countn + n)) { vivrato(); } //
  } setTone(0); digitalWrite(13, 0);
} 

// ============================================
//  Tone
// x    yyy          zzzz
// viv  octave 1-7   note 0-12
// ============================================
 #define o1 0x10   // short base note
 #define o2 0x20   // short base note
 #define o3 0x30   // 
 #define o4 0x40   //
 #define o5 0x50   //
 #define o6 0x60   //
 #define o7 0x70   //
 #define v1 0x10|0x80 // with vivrato
 #define v2 0x20|0x80 // with vivrato
 #define v3 0x30|0x80 // with vivrato
 #define v4 0x40|0x80 // with vivrato
 #define v5 0x50|0x80 // with vivrato
 #define v6 0x60|0x80 // with vivrato
 #define v7 0x70|0x80 // with vivrato
 #define zzz 0xff     // no action
 #define nT 0         // no tone
 #define C  1
 #define Cs 2
 #define D  3
 #define Ds 4
 #define E  5
 #define Ff 6
 #define Fs 7
 #define G  8
 #define Gs 9
 #define A  10
 #define As 11
 #define B  12
// ============================================
//  Dance of the Reed Flutes data
// ============================================
// <I>
const PROGMEM int xcountI[] = {    12,    12,    12,    12,    12,    12,    12,    12 }; // count[8]
const PROGMEM int xtoneIa[] = {  C|o1,  G|o1,  G|o1,  G|o1,  C|o1,  G|o1,  G|o1,  G|o1 }; // toneA
const PROGMEM int xtoneIb[] = {    nT,  G|o2,    nT,  G|o2,    nT,  G|o2,    nT,  G|o2 }; // toneB
const PROGMEM int xtoneIc[] = {    nT,    nT,    nT,    nT,    nT,    nT,    nT,    nT }; // toneC
const PROGMEM int xtoneId[] = {    nT,    nT,    nT,    nT,    nT,    nT,    nT,    nT }; // toneD
const PROGMEM int xlegIa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legA
const PROGMEM int xlegIb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legB
const PROGMEM int xlegIc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legC
const PROGMEM int xlegId[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // legD
// <A>                              |             |             |             |             |             |                           |      |
const PROGMEM int xcountA[] = {     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     3,     3,     3,     3,    12,    12  }; // count [16]
const PROGMEM int xtoneAa[] = {  C|o6,  B|o5,  C|o6,  B|o5,  C|o6,    nT,  B|o5,    nT,  D|o6,    nT,  C|o6,  E|o6,  G|o6,  C|o7,  E|v7,   zzz  }; // toneA
const PROGMEM int xtoneAb[] = {  E|o4,  D|o4,  E|o4,  D|o4,  E|o4,    nT,  D|o4,    nT, Ff|o4,    nT,  E|o4,  G|o4,  C|o4,  E|o4,  G|v4,   zzz  }; // toneB
const PROGMEM int xtoneAc[] = {    nT,   zzz,  B|o2,   zzz,    nT,   zzz,  C|o2,   zzz,    nT,   zzz,  D|o2,   zzz,   zzz,   zzz,    nT,  E|o2  }; // toneC
const PROGMEM int xtoneAd[] = {  B|o1,   zzz,  B|o1,   zzz,  C|o1,   zzz,  C|o1,   zzz,  D|o1,   zzz,  D|o1,   zzz,   zzz,   zzz,  E|o1,  E|o1  }; // toneD
const PROGMEM int xlegAa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legA
const PROGMEM int xlegAb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legB
const PROGMEM int xlegAc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legC
const PROGMEM int xlegAd[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz  }; // legD
// <B>                              |             |             |             |             |      |             |      |
const PROGMEM int xcountB[] = {     6,     6,     6,     6,     6,     6,     6,     6,    12,     6,     6,    12,    12   }; // count [13]
const PROGMEM int xtoneBa[] = { Ff|o7,  E|o7, Ff|o7,  E|o7,  D|o7,  C|o7,  G|o6,  E|o6,  C|o6,   zzz,  C|o7,  B|v6,   zzz   }; // toneA
const PROGMEM int xtoneBb[] = {  A|o5,  G|o5,  A|o5,  G|o5, Ff|o5,  E|o5,  C|o5,  E|o5, Gs|o5,   zzz,   zzz, Ff|v5,   zzz   }; // toneB
const PROGMEM int xtoneBc[] = {    nT,   zzz, Ff|o2,   zzz,    nT,   zzz,  G|o2,   zzz,    nT,  G|o2,   zzz,    nT,  G|o2   }; // toneC
const PROGMEM int xtoneBd[] = { Ff|o1,   zzz, Ff|o1,   zzz,  G|o1,   zzz,  G|o1,   zzz,  G|o1,  G|o1,   zzz,  G|o1,  G|o1   }; // toneD
const PROGMEM int xlegBa[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legA
const PROGMEM int xlegBb[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legB
const PROGMEM int xlegBc[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legC
const PROGMEM int xlegBd[]  = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz   }; // legD
// ============================================
//  Lady Madonna data 
// ============================================
// <C>                                    <|             |             |             |       >    <|             |                           |             |       > 
const PROGMEM int xcountC[] = {     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     3,     4,     3,     4,     7,     7,     7,     5 }; // count [16x6]
const PROGMEM int xtoneCa[] = {   zzz, Cs|o5, Cs|o5,   zzz,  B|o4,  B|o4,  A|o4,   zzz,   zzz, Cs|o5, Cs|o5,  B|o4,    nT,  C|o4,  A|o4,   zzz,   zzz,   zzz,   zzz }; // toneA
const PROGMEM int xtoneCb[] = {  D|o1,  B|o1,  A|o2, Cs|o1, Cs|o2,  D|o2,  D|o1,  D|o1,  D|o1,  B|o1,  A|o2, Cs|o1,   zzz, Cs|o2,   zzz,  D|o2,  D|o1,  D|o1,  D|o1 }; // toneB
const PROGMEM int xtoneCc[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // toneC
const PROGMEM int xtoneCd[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz }; // toneD
const PROGMEM int xlegCa[]  = {    30,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,   zzz,    60,    30,   zzz }; // legA
const PROGMEM int xlegCb[]  = {    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,    60,   zzz,    30,   zzz,   zzz,   zzz }; // legB
const PROGMEM int xlegCc[]  = {    30,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,   zzz,   zzz,    60,    30,   zzz,   zzz }; // legC
const PROGMEM int xlegCd[]  = {    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,    30,   zzz,   zzz,    60,   zzz,    30,   zzz,   zzz,   zzz,    60,    30 }; // legD  
//                                 L      W      R      W      L      W      R      W      L      W      R      W             L             W      R      W      L  
// <D>                             <|      |      |      |      |      |      |      |             |      |      |             |>
const PROGMEM int xcountD[] = {     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,     7,   35 }; // count [13x6]
const PROGMEM int xtoneDa[] = { Cs|o6, Cs|o6,  E|o6, Cs|o6, Fs|o6,  E|o6, Cs|o6,  A|o5,   zzz,  G|o5,  B|o5,  A|o5,   zzz,  A|v6,  zzz }; // toneA
const PROGMEM int xtoneDb[] = {  B|o1,  A|o2, Cs|o1, Cs|o2,  D|o2,  D|o1,  E|o2,  E|o1, Ff|o1, Ff|o2, Cs|o1,  G|o2,  A|o2,  E|v5,  zzz }; // toneB
const PROGMEM int xtoneDc[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  E|v7,  zzz }; // toneC
const PROGMEM int xtoneDd[] = {  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,    nT,  A|o4,  A|v4,  zzz }; // toneD
const PROGMEM int xlegDa[]  = {    10,   zzz,   zzz,   zzz,    58,   zzz,   zzz,   zzz,    20,   zzz,    48,   zzz,    58,   zzz,    0 }; // legA
const PROGMEM int xlegDb[]  = {    10,   zzz,   zzz,   zzz,    58,   zzz,   zzz,   zzz,   zzz,   zzz,    20,   zzz,    58,   zzz,    0 }; // legB
const PROGMEM int xlegDc[]  = {    58,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,   zzz,   zzz,    48,   zzz,    58,   zzz,    0 }; // legC
const PROGMEM int xlegDd[]  = {    58,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,    48,   zzz,    20,   zzz,    58,   zzz,    0 }; // legD  
// ============================================
//  The Imperial March data
// ============================================
// <1>                             |+1    |2     |3     |4            |5     |6           ||7,8
const PROGMEM int count1[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone1a[] = {  A|o3,  A|o3,  A|o3, Ff|o3,  C|o4,  A|o3, Ff|o3,  C|o4,  A|v3 }; // toneA
const PROGMEM int tone1b[] = {  E|o2,  E|o2,  E|o2,   zzz,   zzz,  E|o2,   zzz,   zzz,  E|v2 }; // toneB
const PROGMEM int tone1c[] = {  B|o1,  B|o1,  B|o1,  B|o2,   zzz,  B|o1,  B|o2,   zzz,  B|v1 }; // toneC
const PROGMEM int tone1d[] = {  A|o1,   zzz,   zzz, Gs|o2,   zzz,  A|o1, Gs|o2,   zzz,  E|v1 }; // toneD
const PROGMEM int leg1a[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legA  0:Straight >>>> 62:Angle
const PROGMEM int leg1b[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legB  i.e. 35|p3
const PROGMEM int leg1c[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legC
const PROGMEM int leg1d[]  = {    60,   zzz,    20,   zzz,   zzz,    60,    20,   zzz,    60 }; // legD
// <2>                             |+1    |2     |3     |4            |5     |6           ||7,8
const PROGMEM int count2[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone2a[] = {  E|o4,  E|o4,  E|o4, Ff|o4,  C|o4, Gs|o3, Ff|o3,  C|o4,  A|v3 }; // toneA
const PROGMEM int tone2b[] = {  A|o2,  A|o2,  A|o2, Gs|o1,   zzz,  A|o2, Gs|o1,   zzz,  C|v2 }; // toneB
const PROGMEM int tone2c[] = {  C|o1,  C|o1,  C|o1,  C|o2,   zzz,  C|o1,  C|o2,   zzz,  E|v1 }; // toneC
const PROGMEM int tone2d[] = {  A|o1,   zzz,   zzz, Gs|o2,   zzz,  A|o1, Gs|o2,   zzz,  A|v1 }; // toneD
const PROGMEM int leg2a[]  = {    60,    20,   60,    20,   zzz,    60,    20,   zzz,    60 }; // legA  0:Straight >>>> 62:Angle
const PROGMEM int leg2b[]  = {    20,    60,   20,    60,   zzz,    60,    20,   zzz,    60 }; // legB  i.e. 35|p3
const PROGMEM int leg2c[]  = {    60,    20,   60,    20,   zzz,    20,    60,   zzz,    60 }; // legC
const PROGMEM int leg2d[]  = {    20,    60,   20,    60,   zzz,    20,    60,   zzz,    60 }; // legD
// <3>                             |+1    |2            |3     |4            |+1                  |2
const PROGMEM int count3[] = {    16,    13,     3,    16,     8,     8,     4,     4,     8,     8 }; // count
const PROGMEM int tone3a[] = {  A|o4,  A|o3,  A|o3,  A|o4, Gs|o4,  G|o4, Fs|o4, Ff|o4, Fs|o4,    nT }; // toneA
const PROGMEM int tone3b[] = {  C|o2,  C|o2,   zzz,  C|o2,  C|o2,   zzz, Ds|o2,   zzz,   zzz,    nT }; // toneB  c  d
const PROGMEM int tone3c[] = {  E|o1,  E|o1,   zzz,  E|o1,  E|o1,   zzz,  A|o1,   zzz,   zzz,    nT }; // toneC  a  b
const PROGMEM int tone3d[] = {  A|o1,   zzz,   zzz,   zzz,   zzz,   zzz, Fs|o1,   zzz,   zzz,    nT }; // toneD
const PROGMEM int leg3a[]  = {    62,   zzz,   zzz,     0,   zzz,    50,   zzz,   zzz,   zzz,    15 }; // legA NE:abcd 
const PROGMEM int leg3b[]  = {   zzz,    15,   zzz,   zzz,    50,   zzz,    62,   zzz,   zzz,   zzz }; // legB NW:bdac
const PROGMEM int leg3c[]  = {   zzz,    15,   zzz,   zzz,    50,   zzz,     0,   zzz,   zzz,   zzz }; // legC SW:dcba   
const PROGMEM int leg3d[]  = {     0,   zzz,   zzz,    62,   zzz,   zzz,   zzz,   zzz,   zzz,    15 }; // legD SE:cadb
// <4>                                    |3     |4            |+1                  |2     
const PROGMEM int count4[] = {     8,    16,     8,     8,     4,     4,     8,     8 }; // count
const PROGMEM int tone4a[] = { As|o3, Ds|o4,  D|o4, Cs|o4,  C|o4,  B|o3,  C|o4,    nT }; // toneA
const PROGMEM int tone4b[] = {   zzz,  A|o2,  A|o2,   zzz,  E|o2,   zzz,   zzz,   zzz }; // toneB
const PROGMEM int tone4c[] = {   zzz, Ds|o1, Ds|o1,   zzz,  A|o1,   zzz,   zzz,   zzz }; // toneC
const PROGMEM int tone4d[] = {   zzz,  A|o1,  A|o1,   zzz,  C|o2,   zzz,   zzz,   zzz }; // toneD
const PROGMEM int leg4a[]  = {   zzz,   zzz,    50,   zzz,     0,   zzz,   zzz,   zzz }; // legA
const PROGMEM int leg4b[]  = {   zzz,     0,   zzz,    50,   zzz,   zzz,   zzz,    15 }; // legB
const PROGMEM int leg4c[]  = {   zzz,    62,   zzz,   zzz,   zzz,   zzz,   zzz,    15 }; // legC
const PROGMEM int leg4d[]  = {   zzz,   zzz,    50,   zzz,    62,   zzz,   zzz,   zzz }; // legD
// <5>                                    |3     |4                   |+1           |2                   |3     |4
const PROGMEM int count5[] = {     8,    16,     8,     5,     3,     8,     8,     8,     5,     3,    16,    16 }; // count
const PROGMEM int tone5a[] = { Ff|o3, Gs|o3, Ff|o3,   zzz,  C|o4,  A|o3,   zzz, Ff|o3,   zzz,  C|o4,  A|v3,   zzz }; // toneA
const PROGMEM int tone5b[] = {   zzz,   zzz,   zzz,   zzz,   zzz,  A|o1,   zzz,   zzz,   zzz,   zzz,  E|v2,   zzz }; // toneB
const PROGMEM int tone5c[] = {   zzz,  C|o1,  C|o1,   zzz,   zzz,  E|o2,   zzz,   zzz,   zzz,   zzz,  C|v1,   zzz }; // toneC
const PROGMEM int tone5d[] = {   zzz, Gs|o2, Ff|o2,   zzz,   zzz,  C|o1,   zzz,   zzz,   zzz,   zzz,  A|v1,   zzz }; // toneD
const PROGMEM int leg5a[]  = {   zzz,    62,   zzz,   zzz,   zzz,    60,    50,    60,    50,   zzz,    60,     0 }; // legA
const PROGMEM int leg5b[]  = {   zzz,   zzz,    50,   zzz,   zzz,    50,    60,    50,    60,   zzz,    50,     0 }; // legB
const PROGMEM int leg5c[]  = {   zzz,   zzz,    50,   zzz,   zzz,    50,    30,    50,    30,   zzz,    50,     0 }; // legC
const PROGMEM int leg5d[]  = {   zzz,     0,   zzz,    50,   zzz,    30,    50,    30,    50,   zzz,    30,     0 }; // legD
// ============================================
//  Theme from Close Encouters of the Third Kind
// ============================================
// <6>                             |      |      |      |      |      |      |      |      |    
const PROGMEM int count6[] = {    16,    16,    16,    16,    16,    16,    16,    16,    64  }; // count
const PROGMEM int tone6a[] = {  A|o6,  B|o6,  G|o6,  G|o5,  D|o5,   zzz,   zzz,   zzz,  D|v5  }; // toneA
const PROGMEM int tone6b[] = {   zzz,   zzz,   zzz,   zzz,  A|o4,  B|o4,  G|o4,  G|o3,  D|v3  }; // toneB
const PROGMEM int tone6c[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  A|v3  }; // toneC
const PROGMEM int tone6d[] = {   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  D|v2  }; // toneD
const PROGMEM int leg6a[]  = {    10,   zzz,   zzz,   zzz,    90,   zzz,   zzz,   zzz,    10  }; // legA
const PROGMEM int leg6b[]  = {    90,   zzz,   zzz,   zzz,    10,   zzz,   zzz,   zzz,    10  }; // legB
const PROGMEM int leg6c[]  = {    90,   zzz,   zzz,   zzz,   180,   zzz,   zzz,   zzz,   180  }; // legC
const PROGMEM int leg6d[]  = {   180,   zzz,   zzz,   zzz,    90,   zzz,   zzz,   zzz,   180  }; // legD

// ============================================
//  Sub Functions
// ============================================
// ============================================
//  Servo Enable Disable
// ============================================
void SVOattach(int tt) { // Servo attach, detach
  if(tt) {  FRsvo.attach(5);  FLsvo.attach(6);   // Front Right/Left leg
            RRsvo.attach(7);  RLsvo.attach(8);   // Rear  Right/Left leg
  } else {  FRsvo.detach();   FLsvo.detach();    // Front RightLeft leg
            RRsvo.detach();   RLsvo.detach();  } // Rear  Right/Left leg      
}
// ============================================
//  Ultrasonic Distance Meter
//  0: short 1:middle 2:long
// ============================================
void ultras() { // check distance to object
  int dist = ultrasonic.Ranging(CM); // Serial.print(dist); Serial.println(" cm" );
  if(dist <= 13) { zone = 0; } else if(dist > 13 && dist < 30) { zone = 1; } else { zone = 2; }    
}
// ============================================
//  Tone Control
//    12note + octave, vivrato, short base note
// x    yyy          zzzz
// viv  octave 1-7   note 0-12
   long itime1s, itime2s;      // system timers
   int vcnt, octo;             // base counter
   long frq;                   // tone frequency   
   int  viv = 0;               // vivrato switch
   boolean tglv = true;        // vivrato tgl
   float vvv;                  // vivrato depth
// ============================================
long oto[]  = {  // divide 0 to 7 times(3bit)
   0,       // 0  notone
   2093*2,  // 1  C
   2217*2,  // 2  Cs
   2349*2,  // 3  D
   2489*2,  // 4  Ds
   2637*2,  // 5  E
   2794*2,  // 6  F
   2960*2,  // 7  Fs
   3136*2,  // 8  G
   3322*2,  // 9  Gs
   3520*2,  // 10 A
   3729*2,  // 11 As
   3951*2   // 12 B  5bit(0-16)
};
void setTone(int note) { if(note != zzz) { noTone(2); frq = frqcalc(note); vcnt = 0; digitalWrite(13, 1); } }
long frqcalc(int dd) { // decode from ddd to freqeucy and octave
  long frqq = oto[min(dd & 0x0f, 12)];                                   // frequency
  octo = 7 - ((dd & 0x70) >> 4);                                         // octave
  if(octo < 7) { for (int k = 0; k < octo; k++) { frqq /= 2; } tone(2, frqq); } else { frqq = 0; }
  viv = bitRead(dd, 7);  vvv = frqq * 0.006;  return frqq;
}
void vivrato() { //
  if(millis() - itime1s > 20) { itime1s = millis(); 
     vcnt++; if(vcnt > 6 && !viv && octo > 4) { noTone(2); }             // short tone for base line  
     if(vcnt > 5 && vcnt < 7) { digitalWrite(13, 0); }                   // LED off @count 6
  }
  if(millis() - itime2s > 80 && viv && frq) { itime2s = millis();        // vivrato
     if(tglv) { tone(2, frq - vvv); } else { tone(2, frq); }             // sound vibration
     digitalWrite(13, tglv); tglv = !tglv;                               // LED flashing     
  }        
}
// ============================================
//  IR Command Receiver
//  --start-------    --"0"------    --"1"----------    --stop------
//    9ms     4ms     600us 600us    600us  1600us      600us          total 50 to 80ms 
// ============================================
char IRdrcv() {
  long TStime; long sTStime; int lap[40]; int n = 0; long ddd = 0; char moji = 0;
  if(!digitalRead(12)) {
    sTStime = millis();                                                        // total length check timer
      TStime = micros(); while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'a'; } 
      if(micros() - TStime < 4000) return 'b';                                 // start "L" 9ms   
      while( digitalRead(12)) { if(millis() - sTStime > 100) return 'c'; }     // start space "H" 4ms 
    for(int n = 0; n < 32; n++) {
      while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'd'; }     // data carry
      TStime = micros(); while( digitalRead(12)) { if(millis() - sTStime > 100) return 'e'; } 
      lap[n] = micros() - TStime;                                              // data space check   
    } while(!digitalRead(12)) { if(millis() - sTStime > 100) return 'f'; }     // stop bit check
    for(int n = 0; n < 32; n++) { if(lap[n] > 1000) { bitSet(ddd, 31 - n); } } // Serial.print("data:"); Serial.println(ddd, HEX); 
    switch(ddd) {                                                              // decode
       case 0xFFA25D:  moji = '1'; break;    
       case 0xFF629D:  moji = '2'; break;
       case 0xFFE21D:  moji = '3'; break;
       case 0xFF22DD:  moji = '4'; break;
       case 0xFF02FD:  moji = '5'; break;
       case 0xFFC23D:  moji = '6'; break;
       case 0xFFE01F:  moji = '7'; break; 
       case 0xFFA857:  moji = '8'; break;
       case 0xFF906F:  moji = '9'; break;
       case 0xFF9867:  moji = '0'; break;
       case 0xFF6897:  moji = '*'; break;
       case 0xFFB04F:  moji = '#'; break; 
       case 0xFF18E7:  moji = 'U'; break; // "^"
       case 0xFF4AB5:  moji = 'D'; break; // "v"
       case 0xFF10EF:  moji = 'L'; break; // "<-"
       case 0xFF5AA5:  moji = 'R'; break; // "->"
       case 0xFF38C7:  moji = 'K'; break; // "ok"
    }  Serial.print("["); Serial.print(moji); Serial.print("]");
  } return moji;  
}

Software

Arduino
No preview (download only).

Credits

Masahiro Mizuno

Masahiro Mizuno

20 projects • 32 followers
Chief Prototypist. 20+ years R&D experience in wide range of technology.

Comments