Animate Sheild 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.

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);
    }
  }
}
Leave a Reply

Your email address will not be published. Required fields are marked *