Masahiro Mizuno
Published © GPL3+

Voice Controlled "SHAKEYs"

The robots will sing and dance with voice command.

IntermediateShowcase (no instructions)5 hours848
Voice Controlled "SHAKEYs"

Things used in this project

Hardware components

Seeed Studio Grove Speech recognizer
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

UP3D mini
FreeCAD

Story

Read more

Custom parts and enclosures

SHAKEY gerber

Voice Controlled IR gerber

Schematics

SHAKEY

Voice Controlled IR

Code

SHAKEY code

Arduino
para.h
// ============================================
//  Tone
// ============================================
#define o1 0x10 // short base note 1
#define o2 0x20 // short base note 2
#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 F  6
#define Fs 7
#define G  8
#define Gs 9
#define A  10
#define As 11
#define B  12
// ============================================
//  Tone
     boolean tglv = true;         // vivrato tgl
     int   viv = 0;               // vivrato on/off switch
     float vvv;                   // vivrato depth
     int freq;                    // sound frequency
     int octo;                    // oct control (base short note)
     boolean stgl = true;         // face swing tgl
     int unitt = 40;              // tempo    
// ============================================
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)
};

Music.ino
// ============================================
//  Dance of the Reed Flutes data "a(ov1) b(ov2)(short)    c(ov3) d(ov4) e(ov5) f(ov6) g(ov7)"
// ============================================
// <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
// <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,  F|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
// <B>                              |             |             |             |             |      |             |      |
const PROGMEM int xcountB[] = {     6,     6,     6,     6,     6,     6,     6,     6,    12,     6,     6,    12,    12   }; // count [13]
const PROGMEM int xtoneBa[] = {  F|o7,  E|o7,  F|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,  F|o5,  E|o5,  C|o5,  E|o5, Gs|o5,   zzz,   zzz,  F|v5,   zzz   }; // toneB
const PROGMEM int xtoneBc[] = {    nT,   zzz,  F|o2,   zzz,    nT,   zzz,  G|o2,   zzz,    nT,  G|o2,   zzz,    nT,  G|o2   }; // toneC
const PROGMEM int xtoneBd[] = {  F|o1,   zzz,  F|o1,   zzz,  G|o1,   zzz,  G|o1,   zzz,  G|o1,  G|o1,   zzz,  G|o1,  G|o1   }; // toneD
void DanceoftheRead()  { humming(xcountI, xtoneIa, xtoneIb, xtoneIc, xtoneId,  8);   // Dance of the Reed Flutes data Intro
                         humming(xcountA, xtoneAa, xtoneAb, xtoneAc, xtoneAd, 16);   // Dance of the Reed Flutes data 1
                         humming(xcountB, xtoneBa, xtoneBb, xtoneBc, xtoneBd, 13); } // Dance of the Reed Flutes data 2
// ============================================
//  Lady Madonna data "a(ov1) b(ov2)(short)    c(ov3) d(ov4) e(ov5) f(ov6) g(ov7)"
// ============================================
// <C>           
const PROGMEM int xcountC[] = {     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     3,     3,     3,     3,    6,    6,    6,    6  }; // count [16x6]
const PROGMEM int xtoneCa[] = { 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[] = {  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[] = {    nT,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  zzz,  zzz,  zzz,  zzz  }; // toneC
const PROGMEM int xtoneCd[] = {    nT,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  zzz,  zzz,  zzz,  zzz  }; // toneD
// <D>
const PROGMEM int xcountD[] = {     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,     6,    36  }; // 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  }; // toneA
const PROGMEM int xtoneDb[] = {  B|o1,  A|o2, Cs|o1, Cs|o2,  D|o2,  D|o1,  E|o2,  E|o1,  F|o1,  F|o2, Cs|o1,  G|o2,  A|o2,  E|v5  }; // toneB
const PROGMEM int xtoneDc[] = {    nT,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  E|v7  }; // 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  }; // toneD
void LadyMaddonna()    { humming(xcountC, xtoneCa, xtoneCb, xtoneCc, xtoneCd, 18);   // Lady Maddonna
                         humming(xcountD, xtoneDa, xtoneDb, xtoneDc, xtoneDd, 14); }    
// ============================================
//  The Imperial March data "a(ov1) b(ov2)(short)    c(ov3) d(ov4) e(ov5) f(ov6) g(ov7)"
// ============================================
// <1>                             |      |      |      |             |      |            ||
const PROGMEM int count1[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone1a[] = {  A|o3,  A|o3,  A|o3,  F|o3,  C|o4,  A|o3,  F|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
// <2>                             |      |      |      |             |      |            ||
const PROGMEM int count2[] = {    16,    16,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone2a[] = {  E|o4,  E|o4,  E|o4,  F|o4,  C|o4, Gs|o3,  F|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,    nT,    nT, Gs|o2,    nT,  A|o1, Gs|o2,    nT,  A|v1 }; // toneD
// <3>                             |      |             |      |             |                    |
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,  F|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
const PROGMEM int tone3c[] = {  E|o1,  E|o1,   zzz,  E|o1,  E|o1,   zzz,  A|o1,   zzz,   zzz,    nT }; // toneC
const PROGMEM int tone3d[] = {  A|o1,   zzz,   zzz,   zzz,   zzz,   zzz, Fs|o1,   zzz,   zzz,    nT }; // toneD
// <4>                                    |      |             |                    |             |
const PROGMEM int count4[] = {     8,    16,     8,     8,     4,     4,     8,     8,     8,     8 }; // count
const PROGMEM int tone4a[] = { As|o3, Ds|o4,  D|o4, Cs|o4,  C|o4,  B|o3,  C|o4,    nT, Fs|o4,    nT }; // toneA
const PROGMEM int tone4b[] = {    nT,  A|o2,  A|o2,   zzz,  E|o2,   zzz,   zzz,   zzz,   zzz,    nT }; // toneB
const PROGMEM int tone4c[] = {    nT, Ds|o1, Ds|o1,   zzz,  A|o1,   zzz,   zzz,   zzz,   zzz,    nT }; // toneC
const PROGMEM int tone4d[] = {    nT,  A|o1,  A|o1,   zzz,  C|o2,   zzz,   zzz,   zzz,   zzz,    nT }; // toneD
// <5>                                    |      |             |      |            ||
const PROGMEM int count5[] = {     8,    16,    13,     3,    16,    13,     3,    32 }; // count
const PROGMEM int tone5a[] = {  F|o3, Gs|o3,  F|o3,  C|o4,  A|o3,  F|o3,  C|o4,  A|v3 }; // toneA
const PROGMEM int tone5b[] = {    nT,   zzz,   zzz,   zzz,  A|o1,   zzz,   zzz,  E|v2 }; // toneB
const PROGMEM int tone5c[] = {    nT,  C|o1,  C|o1,   zzz,  E|o2,   zzz,   zzz,  C|v1 }; // toneC
const PROGMEM int tone5d[] = {    nT, Gs|o2,  F|o2,   zzz,  C|o1,   zzz,   zzz,  A|v1 }; // toneD
void ImperialMarch1()  { humming(count1,   tone1a,  tone1b,  tone1c,  tone1d,  9); } // The Imperial March data 1/3
void ImperialMarch2()  { humming(count2,   tone2a,  tone2b,  tone2c,  tone2d,  9); } // The Imperial March data 2/3
void ImperialMarch3()  { humming(count3,   tone3a,  tone3b,  tone3c,  tone3d, 10);   // The Imperial March data 3/3
                         humming(count4,   tone4a,  tone4b,  tone4c,  tone4d,  8);
                         humming(count5,   tone5a,  tone5b,  tone5c,  tone5d,  8); }
// ============================================
//  Theme from Close Encouters of the Third Kind  "a(ov1) b(ov2)(short)    c(ov3) d(ov4) e(ov5) f(ov6) g(ov7)"
// ============================================
// <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[] = {    nT,   zzz,   zzz,   zzz,  A|o4,  B|o4,  G|o4,  G|o3,  D|v3  }; // toneB
const PROGMEM int tone6c[] = {    nT,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  A|v3  }; // toneC
const PROGMEM int tone6d[] = {    nT,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,   zzz,  D|v2  }; // toneD
void CloseEncounters() { humming(count6,   tone6a,  tone6b,  tone6c,  tone6d,  9); } // Theme from Close Encounters of the Third Kind               
// ============================================
//  play music (viv / oct 2, 1, 0 / note 3, 2, 1, 0 )
    long Ttime;                  //  
// ============================================
void humming(const int *countn, const int *tonena, const int *tonenb, const int *tonenc, const int *tonend, int len) {  
  for(int n = 0; n < len; n++)  { Ttime = millis();
       if(part == 0)      { stone(pgm_read_word_near(tonena + n)); }  // part0
       else if(part == 1) { stone(pgm_read_word_near(tonenb + n)); }  // part1
       else if(part == 2) { stone(pgm_read_word_near(tonenc + n)); }  // part2
       else {               stone(pgm_read_word_near(tonend + n)); }  // part3       
       if(!viv) { magOnwT(0, 50, stgl); stgl = !stgl; }  // swing tgl  
       while(millis() - Ttime < unitt * pgm_read_word_near(countn + n)) { 
         if(viv && freq != 0) {
           if(tglv)  { tone(10, freq - vvv); magOnwT(0, 50, tglv); }               //
           else      { tone(10, freq);       magOnwT(0, 50, tglv); } tglv = !tglv; // vivrato tgl    
         }
       } //
  } noTone(10);
}  
void stone(int ddd) {
  if(ddd == 00) { noTone(10); viv = 0; } else if(ddd == zzz) {  }  // nT/zzz 
  else { noTone(10); delay(2); tone(10, frqcalc(ddd)); }  // 
  if(octo > 4 && !viv) { delay(120); noTone(10); }        // Cut off, Base(1 or 2) short note 
}
long frqcalc(int dd) { 
  freq = oto[min(dd & 0x0f, 12)]; octo = 7 - ((dd & 0x70) >> 4);
  if(octo < 7) { for (int k = 0; k < octo; k++) { freq /= 2; } } else { freq = 0; }
  viv = bitRead(dd, 7);  // vibrato switch
  vvv = freq * 0.01;     // vibrato depth
  return freq;           // note frequency
}

SHAKEY.ino
// ============================================
//  Base design http://simblee.com
//  Language Reference http://arduino.cc/en/Reference/HomePage
//  24kRAM, 128kROM
// ============================================
//  PIN ASSIGN
// ============================================
// D2:IR input
// A3:Light Sensor (analogRead(3))
// D5:Driver Enable
// D6:Driver Phase
// D11:RGB
// D10:BUZZ
//  boarddefs.h in IR remote master 
//  avoid timer confrict between tone() and IR
//  #else
//   Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
//   ATmega48, ATmega88, ATmega168, ATmega328
//   #define IR_USE_TIMER1       // tx = pin 9 << send pin
//   //#define IR_USE_TIMER2     // tx = pin 3 << send pin
// ============================================
//  FILE INCLUDE 
// ============================================
  #include "FastLED.h"      // RGB LED
  #include "para.h"         //       
  #include <avr/pgmspace.h>  

  #include "IRremote.h"     // IR remote controll 
  IRrecv irrecv(2);         // create instance of 'irrecv' receive @D2
  decode_results results;   // create instance of 'decode_results'   
  CRGB leds[2];             // RGB LED buffer  

// ============================================
//  Variables
// ============================================   
  int part = 0;                // part 0 to 3rd   
  boolean tgll = true; 
  
// ============================================
//  SET UP
// ============================================   
void setup() {
  Serial.begin(9600);       // Serial.begin(115200); 
  pinMode(2,  INPUT);       // IR receive 
  pinMode(3,  INPUT);       // Light Sensor
  pinMode(5, OUTPUT); digitalWrite(5, 0);   // Coil Drive Enable
  pinMode(6, OUTPUT);       // Coil Drive Phase
  pinMode(10, OUTPUT);      // BUZZ  
  irrecv.enableIRIn();      // Start IR receiver 
  FastLED.addLeds<NEOPIXEL, 11>(leds, 2);     // FastLED setup for RGB LEDs       
  col(0, 10, 0);                              // RGB LED 
}
// ============================================
//  LOOP (SPIDER: or BALL:)    
// ============================================
void loop() {
  if(irrecv.decode(&results)) { 
   switch(results.value) {
     case 0xFFA25D: Serial.print("1:"); ImperialMarch1();  break;
     case 0xFF629D: Serial.print("2:"); ImperialMarch2();  break;
     case 0xFFE21D: Serial.print("3:"); ImperialMarch3();  break;
     case 0xFF22DD: Serial.print("4:"); CloseEncounters(); break;
     case 0xFF02FD: Serial.print("5:"); DanceoftheRead();  break;
     case 0xFFC23D: Serial.print("6:"); LadyMaddonna();    break;
     case 0xFFE01F: pi(Fs|o4); Serial.print("7:"); for (int k = 0; k < 10;  k++) { lolo( 50,  10); } break; // 1 mmm
     case 0xFFA857: pi(G|o4);  Serial.print("8:"); for (int k = 0; k < 10;  k++) { lolo( 50,  30); } break; // 2
     case 0xFF906F: pi(Gs|o4); Serial.print("9:"); for (int k = 0; k < 10;  k++) { lolo( 50,  60); } break; // 3 mmm
     case 0xFF9867: pi(A|o4);  Serial.print("0:"); for (int k = 0; k < 10;  k++) { lolo( 50, 100); } break; // 4
     case 0xFF6897: pi(As|o4); Serial.print("*:"); break;
     case 0xFFB04F: pi(B|o4);  Serial.print("#:"); break; // 17
     case 0xFF18E7: pi(C|o5);  Serial.print("UP:"); col(10, 20,  0); part = 0; break; // 11
     case 0xFF4AB5: pi(Cs|o5); Serial.print("DN:"); col( 0, 20,  0); part = 1; break; // 12
     case 0xFF10EF: pi(D|o5);  Serial.print("LT:"); col(20,  0,  0); part = 2; break; // 13
     case 0xFF5AA5: pi(Ds|o5); Serial.print("RT:"); col( 0,  0, 20); part = 3; break; // 14
     case 0xFF38C7: pi(E|o5);  Serial.print("OK:"); col(10, 10, 10); part = 0; break; // 15    
   } irrecv.resume();                         // receive the next value
   noTone(10);  
  }  
}
// ============================================
//  Motion (5:coil enable, 6:coil phase)     
// ============================================
void pi(int ddd) { tone(10, frqcalc(ddd)); delay(50); noTone(10); delay(50); }
void lolo(int magt, int fret)  { magOnwT(A|o4, magt, 1); delay(fret); magOnwT(A|o5, magt, 0); delay(fret); }
void magOnwT(int ddd, int tt, boolean ns) { digitalWrite(6, ns); // phase
  digitalWrite(5, 1); if(ddd != 0) { tone(10, frqcalc(ddd)); delay(20); noTone(10); } delay(tt); digitalWrite(5, 0); // delay/off
}
// ============================================
//  NEO PIXEL
// ============================================
void col(int x, int y, int z) { leds[0] = CRGB(x, y, z); leds[1] = leds[0]; FastLED.show(); }

Credits

Masahiro Mizuno

Masahiro Mizuno

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

Comments