Music & Snack Alarm Clock

A rectangular box made of clear acrylic with 3 doors (silver, attached with hinges) is shown, with the doors hanging open and the servos that usually hold them closed seen in the "open" position. 3 switches to control the servos and an ON/OFF switch are also seen. On the top there is a small circular speaker.

Overall View: Open

When the alarm clock goes off, a song starts playing through the speaker and the doors open up to reveal mornings meds and snacks. 

A rectangular box made of clear acrylic with 3 doors (silver, attached with hinges) being held shut by 3 servo motors. 3 switches to control the servos and an ON/OFF switch are also seen. On the top there is a small circular speaker.

Overall View: Closed

When the project is off or the alarm clock is counting down, the doors are closed.

One side of the box is shown. There is a touchpad keypad with numbers 0-9 and letters A-D, as well as a * and a # key. There is an LCD screen at the top with a label reading "LCD" with a smiley face. There is also a label that read "Use keypad to set timer. 2 digit maximum. Use '#' to start."

Highlight: LCD & Keypad

I had never worked with a keypad before, so this was a learning experience! I also got to practice my LCD screen usage more after starting to learn about it in Project 1. 

The top of the box is shown. There is a small circular speaker and a label reading "speaker."

Highlight: Speaker

Another component that I used in this project was a speaker. I used a card to play a song through the speaker when the clock went off, instead of just using a buzzer. It provided some challenges but ended up working pretty well!

IMG_0635.MOV

In Use: Switches & Servos

This video shows the project in use; it desmonstrated the servos that unlock the doors opening when their respective switches are thrown. 

IMG_0647.MOV

Final Project In Use Video

This video shows the whole process of the project, from setting the timer to the alarm going off and the servos unlocking. The timer is set to seconds in this video for demo mode, whereas if this project went on to be used "in the real world" it would be set to hours. 

This image shows the mp3-tf-16p connected via jumper wires to an Arduino UNO and a small circular speaker. The loose circuit is laying on a table in front of a laptop.

Speaker: Starting Out

I started trying to use the speaker with the UNO, but quickly got worried that I wouldn't have enough pins on the UNO to use the speaker, all the switches I wanted, and the keypad (which takes up a lot of pins). I also tried to get a micro SD card from IDEATE lending, but they didn't have one that worked with the speaker. Amazon to the rescue! Once armed with the card, I tried to format it, but had a hard time figuring out how the different libraries I was trying to use wanted the card to be formatted. 

This image shows the mp3-tf-16p connected via jumper wires to a larger Arduino and to a small circular speaker. The loose circuit is laying on a table.

Speaker: Bigger Board?

I finally got the speaker working after fighting with the card formatter and a few different libraries. I used a larger Arduino for a bit, but lending needed it back and I figured I could make the UNO work for the pins I needed. I experimented with different libraries, but eventually settled on one that had decent documentation in the form of a video of the creator showing YouTube how to use it. 

IMG_0415.MOV

Speaker: Success!

I finally got the speaker playing music! Later I found out that I didn't understand the library well enough to figure out how to STOP the music, which was an ongoing issue in the project. Simply getting the music to play was an exciting milestone though!

This image shows a rectangular piece of cardboard with paper cutouts of smaller rectangles that represent the size and shape of the three doors and three hinges to be used for the project. The whole thing is laying flat on a table.

I started out the box design process by cutting out pieces of paper the size and shape that I wanted the doors to be and the size and shape of the hinges that I had on hand. I lay these paper pieces out on the table and cut a piece of cardboard to the size that looked right for the front plate; from here I transferred these dimesnions into Solidworks. 

This image shows the cardboard and paper size & shape prototype of the front plate with servos, LEDs, switches, and some wires laying on it to test the sizing of different components before translating the front plate to CAD in SOLIDWORKS.

Once I had the rough size and shape of the cabinet doors, I figured I should make sure that the servos and switches I wanted to use had ergonomic locations that they could fit in. I left enough space to add a funky LED ring around the ON/OFF button, but didn't end up implementing that design choice due to time. 

This image shows the laser cut front plate and one side plate connected. There are cutouts on the front plate for servo motors, switches, and doors, and there is a cutout on the side plate for an LCD as well as one for the data lines from the keypad.

I first cut the box components out of scrap wood to make sure it fit -- it didn't! Then I made changes and cut it again -- it still didn't!! This happened more time than I'd like to admit for various very small (like 1/16") changes that were mostly small errors I made trying to make CAD too quickly. 

This image shows the completed chassis (made of clear acrylic) before the protective brown film was peeled off; there is a front, back, and 4 side plates with holes cut for various components, as well as inserts that form the walls and floors of the pockets behind the doors. The box is put together and standing on a stool in the IDeATe laser room.

IDEATE lending was also out of all colors of 1/4" acrylic except for clear, and they only had 1'x1' pieces, so I had to make my box clear and fit within that size constraint. Eventually, after SO MUCH PROTOTYPING, I made a box!!

DISCUSSION

Some written critiques that I received during the final critique of this project included a lot about the doors; one person said ​​”Extremely clean implementation, one critique I have is to implement the doors without tape, only because it contrasts against the uber clean implementation,” and another person said “It looks so nice! I think it would have been better if you put the trap doors as like wood or clear acrylic,” both of which are critiques that I fully agree with. My original plan was to cut the doors from acrylic, and my original plan for the acrylic was for it to either be colored (not clear) or to be clear and painted so that seeing inside looked less messy, but IDeATe lending was out of non-clear ¼” acrylic and I ran out of time on the doors, so they ended up being cardboard coated in silver tape. I don’t really love the way they turned out visually, but they worked in a pinch. Another critique I got was “Would like to see it so something like drop a snack through a servo connected trap door instead of having to manually open and close the doors,” which is another piece of critique that I agree with wholeheartedly; I originally wanted to use spring loaded hinges so the doors popped open, but I didn’t have them on hand and I worried about the servos being strong enough to hold them closed. This idea is super cool though — a snack dropping through a trap door would also help you walk up when the alarm goes off! 


I am pretty happy with how my project turned out. I ran into a LOT of issues (struggles with laser cutting, struggles with the libraries for the mp3 player) but I got through it and ended up with a project that did everything I set out to do, except stop the song when you flipped the ON/OFF switch. The ON/OFF switch worked otherwise, but when the song was playing, nothing else in the project responded to any input whatsoever until the song was done playing; this was a fault of me not being good at reading library documentation I think, and given a little more time I could have figured it out I think. I would have liked to use a mix of clear and colored acrylic maybe to hide the inner wiring, but people also seemed to like the clear acrylic, and I do understand the appeal of being able to see inside. I’m happy with how the LCD screen and the keypad work (except for during final critique, when the LCD screen got disconnected) and I think the little “Setting timer!” message, as well as the live countdown, are cute and were well-timed.


I learned that while I like laser cutting and CAD, it can be frustrating to do on a time crunch; I felt super stressed about not being able to access the laser room, so I rushed the CAD and then had to redo a lot of it over and over again due to silly mistakes made from rushing. In the future, I would like to work slower through the CAD to make sure that I do things correctly the first time around. My biggest challenge was perhaps the mp3 player library; I tried 3 libraries and couldn’t figure out how to integrate them into my code how I wanted to. In the future this is a process I would start earlier. I ignored the issue of not being able to stop the song for a while because I figured it would be an easy fix, but then after spending an hour or more trying to fix it, I realized it was definitely not an easy fix for me. Another issue I had was my wiring; I did a lot of soldering because I felt confident after the last project, but then the day before the project was due, I tried to put everything into my clear enclosure and suddenly everything stopped working. I spent about 3 hours trying to figure out the problem before I gave up on good problem solving and started just rapidly replacing every single wire and every single connection in the project out of desperation, which ended up fixing it. I thought I was “ahead” by getting the soldering done and the project working a few days before it was due, but I learned that it is not always as easy as “place the fully soldered assembly into the chassis” and that I should do that much sooner to avoid this in the future. 


If I was to build another iteration of this project, I would likely use different acrylic to let the wiring hide a little more, or do a much neater job of wiring. I would also make the doors out of a more “permanent” or nice looking material like wood or acrylic. I also would use a different library for the mp3 player so that I could stop the song!

CODE:

/*

Ella Sanfilippo CMU 60-223 Project 2 Code

This code is for an alarm clock with 3 doors that 

unlock via servo motors, and includes 3 switches

to control the servos and a master ON/OFF switch.

It uses an mp3 player for the alarm clock sound and 

features an LCD screen and a keypad for entering

the desired number of hours to sleep. 

Please see the textblock below for links to resources. 

*/


/*

PIN DIAGRAM:

12 -> left door switch

13 -> right door switch

A3 -> bottom door switch 

A5 -> main on/off switch

A0 -> left door servo 

A1 -> right door servo 

A2 -> bottom door servo 

10 & 11 -> mp3 player connections 

*/


#include <Servo.h>

#include <Wire.h>

#include <ezButton.h>

#include <Keypad.h>

#include "mp3tf16p.h"

#include <LiquidCrystal_I2C.h>


//LCD

LiquidCrystal_I2C screen(0x27, 16, 2);

const int LCDLONG = 250; // 4x/second

long LCDtimer = 0;


//SWITCHES

ezButton leftSwitch(12); // create ezButton object that attach to pin 12;

ezButton rightSwitch(13);

ezButton bottomSwitch(A3);

ezButton mainSwitch(A5);


Servo leftServo;

Servo rightServo;

Servo bottomServo;


//SEROVS

const int LEFT_PIN = A0;

const int RIGHT_PIN = A1;

const int BOTT_PIN = A2;


//KEYPAD

const byte ROWS = 4;

const byte COLS = 4;


//MP3 PLAYER

MP3Player mp3(10, 11); //pins 10 and 11


char hexaKeys[ROWS][COLS] = {

{ '1', '2', '3', 'A' },

{ '4', '5', '6', 'B' },

{ '7', '8', '9', 'C' },

{ '*', '0', '#', 'D' }

};


//TIMER

const int LONGENOUGH = 1000; // 1x/seconds

long timer = 0;

String inputString;

long inputInt;

bool counting = false;

unsigned long previousMillis;

unsigned long currentMillis;

unsigned long startMillis;


byte rowPins[ROWS] = { 9, 8, 7, 6 };

byte colPins[COLS] = { 5, 4, 3, 2 };


Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);



void setup() {

Serial.begin(9600);

leftSwitch.setDebounceTime(50); // set debounce time to 50 milliseconds

rightSwitch.setDebounceTime(50);

bottomSwitch.setDebounceTime(50);

mainSwitch.setDebounceTime(50);


leftServo.attach(LEFT_PIN);

rightServo.attach(RIGHT_PIN);

bottomServo.attach(BOTT_PIN);


screen.init();

screen.backlight();


mp3.initialize();

}


void loop() {

leftSwitch.loop();

rightSwitch.loop();

bottomSwitch.loop();

mainSwitch.loop();


char key = customKeypad.getKey();

int state = mainSwitch.getState();


if (leftSwitch.isPressed()) {

Serial.println("Left switch: OFF -> ON");

leftServo.write(180);

Serial.println("Left servo pos: 180");

}

if (leftSwitch.isReleased()) {

Serial.println("Left switch: ON -> OFF");

leftServo.write(90);

Serial.println("Left servo pos: 90");

}


if (rightSwitch.isPressed()) {

Serial.println("Right switch: OFF -> ON");

rightServo.write(180);

Serial.println("Right servo pos: 180");

}

if (rightSwitch.isReleased()) {

Serial.println("Right switch: ON -> OFF");

rightServo.write(90);

Serial.println("Right servo pos: 90");

}


if (bottomSwitch.isPressed()) {

Serial.println("Bottom switch: OFF -> ON");

bottomServo.write(180);

Serial.println("Bottom servo pos: 180");

}

if (bottomSwitch.isReleased()) {

Serial.println("Bottom switch: ON -> OFF");

bottomServo.write(90);

Serial.println("Bottom servo pos: 90");

}


if (state == HIGH) {

if (key) {

Serial.println(key);

}

if (key >= '0' && key <= '9') { // only act on numeric keys

inputString += key; // append new character to input string

screen.clear();

screen.setCursor(0,0);

screen.print("Set timer: ");

screen.setCursor(0,1);

inputInt = inputString.toInt();

screen.print(inputInt);

}

else if (key == '#') {

if (inputString.length() > 0) {

screen.clear();

screen.print("Setting timer!");

delay(1000); //1 sec delay

inputInt = inputString.toInt(); // YOU GOT AN INTEGER NUMBER

inputString = ""; // clear input

startMillis = millis(); //the start time

counting = true;

}

}

int inputMin = inputInt * 60; //inputInt is in hours; put in mins

int inputSec = inputMin * 60;

//int inputMillis = inputSec * 1000;

//FOR DEMO MODE:

int inputMillis = inputInt * 1000; //1 hour = 1 second for demo

if ((inputMillis - currentMillis) >= 0 && counting) {

currentMillis = millis() - startMillis;

}

if (counting && (inputMillis - currentMillis == 0)) {

counting = false;

screen.clear();

screen.setCursor(0,0);

Serial.println("DONE!");

screen.print("DONE!");

//when timer hits zero, servos open and music plays

leftServo.write(180);

rightServo.write(180);

bottomServo.write(180);

mp3.playTrackNumber(1, 20);

}


if (millis() - timer >= LONGENOUGH && counting) {

Serial.println();

Serial.println("Counting...");

Serial.println("Current seconds: ");

Serial.println(currentMillis / 1000);

Serial.println("Counting to: ");

Serial.println(inputMillis / 1000);

screen.clear();

screen.home();

screen.print("Time Remaining: ");

screen.setCursor(0, 1);

screen.print(inputMillis/1000 - currentMillis/1000);

timer = millis();

}


}

if(state==LOW){

//reset all

inputString = "";

counting = false;

screen.clear();

screen.setCursor(0,0);

screen.print("OFF");

//screen.noDisplay();

Serial.println("OFF");

delay(1000);

screen.noDisplay();

}

}

Block Diagram

Schematic: