Arduino | Animate Shield Code

Overview

The following code is what we include preloaded on our Animate shield/Arduino board. If you decide to modify or upload your own code to your board, you can always grab this code and upload it to your Arduino.

Upload the default code below using the Board Reset Tool

The Code


// Make Stuff Move | Animate Shield v8.0
// This is the code that comes preloaded on our animate shield/Arduino board combo

int VERSION = 2;

#include <Adafruit_NeoPixel.h>
#include <Servo.h>
#include <EEPROM.h>

// Setup the LED
#define LED_PIN 7
#define LED_COUNT 1
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);


#define MIC_PIN A5
int mic_value;
int curr_level = 0;
int prev_level = 0;
int servo_level = 0;
int light_level = 0;
int is_beat = 0;
int mic_cut_default = 180;
int mic_cut = 180;

// min and max values from the sensor
int vol_min = 300;
int vol_max = 600;



// Cabibration of min and max values from analog
#define ANALOG_MAX 1023
#define ANALOG_MIN 0
#define SERVO_MIN 2
#define SERVO_MAX 178

// Delay between reading for recording movement
int frame = 0;
int playSpeed = 50; // in ms, 50ms seems good
#define FRAME_DELAY 50 // in ms, 50ms seems good
#define FRAME_LIMIT 1024 // number of samples to store

// Arduino Pin assignments
int recordButtonPin = 12;
int playButtonPin = 11;
int ledPin = 13;
int ledState = 0;
int servoPinA = 8;
int servoPinB = 9;
int servoPinC = 10;
int knobPinA = A0;
int knobPinB = A1;
int knobPinC = A2;

// Variables for record/play state
int repeat = 1;
int playing = 0;
int recording = 0;

long pressTime = 0;


// Create the servo objects
Servo myServoA;
Servo myServoB;
Servo myServoC;


void setup() {
  Serial.begin(9600);
  Serial.println("Make Stuff Move | 3 Servo Record and Play");

  pinMode(recordButtonPin, INPUT);
  digitalWrite(recordButtonPin, HIGH);

  pinMode(playButtonPin, INPUT);
  digitalWrite(playButtonPin, HIGH);

  pinMode(ledPin, OUTPUT);

  pinMode(knobPinA, INPUT);
  pinMode(knobPinB, INPUT);
  pinMode(knobPinC, INPUT);


  myServoA.attach(servoPinA);
  myServoB.attach(servoPinB);
  myServoC.attach(servoPinC);

  //Light
  strip.begin();
  strip.show();

  versionBlink(VERSION);

}

void loop() {


  // Check for the play button being clicked or held
  if (digitalRead(playButtonPin) == LOW) {
    pressTime = 0;
    while (digitalRead(playButtonPin) == LOW) {
      delay(1000);
      pressTime = pressTime + 1;
    }
    if (pressTime < 2) {
      Serial.println("PLAY ONLY");
      playServos(playButtonPin);
    }
    else {
      Serial.println("PLAY DANCE");
      playServosDance(playButtonPin);
    }
    pressTime = 0;
  }


  // Check for Record button
  else if (! digitalRead(recordButtonPin)) {
    delay(10);
    // wait for released
    while (! digitalRead(recordButtonPin)) {
      delay(100);
      // OK released!
    }
    Serial.println("RECORD");
    recordServos(recordButtonPin);
  }

  // Otherwise just read the knobs to move the servos
  else {
    moveServos();

  }

}

// Move Function -------------------------------------------------------------------------
void moveServos() {


  // Read the value from the mic
  int mic_value = analogRead(MIC_PIN);
  //Serial.print("MIC | ");
  //Serial.println(mic_value);
  curr_level = map(mic_value, vol_min, vol_max, 0, 100);



  // If the current level is lower than the previous level fade the pixel and move the meter down
  // This provides a smoother movement
  if (curr_level < prev_level) {
    curr_level = prev_level - 2;

    // Don't let the level drop below zero
    if (curr_level < 0) {
      curr_level = 0;
    }

  }


  // Enable the following to get visual output in the Serial Monitor
  //  Warning this slows down the servo ...adds lag
  /*
    for (int i = 0; i <= curr_level/5; i++) {
    Serial.print("|");
    }
    Serial.println("|");
  */




  int a = analogRead(knobPinA);
  int b = analogRead(knobPinB);
  int c = analogRead(knobPinC);

  int red = map(a, ANALOG_MIN, ANALOG_MAX, 255, 0);
  int green = map(b, ANALOG_MIN, ANALOG_MAX, 255, 0);
  int blue = map(c, ANALOG_MIN, ANALOG_MAX, 255, 0);

  light_level = map(curr_level, 0, 100, 0, 50);
  light_update(red, green, blue, light_level);


  a = map(a, ANALOG_MIN, ANALOG_MAX, SERVO_MIN, SERVO_MAX);
  myServoA.write(a);

  b = map(b, ANALOG_MIN, ANALOG_MAX, SERVO_MIN, SERVO_MAX);
  myServoB.write(b);
  //c = map(c, ANALOG_MIN, ANALOG_MAX, SERVO_MIN, SERVO_MAX);
  //myServoC.write(c);

  int servo_meter = map(curr_level, 0, 100, SERVO_MAX, SERVO_MIN);
  myServoC.write(servo_meter);

  Serial.print("SERVO | ");
  Serial.println(servo_meter);

  prev_level = curr_level;
}






// Play Function Dance

void playServosDance(int buttonPin) {

  Serial.println("Playing and Dancing");

  frame = 0;
  playing = 1;

  digitalWrite(ledPin, HIGH);


  while (digitalRead(buttonPin) == HIGH) {


    //Allow for beat cut-in value to be adjusted with holding record and knob A
    if (digitalRead(recordButtonPin) == LOW) {
      mic_cut = analogRead(knobPinA);
      mic_cut = map(mic_cut, ANALOG_MIN, ANALOG_MAX, 300, 50);
      Serial.print("mic_cut: ");
      Serial.println(mic_cut);
    }

    // Read the value from the mic
    int mic_value = analogRead(MIC_PIN);
    //Serial.print("MIC: ");
    //Serial.println(mic_value);


    // Set the cutoff value and if lower, fade the current level for the servo and led
    if (mic_value > mic_cut) {
      is_beat = 1;
      curr_level = 50;
    }
    else {
      is_beat = 0;
      curr_level = prev_level - 7;

    }

    int a = EEPROM.read(frame + 0);
    int b = EEPROM.read(frame + 1);
    int c = EEPROM.read(frame + 2);



    // Check for stop/loop frame
    if (a == 255 or b == 255 or c == 255) {
      frame = 0;
      Serial.println("loop");
      continue;
    }

    if (frame == 0 and is_beat == 0) {
      //Serial.println("waiting");
    }
    else {
      if (frame == 0) {
        Serial.println("BEAT!!");
      }
      frame = frame + 3;
    }

    myServoA.write(a);
    myServoB.write(b);
    myServoC.write(c);

    int red = map(a, 0, 180, 255, 0);
    int green = map(b, 0, 180, 255, 0);
    int blue = map(c, 0, 180, 255, 0);
    light_update(red, green, blue, 50);

    delay(playSpeed);

    prev_level = curr_level;

  }
  Serial.println("Stoped Playing");
  //reset the mic_cut
  mic_cut = mic_cut_default;

  delay(200);
  digitalWrite(ledPin, LOW);

}



// Play Function Frames -------------------------------------------------
void playServos(int buttonPin) {


  Serial.println("Playing");

  frame = 0;
  playing = 1;

  digitalWrite(ledPin, HIGH);

  while (digitalRead(buttonPin) == HIGH) {

    int a = EEPROM.read(frame + 0);
    int b = EEPROM.read(frame + 1);
    int c = EEPROM.read(frame + 2);

    int red = map(a, 0, 180, 255, 0);
    int green = map(b, 0, 180, 255, 05);
    int blue = map(c, 0, 180, 255, 0);
    light_update(red, green, blue, 50);

    // Check for stop/loop frame
    if (a == 255 or b == 255 or c == 255) {
      frame = 0;
      if (repeat == 1) {
        Serial.println("loop");
        continue;
      }
      else {
        Serial.println("stop");
        break;
      }
    }

    myServoA.write(a);
    myServoB.write(b);
    myServoC.write(c);

    // Set speed from first knob A0 while the recordbutton is held down during playback
    if (! digitalRead(recordButtonPin)) {
      playSpeed = analogRead(knobPinA);
      playSpeed = map(playSpeed, ANALOG_MIN, ANALOG_MAX, 100, 0);
    }
    delay(playSpeed);

    frame = frame + 3;

  }
  Serial.println("Stoped Playing");
  delay(200);
  digitalWrite(ledPin, LOW);

}







// Record Function -------------------------------------------------
void recordServos(int buttonPin) {
  frame = 0;

  Serial.println("Recording");

  while (digitalRead(buttonPin)) {

    //int last_a = a;
    int a = analogRead(knobPinA);
    //  Create a smoothing by looking at the difference between values
    //  ie if change is not more than say 5 then do not make a change.

    a = map(a, ANALOG_MIN, ANALOG_MAX, 0, 180);
    myServoA.write(a);
    EEPROM.write(frame, a);

    int b = analogRead(knobPinB);
    b = map(b, ANALOG_MIN, ANALOG_MAX, 0, 180);
    myServoB.write(b);
    EEPROM.write(frame + 1, b);

    int c = analogRead(knobPinC);
    c = map(c, ANALOG_MIN, ANALOG_MAX, 0, 180);
    myServoC.write(c);
    EEPROM.write(frame + 2, c);

    Serial.print(frame);
    Serial.print(" | ");
    Serial.print(a);
    Serial.print(",");
    Serial.print(b);
    Serial.print(",");
    Serial.print(c);
    Serial.println("");

    int red = map(a, 0, 180, 255, 0);
    int green = map(b, 0, 180, 255, 0);
    int blue = map(c, 0, 180, 255, 0);
    light_update(red, green, blue, 50);

    if (frame == FRAME_LIMIT) break;

    frame = frame + 3;

    //  Only take a reading every so many miliseconds to store
    delay(FRAME_DELAY);

    // Blink the light
    if (ledState == 0) {
      digitalWrite(ledPin, HIGH);
      ledState = 1;
    }
    else {
      digitalWrite(ledPin, LOW);
      ledState = 0;
    }
  }


  Serial.println("Stopping Rcording");

  //  If we stop before the end of the storage limit, store 999 so the play funciton will know when to loop.
  if (frame != FRAME_LIMIT) {
    Serial.println("Adding Loop Frame");
    //Set an arbitrary frame number that we will never store ir "999"
    EEPROM.write(frame, 255);
  }

  digitalWrite(ledPin, LOW);

  Serial.println("Finished Recording");
  delay(500);
}


void light_update(int red, int green, int blue, int brightness) {
  uint32_t color = strip.Color(red, green, blue);
  strip.setBrightness(brightness);
  strip.fill(color, 0, LED_COUNT);
  strip.show();
}


void versionBlink(int codeVersion) {
  int ledBlink = 0;
  for (int i = 0; i < codeVersion * 2; i++ ) {
    if (ledBlink == 0) {
      light_update(50, 255, 0, 0);
      ledBlink = 1;
      delay(200);
    }
    else {
      light_update(50, 255, 0, 50);
      ledBlink = 0;
      delay(300);
    }
  }
}