MP3 Player

Hello! My name is Jesse W, I am an upcoming senior at Churchill School. My main project at BlueStamp, is the MP3 player, which is a device that plays music.

Engineer

Jesse W

Area of Interest

Game Design

School

Churchill School and Center

Grade

Incoming Senior

Reflection

Hello, I am Jesse, and I’m an upcoming senior at Churchill. During my time at BlueStamp, I had a great time. Before going in, I had no knowledge of anything regarding computer engineering, but with enough help I was  able to get a lot of stuff done easily. I never thought that I would be very interested in computer engineering. This program really helped in peaking my interest in this topic.

Final Milestone

My main project for BlueStamp is the MP3 player. My first milestone is getting my MP3 player to play music to my headphones. At first when I got all the pieces out of the box, I had absolutely no idea what to do. Eventually, with a ton of help from others, I was able to consistently play MP3 files without any hiccups or crashes. When I opened the box with all of the pieces, there was not a link to any kind of guide on what to do. I had to look up instructions on the internet and go to the Sparkfun website, which is where the parts came. When there, I finally found the proper guide to building the MP3 player. Since the parts arrived with almost everything already soldered on, I had to connect the Arduino with the MP3 shield. At first, I thought I had to put the MP3 shield on top of the Arduino, but I realized connecting with wires worked as well. Then, I had to connect the MP3 shield to a breadboard to prototype and provide power. The next step was to find nine songs to put on the SD card. After getting the songs, I then had to find good example code for the Arduino and put it into the program on my laptop. This was quite a challenge because not only did I have to search and then download a library for the code, but the guide did not  have proper code for the Arduino that I used. The way this works, is that the code recognizes the songs when they are named, Track001-Track009. Once the program is running, you open the command window (or serial monitor) then you press 1-9 on your keyboard to tell the code to play the song with the corresponding number in its name. You can also use other keys such as the arrows, plus and minus signs and other letters to do other commands such as pausing the song, lowering and raising the volume and to speed up or slow down the song. It took a bit to get used to, but once I was able to get music to play, and getting jump-scared by the loud volume, I had finally completed my first milestone.

See Code

//#include <SD.h>
#include <SPI.h>

//Add the SdFat Libraries
#include <SdFat.h>
#include <FreeStack.h>

//and the MP3 Shield Library
#include <SFEMP3Shield.h>

// Below is not needed if interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_Timer1
#include <TimerOne.h>
#elif defined(USE_MP3_REFILL_MEANS) && USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer
#include <SimpleTimer.h>
#endif

SdFat sd;

SFEMP3Shield MP3player;
int16_t last_ms_char; // milliseconds of last recieved character from Serial port.
int8_t buffer_pos; // next position to recieve character from Serial port.

char buffer[6]; // 0-35K+null

void setup() {

uint8_t result; //result code from some function as to be tested at later time.

Serial.begin(115200);

Serial.print(F(“F_CPU = “));
Serial.println(F_CPU);
Serial.print(F(“Free RAM = “)); // available in Version 1.0 F() bases the string to into Flash, to use less SRAM.
Serial.print(FreeStack(), DEC); // FreeRam() is provided by SdFatUtil.h
Serial.println(F(” Should be a base line of 1017, on ATmega328 when using INTx”));

//Initialize the SdCard.
if(!sd.begin(SD_SEL, SPI_FULL_SPEED)) sd.initErrorHalt();
// depending upon your SdCard environment, SPI_HAVE_SPEED may work better.
if(!sd.chdir(“/”)) sd.errorHalt(“sd.chdir”);

//Initialize the MP3 Player Shield
result = MP3player.begin();
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to start MP3 player”));
if( result == 6 ) {
Serial.println(F(“Warning: patch file not found, skipping.”)); // can be removed for space, if needed.
Serial.println(F(“Use the \”d\” command to verify SdCard can be read”)); // can be removed for space, if needed.
}
}

#if (0)
// Typically not used by most shields, hence commented out.
Serial.println(F(“Applying ADMixer patch.”));
if(MP3player.ADMixerLoad(“admxster.053”) == 0) {
Serial.println(F(“Setting ADMixer Volume.”));
MP3player.ADMixerVol(-3);
}
#endif

help();
last_ms_char = millis(); // stroke the inter character timeout.
buffer_pos = 0; // start the command string at zero length.
parse_menu(‘l’); // display the list of files to play

}

void loop() {

// Below is only needed if not interrupt driven. Safe to remove if not using.
#if defined(USE_MP3_REFILL_MEANS) \
&& ( (USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer) \
|| (USE_MP3_REFILL_MEANS == USE_MP3_Polled) )

MP3player.available();
#endif

char inByte;
if (Serial.available() > 0) {
inByte = Serial.read();
if ((0x20 <= inByte) && (inByte <= 0x126)) { // strip off non-ASCII, such as CR or LF
if (isDigit(inByte)) { // macro for ((inByte >= ‘0’) && (inByte <= ‘9’))
// else if it is a number, add it to the string
buffer[buffer_pos++] = inByte;
} else {
// input char is a letter command
buffer_pos = 0;
parse_menu(inByte);
}
buffer[buffer_pos] = 0; // update end of line
last_ms_char = millis(); // stroke the inter character timeout.
}
} else if ((millis() – last_ms_char) > 500 && ( buffer_pos > 0 )) {
// ICT expired and have something
if (buffer_pos == 1) {
// look for single byte (non-number) menu commands
parse_menu(buffer[buffer_pos – 1]);

} else if (buffer_pos > 5) {
// dump if entered command is greater then uint16_t
Serial.println(F(“Ignored, Number is Too Big!”));

} else {
// otherwise its a number, scan through files looking for matching index.
int16_t fn_index = atoi(buffer);
SdFile file;
char filename[13];
sd.chdir(“/”,true);
uint16_t count = 1;
while (file.openNext(sd.vwd(),O_READ))
{
file.getName(filename, sizeof(filename));
if ( isFnMusic(filename) ) {

if (count == fn_index) {
Serial.print(F(“Index “));
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(“: “));
Serial.println(filename);
Serial.print(F(“Playing filename: “));
Serial.println(filename);
int8_t result = MP3player.playMP3(filename);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to play track”));
}
char title[30]; // buffer to contain the extract the Title from the current filehandles
char artist[30]; // buffer to contain the extract the artist name from the current filehandles
char album[30]; // buffer to contain the extract the album name from the current filehandles
MP3player.trackTitle((char*)&title);
MP3player.trackArtist((char*)&artist);
MP3player.trackAlbum((char*)&album);

//print out the arrays of track information
Serial.write((byte*)&title, 30);
Serial.println();
Serial.print(F(“by: “));
Serial.write((byte*)&artist, 30);
Serial.println();
Serial.print(F(“Album: “));
Serial.write((byte*)&album, 30);
Serial.println();
break;
}
count++;
}
file.close();
}

}

//reset buffer to start over
buffer_pos = 0;
buffer[buffer_pos] = 0; // delimit
}

delay(100);
}

uint32_t millis_prv;

void parse_menu(byte key_command) {

uint8_t result; // result code from some function as to be tested at later time.

// Note these buffer may be desired to exist globably.
// but do take much space if only needed temporarily, hence they are here.
char title[30]; // buffer to contain the extract the Title from the current filehandles
char artist[30]; // buffer to contain the extract the artist name from the current filehandles
char album[30]; // buffer to contain the extract the album name from the current filehandles

Serial.print(F(“Received command: “));
Serial.write(key_command);
Serial.println(F(” “));

//if s, stop the current track
if(key_command == ‘s’) {
Serial.println(F(“Stopping”));
MP3player.stopTrack();

//if 1-9, play corresponding track
} else if(key_command >= ‘1’ && key_command <= ‘9’) {
//convert ascii numbers to real numbers
key_command = key_command – 48;

#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard’s volume.
#endif
//tell the MP3 Shield to play a track
result = MP3player.playTrack(key_command);

//check result, see readme for error codes.
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to play track”));
} else {

Serial.println(F(“Playing:”));

//we can get track info by using the following functions and arguments
//the functions will extract the requested information, and put it in the array we pass in
MP3player.trackTitle((char*)&title);
MP3player.trackArtist((char*)&artist);
MP3player.trackAlbum((char*)&album);

//print out the arrays of track information
Serial.write((byte*)&title, 30);
Serial.println();
Serial.print(F(“by: “));
Serial.write((byte*)&artist, 30);
Serial.println();
Serial.print(F(“Album: “));
Serial.write((byte*)&album, 30);
Serial.println();
}

//if +/- to change volume
} else if((key_command == ‘-‘) || (key_command == ‘+’)) {
union twobyte mp3_vol; // create key_command existing variable that can be both word and double byte of left and right.
mp3_vol.word = MP3player.getVolume(); // returns a double uint8_t of Left and Right packed into int16_t

if(key_command == ‘-‘) { // note dB is negative
// assume equal balance and use byte[1] for math
if(mp3_vol.byte[1] >= 254) { // range check
mp3_vol.byte[1] = 254;
} else {
mp3_vol.byte[1] += 2; // keep it simpler with whole dB’s
}
} else {
if(mp3_vol.byte[1] <= 2) { // range check
mp3_vol.byte[1] = 2;
} else {
mp3_vol.byte[1] -= 2;
}
}
// push byte[1] into both left and right assuming equal balance.
MP3player.setVolume(mp3_vol.byte[1], mp3_vol.byte[1]); // commit new volume
Serial.print(F(“Volume changed to -“));
Serial.print(mp3_vol.byte[1]>>1, 1);
Serial.println(F(“[dB]”));

//if < or > to change Play Speed
} else if((key_command == ‘>’) || (key_command == ‘<‘)) {
uint16_t playspeed = MP3player.getPlaySpeed(); // create key_command existing variable
// note playspeed of Zero is equal to ONE, normal speed.

if(key_command == ‘>’) { // note dB is negative
// assume equal balance and use byte[1] for math
if(playspeed >= 254) { // range check
playspeed = 5;
} else {
playspeed += 1; // keep it simpler with whole dB’s
}
} else {
if(playspeed == 0) { // range check
playspeed = 0;
} else {
playspeed -= 1;
}
}
MP3player.setPlaySpeed(playspeed); // commit new playspeed
Serial.print(F(“playspeed to “));
Serial.println(playspeed, DEC);

} else if(key_command == ‘f’ || key_command == ‘F’) {
uint32_t offset = 0;
if (key_command == ‘F’) {
offset = 2000;
}

//create a string with the filename
char trackName[] = “track001.mp3”;

#if USE_MULTIPLE_CARDS
sd.chvol(); // assign desired sdcard’s volume.
#endif
//tell the MP3 Shield to play that file
result = MP3player.playMP3(trackName, offset);
//check result, see readme for error codes.
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to play track”));
}

/* Display the file on the SdCard */
} else if(key_command == ‘d’) {
if(!MP3player.isPlaying()) {
// prevent root.ls when playing, something locks the dump. but keeps playing.
// yes, I have tried another unique instance with same results.
// something about SdFat and its 500byte cache.
Serial.println(F(“Files found (name date time size):”));
sd.ls(LS_R | LS_DATE | LS_SIZE);
} else {
Serial.println(F(“Busy Playing Files, try again later.”));
}

/* Get and Display the Audio Information */
} else if(key_command == ‘i’) {
MP3player.getAudioInfo();

} else if(key_command == ‘p’) {
if( MP3player.getState() == playback) {
MP3player.pauseMusic();
Serial.println(F(“Pausing”));
} else if( MP3player.getState() == paused_playback) {
MP3player.resumeMusic();
Serial.println(F(“Resuming”));
} else {
Serial.println(F(“Not Playing!”));
}

} else if(key_command == ‘t’) {
int8_t teststate = MP3player.enableTestSineWave(126);
if(teststate == -1) {
Serial.println(F(“Un-Available while playing music or chip in reset.”));
} else if(teststate == 1) {
Serial.println(F(“Enabling Test Sine Wave”));
} else if(teststate == 2) {
MP3player.disableTestSineWave();
Serial.println(F(“Disabling Test Sine Wave”));
}

} else if(key_command == ‘S’) {
Serial.println(F(“Current State of VS10xx is.”));
Serial.print(F(“isPlaying() = “));
Serial.println(MP3player.isPlaying());

Serial.print(F(“getState() = “));
switch (MP3player.getState()) {
case uninitialized:
Serial.print(F(“uninitialized”));
break;
case initialized:
Serial.print(F(“initialized”));
break;
case deactivated:
Serial.print(F(“deactivated”));
break;
case loading:
Serial.print(F(“loading”));
break;
case ready:
Serial.print(F(“ready”));
break;
case playback:
Serial.print(F(“playback”));
break;
case paused_playback:
Serial.print(F(“paused_playback”));
break;
case testing_memory:
Serial.print(F(“testing_memory”));
break;
case testing_sinewave:
Serial.print(F(“testing_sinewave”));
break;
}
Serial.println();

} else if(key_command == ‘b’) {
Serial.println(F(“Playing Static MIDI file.”));
MP3player.SendSingleMIDInote();
Serial.println(F(“Ended Static MIDI file.”));

#if !defined(__AVR_ATmega32U4__)
} else if(key_command == ‘m’) {
uint16_t teststate = MP3player.memoryTest();
if(teststate == -1) {
Serial.println(F(“Un-Available while playing music or chip in reset.”));
} else if(teststate == 2) {
teststate = MP3player.disableTestSineWave();
Serial.println(F(“Un-Available while Sine Wave Test”));
} else {
Serial.print(F(“Memory Test Results = “));
Serial.println(teststate, HEX);
Serial.println(F(“Result should be 0x83FF.”));
Serial.println(F(“Reset is needed to recover to normal operation”));
}

} else if(key_command == ‘e’) {
uint8_t earspeaker = MP3player.getEarSpeaker();
if(earspeaker >= 3){
earspeaker = 0;
} else {
earspeaker++;
}
MP3player.setEarSpeaker(earspeaker); // commit new earspeaker
Serial.print(F(“earspeaker to “));
Serial.println(earspeaker, DEC);

} else if(key_command == ‘r’) {
MP3player.resumeMusic(2000);

} else if(key_command == ‘R’) {
MP3player.stopTrack();
MP3player.vs_init();
Serial.println(F(“Reseting VS10xx chip”));

} else if(key_command == ‘g’) {
int32_t offset_ms = 20000; // Note this is just an example, try your own number.
Serial.print(F(“jumping to “));
Serial.print(offset_ms, DEC);
Serial.println(F(“[milliseconds]”));
result = MP3player.skipTo(offset_ms);
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to skip track”));
}

} else if(key_command == ‘k’) {
int32_t offset_ms = -1000; // Note this is just an example, try your own number.
Serial.print(F(“moving = “));
Serial.print(offset_ms, DEC);
Serial.println(F(“[milliseconds]”));
result = MP3player.skip(offset_ms);
if(result != 0) {
Serial.print(F(“Error code: “));
Serial.print(result);
Serial.println(F(” when trying to skip track”));
}

} else if(key_command == ‘O’) {
MP3player.end();
Serial.println(F(“VS10xx placed into low power reset mode.”));

} else if(key_command == ‘o’) {
MP3player.begin();
Serial.println(F(“VS10xx restored from low power reset mode.”));

} else if(key_command == ‘D’) {
uint16_t diff_state = MP3player.getDifferentialOutput();
Serial.print(F(“Differential Mode “));
if(diff_state == 0) {
MP3player.setDifferentialOutput(1);
Serial.println(F(“Enabled.”));
} else {
MP3player.setDifferentialOutput(0);
Serial.println(F(“Disabled.”));
}

} else if(key_command == ‘V’) {
MP3player.setVUmeter(1);
Serial.println(F(“Use \”No line ending\””));
Serial.print(F(“VU meter = “));
Serial.println(MP3player.getVUmeter());
Serial.println(F(“Hit Any key to stop.”));

while(!Serial.available()) {
union twobyte vu;
vu.word = MP3player.getVUlevel();
Serial.print(F(“VU: L = “));
Serial.print(vu.byte[1]);
Serial.print(F(” / R = “));
Serial.print(vu.byte[0]);
Serial.println(” dB”);
delay(1000);
}
Serial.read();

MP3player.setVUmeter(0);
Serial.print(F(“VU meter = “));
Serial.println(MP3player.getVUmeter());

} else if(key_command == ‘T’) {
uint16_t TrebleFrequency = MP3player.getTrebleFrequency();
Serial.print(F(“Former TrebleFrequency = “));
Serial.println(TrebleFrequency, DEC);
if (TrebleFrequency >= 15000) { // Range is from 0 – 1500Hz
TrebleFrequency = 0;
} else {
TrebleFrequency += 1000;
}
MP3player.setTrebleFrequency(TrebleFrequency);
Serial.print(F(“New TrebleFrequency = “));
Serial.println(MP3player.getTrebleFrequency(), DEC);

} else if(key_command == ‘E’) {
int8_t TrebleAmplitude = MP3player.getTrebleAmplitude();
Serial.print(F(“Former TrebleAmplitude = “));
Serial.println(TrebleAmplitude, DEC);
if (TrebleAmplitude >= 7) { // Range is from -8 – 7dB
TrebleAmplitude = -8;
} else {
TrebleAmplitude++;
}
MP3player.setTrebleAmplitude(TrebleAmplitude);
Serial.print(F(“New TrebleAmplitude = “));
Serial.println(MP3player.getTrebleAmplitude(), DEC);

} else if(key_command == ‘B’) {
uint16_t BassFrequency = MP3player.getBassFrequency();
Serial.print(F(“Former BassFrequency = “));
Serial.println(BassFrequency, DEC);
if (BassFrequency >= 150) { // Range is from 20hz – 150hz
BassFrequency = 0;
} else {
BassFrequency += 10;
}
MP3player.setBassFrequency(BassFrequency);
Serial.print(F(“New BassFrequency = “));
Serial.println(MP3player.getBassFrequency(), DEC);

} else if(key_command == ‘C’) {
uint16_t BassAmplitude = MP3player.getBassAmplitude();
Serial.print(F(“Former BassAmplitude = “));
Serial.println(BassAmplitude, DEC);
if (BassAmplitude >= 15) { // Range is from 0 – 15dB
BassAmplitude = 0;
} else {
BassAmplitude++;
}
MP3player.setBassAmplitude(BassAmplitude);
Serial.print(F(“New BassAmplitude = “));
Serial.println(MP3player.getBassAmplitude(), DEC);

} else if(key_command == ‘M’) {
uint16_t monostate = MP3player.getMonoMode();
Serial.print(F(“Mono Mode “));
if(monostate == 0) {
MP3player.setMonoMode(1);
Serial.println(F(“Enabled.”));
} else {
MP3player.setMonoMode(0);
Serial.println(F(“Disabled.”));
}
#endif

} else if(key_command == ‘l’) {
if(!MP3player.isPlaying()) {
Serial.println(F(“Music Files found :”));
SdFile file;
char filename[13];
sd.chdir(“/”,true);
uint16_t count = 1;
while (file.openNext(sd.vwd(),O_READ))
{
file.getName(filename, sizeof(filename));
if ( isFnMusic(filename) ) {
SerialPrintPaddedNumber(count, 5 );
Serial.print(F(“: “));
Serial.println(filename);
count++;
}
file.close();
}
Serial.println(F(“Enter Index of File to play”));

} else {
Serial.println(F(“Busy Playing Files, try again later.”));
}

} else if(key_command == ‘h’) {
help();
}

// print prompt after key stroke has been processed.
Serial.print(F(“Time since last command: “));
Serial.println((float) (millis() – millis_prv)/1000, 2);
millis_prv = millis();
Serial.print(F(“Enter s,1-9,+,-,>,<,f,F,d,i,p,t,S,b”));
#if !defined(__AVR_ATmega32U4__)
Serial.print(F(“,m,e,r,R,g,k,O,o,D,V,B,C,T,E,M:”));
#endif
Serial.println(F(“,l,h :”));
}
void help() {
Serial.println(F(“Arduino SFEMP3Shield Library Example:”));
Serial.println(F(” courtesy of Bill Porter & Michael P. Flaga”));
Serial.println(F(“COMMANDS:”));
Serial.println(F(” [1-9] to play a track”));
Serial.println(F(” [f] play track001.mp3 by filename example”));
Serial.println(F(” [F] same as [f] but with initial skip of 2 second”));
Serial.println(F(” [s] to stop playing”));
Serial.println(F(” [d] display directory of SdCard”));
Serial.println(F(” [+ or -] to change volume”));
Serial.println(F(” [> or <] to increment or decrement play speed by 1 factor”));
Serial.println(F(” [i] retrieve current audio information (partial list)”));
Serial.println(F(” [p] to pause.”));
Serial.println(F(” [t] to toggle sine wave test”));
Serial.println(F(” [S] Show State of Device.”));
Serial.println(F(” [b] Play a MIDI File Beep”));
#if !defined(__AVR_ATmega32U4__)
Serial.println(F(” [e] increment Spatial EarSpeaker, default is 0, wraps after 4″));
Serial.println(F(” [m] perform memory test. reset is needed after to recover.”));
Serial.println(F(” [M] Toggle between Mono and Stereo Output.”));
Serial.println(F(” [g] Skip to a predetermined offset of ms in current track.”));
Serial.println(F(” [k] Skip a predetermined number of ms in current track.”));
Serial.println(F(”

[r] resumes play from 2s from begin of file”));
Serial.println(F(” [R] Resets and initializes VS10xx chip.”));
Serial.println(F(” [O] turns OFF the VS10xx into low power reset.”));
Serial.println(F(” [o] turns ON the VS10xx out of low power reset.”));
Serial.println(F(” [D] to toggle SM_DIFF between inphase and differential output”));
Serial.println(F(” [V] Enable VU meter Test.”));
Serial.println(F(” [B] Increament bass frequency by 10Hz”));
Serial.println(F(” [C] Increament bass amplitude by 1dB”));
Serial.println(F(” [T] Increament treble frequency by 1000Hz”));
Serial.println(F(” [E] Increament treble amplitude by 1dB”));
#endif
Serial.println(F(” [l] Display list of music files”));
Serial.println(F(” [0####] Enter index of file to play, zero pad! e.g. 01-65534″));
Serial.println(F(” [h] this help”));
}

void SerialPrintPaddedNumber(int16_t value, int8_t digits ) {
int currentMax = 10;
for (byte i=1; i<digits; i++){
if (value < currentMax) {
Serial.print(“0”);
}
currentMax *= 10;
}
Serial.print(value);
}

TV-B-Gone

For my starter project at BlueStamp, I decided to make a TV-B-Gone. I made it with the following: a circuit board, a AA battery holder, a 6 pin header which holds the IC chip, a couple of NPN transistors, a PNP transistor, a 6mm tact switch button, some LEDs, a couple of resistors, some capacitors, a ceramic oscillator and a microcontroller.I used soldering iron to connect everything to the board. The IC chip operates as the brain of the project, deciding which components to active and when. The oscillator determines the timing  of the entire system. The purpose of the capacitor is to keep the negative and positive charges away to store the energy between them. Capacitors store electrical energy in the form of charge in order to release at the right and stabilize voltage outputs. The purpose of the resistor is limit the current of the circuit. The resistors are utilized so no electrical component in the circuit is ever supplied too much current. The switch button is used to turn the power on and off. The transistor is used to change the flow of the current. This is a kind of TV remote that works very differently than the ones you will normally find in someone’s living room. Those remotes only work for only one TV but have many different functions like changing the volume and channel. However, a TV-B-Gone only has one function, which is turning on and off the power. It does this task by sending out IR from the LEDs on the back of the circuit. This can be more useful than it seems at first, as it can work with almost any TV model. When working on my project, I did run into a couple of issues. First, I put too much into  the holes for the AA battery pack to the point where it was completely covered up. I had to get a little creative in order to solve the issue. Instead of trying to get rid of the solder, a rather tedious process, I decided to solder the wire onto the already existing solder that was covering the hole. Another issue I encountered was that I cut the wire on the AA battery pack way too short. The wire could not fit into the circuit board. The solution to this was to use a different AA battery pack. Doing this project taught me many things. I learned how to solder and how to remove solder, a skill which is very important to know when doing computer engineering. I learned how to be a better problem solver for the many mistakes I made. And lastly, I learned what all of the components for my project do, and how they help in functioning the device.

Leave a Comment

Start typing and press Enter to search