I decided to make an automaton music box for this assignment. I never expected it could be so much work. Of all the projects this semester, I think I learned the most doing this one. In the process I accidentally fried 2 arduinos and a good handful of other electronics. While it was frustrating at the time, the other projects were much easier thanks to the knowledge I gained.

My friend Jackson made the 3 songs used after I gave him some small prompts, I was happy to get to include a piece of him in this odd little project.

The initial idea was a barber shop that caught on fire, not sure how well that was reflected but I was happy with the mood of the finished piece.

 

Electronics and Structure:

Some of the fabrication:

Some early sketches and plans:

 

Electronics:

arduino uno, 7408 quad AND gate, 7404 NOT gate, L293D motor driver, DFPlayer mini, 2 hobby gear motors, 1 continuous rotation servo, micro sd card, micro sd card reader/writer, 3 pushbuttons, 2 potentiometers, speakers, neo pixel ring, 4 yellow LEDs, 8 red LEDs, wires, resistor, breadboard, 5v power source

Materials:

wood, cardstock, cereal boxes, sewing pins, paperclips, wire, plastic bags, old clothing/fabric, thread, tissues, electrical tape, gaffer tape, duct tape, staples, boba straw, pebbles, Styrofoam

Tools:

soldering iron and fan, scissors, wire cutters, needle, pliers, precision knife, compass (drawing tool), stapler, pencils/pens, ruler, cutting mat

 

Code:

Everything but music:

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Adafruit_NeoPixel.h>
#include <Servo.h>
#define PIN 9
#define NUMPIXELS 12
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
bool stage1 = false;
bool stage2 = false;
bool stage3 = false;
bool button1 = false;
bool button2 = false;
bool button3 = false;
bool song1 = false;
bool song2 = false;
bool song3 = false;
int value;
int angle;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
uint32_t red = pixels.Color(250,0,0);
Servo myservo;
void setup() {
pixels.begin(); //backlight
pixels.setBrightness(0);
pixels.show();
pinMode(5, OUTPUT); //m1
pinMode(6, OUTPUT); //m2
myservo.attach(3); //m3
pinMode(7, INPUT); //button1
pinMode(8, INPUT); //button2
pinMode(4, INPUT); //button3
pinMode(A0, INPUT); //p1
pinMode(A1, INPUT); //p2
mySoftwareSerial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true);
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.volume(30); //Set volume value. From 0 to 30
}
void loop() {
//part 1
if (digitalRead(7) == HIGH) {
analogWrite(5, analogRead(A0)/4);
button1 = true;
} else {
button1 = false;
}
//part 2
if (digitalRead(8) == HIGH) {
analogWrite(6, analogRead(A0)/4);
button2 = true;
} else {
button2 = false;
}
//part 3
if (digitalRead(4) == HIGH) {
//m3
value = analogRead(A1);
angle = map(value, 0, 1023, 10, 170);
myservo.write(angle);
//backlight
pixels.setBrightness(150);
pixels.fill(red);
pixels.show();
button3 = true;
} else {
myservo.write(10);
pixels.setBrightness(0);
pixels.show();
button3 = false;
}
//dfmini
stage1 = (button1 && !button2);
stage2 = (button1 && button2 && !button3);
stage3 = (button1 && button2 && button3);
if (stage1 && !stage2 && !stage3 && !song1) {
myDFPlayer.play(3);
song1 = true;
song2 = false;
song3 = false;
} else if (stage2 && !stage3 && !song2){
myDFPlayer.play(1);
song2 = true;
song1 = false;
song3 = false;
} else if (stage3 && !song3){
myDFPlayer.play(2);
song3 = true;
song1 = false;
song2 = false;
}
if (!stage1 && !stage2 && !stage3) {
myDFPlayer.stop();
song1 = false;
song2 = false;
song3 = false;
}
}
#include "Arduino.h" #include "SoftwareSerial.h" #include "DFRobotDFPlayerMini.h" #include <Adafruit_NeoPixel.h> #include <Servo.h> #define PIN 9 #define NUMPIXELS 12 SoftwareSerial mySoftwareSerial(10, 11); // RX, TX DFRobotDFPlayerMini myDFPlayer; void printDetail(uint8_t type, int value); bool stage1 = false; bool stage2 = false; bool stage3 = false; bool button1 = false; bool button2 = false; bool button3 = false; bool song1 = false; bool song2 = false; bool song3 = false; int value; int angle; Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800); uint32_t red = pixels.Color(250,0,0); Servo myservo; void setup() { pixels.begin(); //backlight pixels.setBrightness(0); pixels.show(); pinMode(5, OUTPUT); //m1 pinMode(6, OUTPUT); //m2 myservo.attach(3); //m3 pinMode(7, INPUT); //button1 pinMode(8, INPUT); //button2 pinMode(4, INPUT); //button3 pinMode(A0, INPUT); //p1 pinMode(A1, INPUT); //p2 mySoftwareSerial.begin(9600); Serial.begin(115200); Serial.println(); Serial.println(F("DFRobot DFPlayer Mini Demo")); Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)")); if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3. Serial.println(F("Unable to begin:")); Serial.println(F("1.Please recheck the connection!")); Serial.println(F("2.Please insert the SD card!")); while(true); } Serial.println(F("DFPlayer Mini online.")); myDFPlayer.volume(30); //Set volume value. From 0 to 30 } void loop() { //part 1 if (digitalRead(7) == HIGH) { analogWrite(5, analogRead(A0)/4); button1 = true; } else { button1 = false; } //part 2 if (digitalRead(8) == HIGH) { analogWrite(6, analogRead(A0)/4); button2 = true; } else { button2 = false; } //part 3 if (digitalRead(4) == HIGH) { //m3 value = analogRead(A1); angle = map(value, 0, 1023, 10, 170); myservo.write(angle); //backlight pixels.setBrightness(150); pixels.fill(red); pixels.show(); button3 = true; } else { myservo.write(10); pixels.setBrightness(0); pixels.show(); button3 = false; } //dfmini stage1 = (button1 && !button2); stage2 = (button1 && button2 && !button3); stage3 = (button1 && button2 && button3); if (stage1 && !stage2 && !stage3 && !song1) { myDFPlayer.play(3); song1 = true; song2 = false; song3 = false; } else if (stage2 && !stage3 && !song2){ myDFPlayer.play(1); song2 = true; song1 = false; song3 = false; } else if (stage3 && !song3){ myDFPlayer.play(2); song3 = true; song1 = false; song2 = false; } if (!stage1 && !stage2 && !stage3) { myDFPlayer.stop(); song1 = false; song2 = false; song3 = false; } }
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

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

#define PIN            9
#define NUMPIXELS      12

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

bool stage1 = false;
bool stage2 = false;
bool stage3 = false;

bool button1 = false;
bool button2 = false;
bool button3 = false;

bool song1 = false;
bool song2 = false;
bool song3 = false;

int value;
int angle;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

uint32_t red = pixels.Color(250,0,0);

Servo myservo;

void setup() {
  pixels.begin(); //backlight 
  pixels.setBrightness(0); 
  pixels.show();         

  pinMode(5, OUTPUT); //m1
  pinMode(6, OUTPUT); //m2
  myservo.attach(3); //m3
  
  pinMode(7, INPUT); //button1
  pinMode(8, INPUT); //button2
  pinMode(4, INPUT); //button3
  
  pinMode(A0, INPUT); //p1
  pinMode(A1, INPUT); //p2

  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
}

void loop() {

  //part 1
  if (digitalRead(7) == HIGH) {
    analogWrite(5, analogRead(A0)/4);
    button1 = true; 
  } else {
    button1 = false;
  }

  //part 2
  if (digitalRead(8) == HIGH) {
    analogWrite(6, analogRead(A0)/4);
    button2 = true;
  } else {
    button2 = false;
  }

  //part 3
  if (digitalRead(4) == HIGH) {
    //m3
    value = analogRead(A1);
    angle = map(value, 0, 1023, 10, 170); 
    myservo.write(angle); 
    //backlight
    pixels.setBrightness(150);
    pixels.fill(red);
    pixels.show();
    button3 = true;
  } else {
    myservo.write(10);
    pixels.setBrightness(0);
    pixels.show();
    button3 = false;
  }

  //dfmini 
  stage1 = (button1 && !button2);
  stage2 = (button1 && button2 && !button3);
  stage3 = (button1 && button2 && button3);
  
  if (stage1 && !stage2 && !stage3 && !song1) {
    myDFPlayer.play(3);
    song1 = true;
    song2 = false;
    song3 = false;
  } else if (stage2 && !stage3 && !song2){
    myDFPlayer.play(1);
    song2 = true;
    song1 = false;
    song3 = false;
  } else if (stage3 && !song3){
    myDFPlayer.play(2);
    song3 = true;
    song1 = false;
    song2 = false;
  } 
  
  if (!stage1 && !stage2 && !stage3) {
    myDFPlayer.stop();
    song1 = false;
    song2 = false;
    song3 = false;
  }
  
}

 

dfmini controls:

/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
<https://www.dfrobot.com/index.php?route=product/product&product_id=1121>
***************************************************
This example shows the basic function of library for DFPlayer.
Created 2016-12-07
By [Angelo qiao](Angelo.qiao@dfrobot.com)
GNU Lesser General Public License.
See <http://www.gnu.org/licenses/> for details.
All above must be included in any redistribution
****************************************************/
/***********Notice and Trouble shooting***************
1.Connection and Diagram can be found here
<https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
2.This code is tested on Arduino Uno, Leonardo, Mega boards.
****************************************************/
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
int counter = 1;
void setup()
{
pinMode(7, INPUT);
mySoftwareSerial.begin(9600);
Serial.begin(115200);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true);
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.volume(30); //Set volume value. From 0 to 30
}
void loop()
{
if (digitalRead(7) == HIGH) {
if (counter == 1) {
myDFPlayer.play(3);
} else if (counter == 2) {
myDFPlayer.play(1);
} else if (counter == 3) {
myDFPlayer.play(2);
} else {
myDFPlayer.stop();
}
counter = counter + 1;
if (counter == 5) {
counter = 1;
}
delay(200);
}
if (myDFPlayer.available()) {
printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
}
}
void printDetail(uint8_t type, int value){
switch (type) {
case TimeOut:
Serial.println(F("Time Out!"));
break;
case WrongStack:
Serial.println(F("Stack Wrong!"));
break;
case DFPlayerCardInserted:
Serial.println(F("Card Inserted!"));
break;
case DFPlayerCardRemoved:
Serial.println(F("Card Removed!"));
break;
case DFPlayerCardOnline:
Serial.println(F("Card Online!"));
break;
case DFPlayerPlayFinished:
Serial.print(F("Number:"));
Serial.print(value);
Serial.println(F(" Play Finished!"));
break;
case DFPlayerError:
Serial.print(F("DFPlayerError:"));
switch (value) {
case Busy:
Serial.println(F("Card not found"));
break;
case Sleeping:
Serial.println(F("Sleeping"));
break;
case SerialWrongStack:
Serial.println(F("Get Wrong Stack"));
break;
case CheckSumNotMatch:
Serial.println(F("Check Sum Not Match"));
break;
case FileIndexOut:
Serial.println(F("File Index Out of Bound"));
break;
case FileMismatch:
Serial.println(F("Cannot Find File"));
break;
case Advertise:
Serial.println(F("In Advertise"));
break;
default:
break;
}
break;
default:
break;
}
}
/*************************************************** DFPlayer - A Mini MP3 Player For Arduino <https://www.dfrobot.com/index.php?route=product/product&product_id=1121> *************************************************** This example shows the basic function of library for DFPlayer. Created 2016-12-07 By [Angelo qiao](Angelo.qiao@dfrobot.com) GNU Lesser General Public License. See <http://www.gnu.org/licenses/> for details. All above must be included in any redistribution ****************************************************/ /***********Notice and Trouble shooting*************** 1.Connection and Diagram can be found here <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram> 2.This code is tested on Arduino Uno, Leonardo, Mega boards. ****************************************************/ #include "Arduino.h" #include "SoftwareSerial.h" #include "DFRobotDFPlayerMini.h" SoftwareSerial mySoftwareSerial(10, 11); // RX, TX DFRobotDFPlayerMini myDFPlayer; void printDetail(uint8_t type, int value); int counter = 1; void setup() { pinMode(7, INPUT); mySoftwareSerial.begin(9600); Serial.begin(115200); Serial.println(); Serial.println(F("DFRobot DFPlayer Mini Demo")); Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)")); if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3. Serial.println(F("Unable to begin:")); Serial.println(F("1.Please recheck the connection!")); Serial.println(F("2.Please insert the SD card!")); while(true); } Serial.println(F("DFPlayer Mini online.")); myDFPlayer.volume(30); //Set volume value. From 0 to 30 } void loop() { if (digitalRead(7) == HIGH) { if (counter == 1) { myDFPlayer.play(3); } else if (counter == 2) { myDFPlayer.play(1); } else if (counter == 3) { myDFPlayer.play(2); } else { myDFPlayer.stop(); } counter = counter + 1; if (counter == 5) { counter = 1; } delay(200); } if (myDFPlayer.available()) { printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states. } } void printDetail(uint8_t type, int value){ switch (type) { case TimeOut: Serial.println(F("Time Out!")); break; case WrongStack: Serial.println(F("Stack Wrong!")); break; case DFPlayerCardInserted: Serial.println(F("Card Inserted!")); break; case DFPlayerCardRemoved: Serial.println(F("Card Removed!")); break; case DFPlayerCardOnline: Serial.println(F("Card Online!")); break; case DFPlayerPlayFinished: Serial.print(F("Number:")); Serial.print(value); Serial.println(F(" Play Finished!")); break; case DFPlayerError: Serial.print(F("DFPlayerError:")); switch (value) { case Busy: Serial.println(F("Card not found")); break; case Sleeping: Serial.println(F("Sleeping")); break; case SerialWrongStack: Serial.println(F("Get Wrong Stack")); break; case CheckSumNotMatch: Serial.println(F("Check Sum Not Match")); break; case FileIndexOut: Serial.println(F("File Index Out of Bound")); break; case FileMismatch: Serial.println(F("Cannot Find File")); break; case Advertise: Serial.println(F("In Advertise")); break; default: break; } break; default: break; } }
/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
 <https://www.dfrobot.com/index.php?route=product/product&product_id=1121>

 ***************************************************
 This example shows the basic function of library for DFPlayer.

 Created 2016-12-07
 By [Angelo qiao](Angelo.qiao@dfrobot.com)

 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution
 ****************************************************/

/***********Notice and Trouble shooting***************
 1.Connection and Diagram can be found here
 <https://www.dfrobot.com/wiki/index.php/DFPlayer_Mini_SKU:DFR0299#Connection_Diagram>
 2.This code is tested on Arduino Uno, Leonardo, Mega boards.
 ****************************************************/

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);

int counter = 1;

void setup()
{
  pinMode(7, INPUT);
  
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(30);  //Set volume value. From 0 to 30
}

void loop()
{
  
  if (digitalRead(7) == HIGH) {
    if (counter == 1) {
      myDFPlayer.play(3);
    } else if (counter == 2) {
      myDFPlayer.play(1);
    } else if (counter == 3) {
      myDFPlayer.play(2);
    } else {
      myDFPlayer.stop();
    }
    counter = counter + 1;
    if (counter == 5) {
      counter = 1;
    }
    delay(200);
  }

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }
}

void printDetail(uint8_t type, int value){
  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

 

Useful references:

DFPlayermini

https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299

https://www.instructables.com/Tutorial-of-MP3-TF-16P/

L293d

https://www.tinkercad.com/things/gigwXYoyaDb

Neopixel_ring

https://www.instructables.com/3D-Printed-NeoPixel-Ring-Butterfly-With-Tinkercad/

https://www.tinkercad.com/things/c4nyZ9UpWer

 

Libraries found on Github:

https://github.com/adafruit/Adafruit_NeoPixel

https://github.com/DFRobot/DFRobotDFPlayerMini

 

TinkerCad Circuits I used to troubleshoot:

https://www.tinkercad.com/things/0evKMIHM0Ai-fantabulous-inari/editel?sharecode=NX5CYihf8vkyRuLa-rzRwghpmeox1-OVk11WzY99hrU

https://www.tinkercad.com/things/7uIwm5bLp6N-copy-of-project-1/editel?sharecode=YA4F9Lz2rxujlDz2OgQx0Xv3PKQZNSbunOs2S8PjWWM