// ============================================
// 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;
}
Comments