Masahiro Mizuno
Published © GPL3+

4-Legged Walking Robot #2

Arduino Nano or Obniz controlled robot design information.

IntermediateFull instructions provided10 hours2,322
4-Legged Walking Robot #2

Things used in this project

Hardware components

Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
Arduino Nano R3
Arduino Nano R3
×1
MG90S Servo
×1
IR Receiver
×1
Microchip MCP73831
×1
Makerchip TC1240
×1

Story

Read more

Custom parts and enclosures

4-legged walking robot body gerber data

Schematics

4-legged walking robot schematic

Code

Control Software

Arduino
// ============================================
//  4-Legged walking robot
//  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 <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
// ============================================ 
   long itime, itime2, itime3, itime4; // event timer  
   boolean tgll = true;                // led tggle
   int stepp = 5;                      // walking step
   boolean autom = true;               // IR controller/auto mode
// ============================================
//  SETUP
  int dstep = 90; int ddir = 1;
// ============================================
void setup() {
  Serial.begin(9600);             // Serial Monitor  
  
  pinMode(10, OUTPUT);            // LED
  pinMode(13, OUTPUT);            // on board LED
  pinMode(12, INPUT_PULLUP);      // IR
  pinMode(A1, INPUT);

  FRsvo.attach(5);                // FR leg
  FLsvo.attach(6);                // FL leg
  RRsvo.attach(7);                // RR leg
  RLsvo.attach(8);                // RL leg
  TBL.attach(9);                  // TABLE control
  FR(70); FL(70); RR(110); RL(110);  // home position
  delay(2000);     
}
// ============================================
//  LOOP
  int inter = 1000; 
  int mode, Omode;
  int Rstate, Rtim;
// ============================================
void loop() {
  IRreceiver(); digitalWrite(10, !autom);                                  // IR controller command decode
  if(autom) {                                                              // AUTO mode
     if(millis() - itime2 > 200) { itime2 = millis();                      // distance sensor
        ultras(); if(mode == 1) { go(0); }                                 // walk 
        if(Omode != mode) { 
           if(mode == 0)      { FR(65*tgll); FL(65*!tgll); RR(100); RL(100); noTone(2); } // short distance
           else if(mode == 2) { FR(65); FL(65); RR(100); RL(100);            noTone(2); } // long distance
           Omode = mode;
        }  
     } 
     tablecontrol();
  }
  if(millis() - itime > inter) { itime = millis(); tgll = !tgll;           // table 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
  }      
}
void ultras() {
  int dist = ultrasonic.Ranging(CM);                                       // Serial.print(dist); Serial.println(" cm" );
  if(dist <= 13) { mode = 0; } else if(dist > 13 && dist < 30) { mode = 1; } else { mode = 2; }    
}
// ============================================
//  TURNTABLE control
// ============================================
void tablecontrol() {
   if(inter < 1000) { // table mode 
     if(millis() - itime3 > 400 && mode == 2) { itime3 = millis();  // table rotation
        if(ddir) { dstep += 1; if(dstep > 180) { ddir = 0; } else { TBL.write(dstep); } }
        else     { dstep -= 1; if(dstep < 0)   { ddir = 1; } else { TBL.write(dstep); } }   
     }   
     if(millis() - itime4 > Rtim) { itime4 = millis();              // table random pose
        Rtim = random(5000*2, 12000*2); ddir = !ddir;
        Rstate++; if(Rstate > 7) { Rstate = 0; }
        switch(Rstate) {
             case 0: FR(70); FL(70); RR(110); RL(110); break;  // Home
             case 1: FR(0);  FL(90); RR(90);  RL(180); break;  // Right stretch
             case 2: FR(70); FL(70); RR(110); RL(110); break;  // Home
             case 3: FR(90); FL(90); RR(180); RL(180); break;  // Rear stretch!! 
             case 4: FR(70); FL(70); RR(110); RL(110); break;  // Home             
             case 5: FR(90); FL(0);  RR(180); RL(90);  break;  // Left stretch
             case 6: FR(70); FL(70); RR(110); RL(110); break;  // Home
             case 7: FR(0);  FL(0);  RR(180); RL(180); 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; // 1 light/charge sensor test
       case '2':  Serial.print("ultrasonic distance measurement(cm): ");
                  Serial.println(ultrasonic.Ranging(CM));                             break; // 2 ultrasonic test
       case '3':  Serial.println("tone"); tone(2, 440); delay(200); noTone(2);    break; // 3 buzz test
       case '4':  Serial.println("Rear stretch:");  FR(90); FL(90); RR(180); RL(180); break;  // Rear ful stretch
       case '5':  Serial.println("Ful stretch:");   FR(0);  FL(0);  RR(180); RL(180); break;  // Ful stretch
       case '6':  Serial.println("Front stretch:"); FR(0);  FL(0);  RR(90);  RL(90);  break;  // Front stretch
       case '7':  Serial.println("Rear fuse:");     FR(90); FL(90); RR(120); RL(120); break;  // Rear fuse
       case '8':  Serial.println("Ful fuse:");      FR(25); FL(25); RR(120); RL(120); break;  // Ful fuse
       case '9':  Serial.println("Front fuse: ");   FR(25); FL(25); RR(75);  RL(75);  break;  // Front fuse 
       case '0':  Serial.println("Home postion:");  FR(80); FL(80); RR(53);  RL(53);  noTone(2); break;   // Square Home position  
       case '*':       go(3);            break;   // * small steps
       case '#':                         break;   // #
       case 'U':       go(0);            break;   // UP    forward steps
       case 'D':       goback();         break;   // DOWN  reverse steps
       case 'L':       go(1);            break;   // LEFT  left direction
       case 'R':       go(2);            break;   // RIGTH right direction
       case 'K':  Serial.print("auto mode:");  autom = !autom;   
                  Serial.println(autom); break;   // OK    auto or manual
     }
   }    
}
// ============================================
//  IR rcv
// f:38kHz unit:high = 9us/low = 17us (26us) 
// (0)600/26, (1)1200/26, (2)2500/26
// || 342 ||``170`,,``||22||``22``,,,||22||````63````,,,||22||```````
//  --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; int lgth; long ddd = 0; char moji = 0;
  if(!digitalRead(12)) {
    sTStime = millis(); // total length check
      TStime = micros(); while(!digitalRead(12)) { if(millis() - sTStime > 100) return ddd; } 
      if(micros() - TStime < 4000) return ddd;                                 // start "L" 9ms   
      while( digitalRead(12)) { if(millis() - sTStime > 100) return ddd; }     // start space "H" 4ms 
    for(int n = 0; n < 32; n++) {
      while(!digitalRead(12)) { if(millis() - sTStime > 100) return 0; }       // data carry
      TStime = micros(); while( digitalRead(12)) { if(millis() - sTStime > 100) return ddd; } 
      lap[n] = micros() - TStime;                                              // data space   
    } while(!digitalRead(12)) { if(millis() - sTStime > 100) return 0; }       // stop bit   
    for(int n = 0; n < 32; n++) { if(lap[n] > 1000) { bitSet(ddd, 31 - n); } } //Serial.print("data:"); Serial.println(ddd, HEX); 
    switch(ddd) {
       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;  
}

// ============================================
//  0<----- | ----->180
//    25    90
//        75---120
//      45--90
   void FR(int posi) { FRsvo.write(180-posi); } // 0, 25, 90
   void FL(int posi) { FLsvo.write(posi);     } // 0, 25, 90                    80 Home
   void RR(int posi) { RRsvo.write(180-posi); } // 75, 120, 75-30, 120-30, 180
   void RL(int posi) { RLsvo.write(posi);     } // 75, 120, 75-30, 120-30, 180  53 Home                                        
// ============================================
int go(int dir) {  // 1:left 2:rite
      tone(2, 200 + 200*stepp);
      stepp += 1; if(stepp > 5) { stepp = 0; }
      if(!dir) mogaki(stepp,0,0);               // normal steps
      else if(dir == 1) mogaki(stepp, 0, 1);    // right direction
      else if(dir == 2) mogaki(stepp, 1, 0);    // left direction
      else if(dir == 3) mogaki(stepp, 1, 1);    // small steps
}   
int goback() {
      tone(2, 2000 + 200*stepp);
      stepp -= 1; if(stepp < 0) { stepp = 5; } 
      mogaki(stepp,1,1); 
}
void mogaki(int para, int lt, int rt) { 
   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;    
   }
}   

Credits

Masahiro Mizuno

Masahiro Mizuno

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

Comments