<featured image>
When I can’t get a loved one on the phone, this box plays a song I associate with them, and the LCD displays an activity that I frequently do with them, the advice I think they’d give me in this scenario, or a link to a piece of media we usually watch together.
<moving image>
<overall photo>
<detail photo>
<image showing use of the thing>
Process
<old code where I had to comment out delays>
The amount of SRAM on the board was a huge problem. Whenever the Arduino Uno pulls up a file from the SD card, I think it creates a big file buffer, which takes up almost half of the available SRAM. Getting my code to run all the way to the end without being overwritten by the file buffer was a trial and error process, mostly involving constant commenting things out. This also made debugging really difficult, since I didn’t have enough SRAM for a lot of Serial.print statements.
<pivoting to a feather because it has more on board RAM>
I wound up pivoting to an Adafruit Feather board because it had more RAM available, so I could hardcode in more people.
<CAD model screenshot>
I originally wanted to laser cut pieces to make the enclosure, but decided to pivot to a cardboard box due to time constraints.
Discussion
I’m pretty happy with how the project turned out. It evolved a lot from my original concept, which functionally worked as a voicemail box which didn’t autodelete messages. The low sound quality and the way only one message could repeat from each person ended up feeling a little creepy instead of comforting, and pivoting to a music clip instead wound up giving me what I was actually looking for. I haven’t actually gotten a chance to use it, but frequently wind up wanting to use it now that I know it exists. Creating the project made me more conscious of all the barriers stopping me from contacting these people (time zones, stressful deadlines on both sides).
I wound up using a cardboard box due to time constraints, but also actually really liked it. Making a box which can open and close seamlessly is pretty difficult, and the long rectangular prism of the cardboard box actually looks a little sleeker than the squat cube I had originally designed. I think I should definitely use more cardboard for prototyping in future. I did learn that the choice of microcontroller has a lot of effect on the final project, since the amount of SRAM on the Arduino significantly impacted the behavior of the final product – I spent a long time adjusting delays to get the feel of the keypad to more accurately replicate the experience of using a telephone, and had to get rid of all that code because of the SRAM constraint.
I think it would be fun to redo this project with an actual telephone. I have one at home and might give it a shot – that would be a fun item just to keep around the house, and a good conversation starter. I also think that the idea of having people be able to record messages would be really fun! I love hosting events with lots of people, and getting a bunch of audio recordings from an event would be a great memento.
People’s primary critique of my project was that it was difficult to remember numbers. One person suggested “having letters instead of the numbers to make it easier to put in someone’s name instead of remembering their number,” but I’m not a huge fan of this idea. I like having a few friends’ numbers memorized, and I have numbers memorized for all of the people hardcoded in currently. A different person suggested “having the numbers be listed on the box itself could help with that” – I like that option a lot better. I think having the numbers on a piece of paper inside the box could be fun, with the current cardboard box, or having numbers posted on the wall next to the place where the telephone sits.
Block Diagram
Schematic
Code
/* @file dialaphone.pde || @version 4.0 || @author Bhairavi Chandersekhar || @contact bhairavi.chand@gmail.com || || @description || plays a song corresponding to a specific person when their telephone number is dialed. || # */ #include <Keypad.h> #include <SPI.h> #include <Adafruit_VS1053.h> #include <SD.h> // These are the pins used for the music maker shield #define SHIELD_RESET -1 // VS1053 reset pin (unused!) #define SHIELD_CS 7 // VS1053 chip select pin (output) #define SHIELD_DCS 6 // VS1053 Data/command select pin (output) // These are common pins between breakout and shield #define CARDCS 4 // Card chip select pin // DREQ should be an Int pin, see http://arduino.cc/en/Reference/attachInterrupt #define DREQ 3 // VS1053 Data request, ideally an Interrupt pin const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = { {'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'} }; //R3, R2, C1, R1, C3, R4, C2 byte rowPins[ROWS] = {A0, A2, 2, 8}; //connect to the row pinouts of the keypad byte colPins[COLS] = {A1, 9, 5}; //connect to the column pinouts of the keypad Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS); String phone_number; int digits_entered = 0; void setup(){ Serial.begin(9600); //Serial.println("setting up!"); // Music player setup if (! musicPlayer.begin()) { // initialise the music player Serial.println(F("Couldn't find VS1053, do you have the right pins defined?")); while (1); } Serial.println(F("VS1053 found")); if (!SD.begin(CARDCS)) { Serial.println(F("SD failed, or not present")); while (1); // don't do anything more } /* // list files Serial.println("should be listing files..."); printDirectory(SD.open("/"), 0); */ // Set volume for left, right channels.c lower numbers == louder volume! musicPlayer.setVolume(30,30); //#2 and #3 are the interrupt pins musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int phone_number = ""; digits_entered = 0; } void loop(){ Serial.println("Start typing phone number"); while (digits_entered < 12) { char key = keypad.getKey(); bool paused = musicPlayer.paused(); if (key == '*' && !paused) { musicPlayer.stopPlaying(); } else if (key) { musicPlayer.playFullFile("/beep____.mp3"); phone_number += key; Serial.print(key); digits_entered++; } if (digits_entered == 3 || digits_entered == 7) { //delay(10); phone_number += '-'; Serial.print('-'); digits_entered++; } } //Serial.println("phone number: "); //Serial.println(phone_number); Serial.print('\n'); //delay(200); if (phone_number == "617-775-4908") { Serial.println("CALEB"); //delay(700); musicPlayer.startPlayingFile("/caleb___.mp3"); //delay(700); Serial.println("tinyurl.com/care2pet"); Serial.println("and then some Carmen Sandiego"); } else if (phone_number == "617-669-3380") { Serial.println("JOHN"); //delay(700); musicPlayer.startPlayingFile("/john____.mp3"); //delay(700); //Serial.println("go watch forged in fire"); //delay(700); //Serial.println("an episode with will willis"); //delay(700); Serial.println("tinyurl.com/surprisedog"); } else if (phone_number == "603-233-4056") { Serial.println("MOM"); //delay(700); musicPlayer.startPlayingFile("/mom_____.mp3"); //delay("700"); Serial.println("make yourself some ginger tea!"); //delay("700"); Serial.println("or maybe with mint?"); } else if (phone_number == "555-555-5555") { Serial.println("PATI"); //delay(700); musicPlayer.startPlayingFile("/pati____.mp3"); //delay("700"); Serial.println("maybe it's finally time to learn crochet?"); } else if (phone_number == "111-111-1111") { Serial.println("Lorde"); //delay(700); musicPlayer.startPlayingFile("/track002.mp3"); } else if (phone_number == "222-222-2222") { Serial.println("the Beatles"); //delay(700); musicPlayer.startPlayingFile("/track001.mp3"); } else { Serial.println("Phone number not found"); } digits_entered = 0; phone_number = ""; } /* /// File listing helper void printDirectory(File dir, int numTabs) { Serial.println("should be printing files"); while(true) { File entry = dir.openNextFile(); if (! entry) { // no more files Serial.println("**nomorefiles**"); break; } for (uint8_t i=0; i<numTabs; i++) { Serial.print('\t'); } Serial.print(entry.name()); if (entry.isDirectory()) { Serial.println("/"); printDirectory(entry, numTabs+1); } else { // files have sizes, directories do not Serial.print("\t\t"); Serial.println(entry.size(), DEC); } entry.close(); } } */