ECE 4180 Final Project

Dependencies:   mbed wave_player 4DGL-uLCD-SE SDFileSystem_OldbutworkswithRTOS PinDetect

Portable Surface Transducer Jukebox

ECE 4180 Final Project

Team members

  • Bruna Correa
  • Lance Hudson
  • Javier Rodriguez

Jukebox Overview

This unique jukebox uses a surface transducer to essentially turn any hard surface (table, etc) into a resonant speaker. The user has the option to select one of out ten songs which were preselected and loaded onto the SD card. To begin, the user types their song choice into the keypad and is prompted to press “START” to begin the song. The user can end the song at any time by pressing “STOP,” which will redirect them back to the original selection menu.

Parts Required

  • 1x Mbed (LPC1768)

Mbed

  • 1x MicroSD card breakout (Sparkfun)

MicroSD Breakout

  • 1x Class D Amp (Sparkfun TPA2005)

Class D Amp

  • 1x Surface conduction transducer speaker (Generic)

Surface Transducer

  • 1x Breadboard speaker

Speaker

  • 2x standard pushbuttons

Pushbutton

  • 1x uLCD (Sparkfun 4DGL)

uLCD Screen

  • 1x Touch capacitance keypad (Sparkfun MPR121)

Touch Pad

  • 2x 6-volt breadboard battery packs

Battery Pack

  • 1x Standard 8x4x4 project box

Project Box

Design Challenges and Tradeoffs

One of the major challenges experienced when developing the Jukebox user interface was the synchronous playback function of the music. This required several instances of interrupt handling and pin detects. More specifically, regarding the “STOP” button, we realized that it was initially not possible to perform any pushbutton polling while the waveplayer function play() is active; if the “STOP” button was pressed while a song is playing, it would only be recognized when the song was finished. Therefore, we looked into editing the waveplayer library itself by passing an extern bool named “play” that was switched to true when “START” is pressed and false when “STOP” is pressed. Inside the play() function we added a logical check to ensure that this play variable is true, and if switched to false, it immediately breaks from the loop, thereby stopping the playback.

Several design tradeoffs had to be made for the benefit of portability. For example, we chose to not implement the original RGB LED strip because it added too much weight and occupied too much space inside the housing for the portable implementation desired. We believe that portability was a more valuable feature for the end user than an LED light show.

Schematic

The schematic used is shown below. For more detailed information on connection declarations and classifications in the software, refer to the code repository.

/media/uploads/jrod1096/schematic.jpeg

Demonstration Video

main.cpp

Committer:
jrod1096
Date:
2018-12-12
Revision:
3:74066405c9fc
Parent:
2:c2afd0c426af

File content as of revision 3:74066405c9fc:


#include "mbed.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "uLCD_4DGL.h"
#include "mpr121.h"
#include "PinDetect.h"
#include <string>
#include <list>

DigitalOut led1(LED1);
InterruptIn interrupt(p26);
InterruptIn start(p12);
PinDetect stop(p13);

SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
uLCD_4DGL uLCD(p9, p10, p11);
Serial pc(USBTX, USBRX);  
                                                                                                                                                               

// Speaker and Class D
AnalogOut speaker(p18);
wave_player waver(&speaker);

// Keypad
I2C i2c(p28, p27);
Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);

int keypad = 0;
string title;
int title_size;
string artist;
int artist_size;


bool newKey = false;
bool play = false;
bool reset = false;

void key () {
    
    newKey = true;
    
}

void b1 () {
    
    if (keypad != 0) {
        play = true;
    }
    
}


void update_screen(int index) {
    
    if (index == 1) { // MENU SCREEN
    
            uLCD.cls();
    
            // Draw border
            uLCD.filled_circle(0,0,10,AQUA);   
            uLCD.filled_circle(0,128,10,AQUA);   
            uLCD.filled_circle(128,0,10,AQUA);   
            uLCD.filled_circle(128,128,10,AQUA);   
            uLCD.filled_rectangle(0,0,128,3,AQUA);   
            uLCD.filled_rectangle(124,0,128,128,AQUA);  
            uLCD.filled_rectangle(0,0,3,128,AQUA);  
            uLCD.filled_rectangle(0,125,128,128,AQUA);  

            // Print title
            uLCD.color(AQUA);
            uLCD.text_width(2.5);
            uLCD.text_height(2.5);
            uLCD.locate(1,1);
            uLCD.printf("JUKEBOX");
 
            // Print menu information
            uLCD.color(TEAL);           
            uLCD.text_width(1);
            uLCD.text_height(1);
            uLCD.locate(3,5);
            uLCD.printf("  Welcome!\r\n");
            uLCD.locate(2,6);
            uLCD.printf("Please make a \r\n");
            uLCD.locate(2,7);
            uLCD.printf("song selection.\r\n");            
            uLCD.locate(1,9);
            uLCD.printf(" Then hit PLAY!\r\n"); 
            uLCD.filled_rectangle(15,90,114,90, GREEN);
            uLCD.filled_rectangle(15,110,114,110, GREEN);            
            uLCD.filled_rectangle(15,90,15,110, GREEN);
            uLCD.filled_rectangle(114,90,114,110, GREEN);  
                       
    } else if (index == 2) { // SONG CHOICE 

            // Print KEYPAD selection
            uLCD.text_width(1);
            uLCD.text_height(1);
            uLCD.locate(6,12);
            uLCD.color(GREEN);
            if (keypad > 0) {
                if (keypad < 10) {
                     uLCD.printf("Song 0%i\r\n",keypad);   
                } else {
                    uLCD.printf("Song %i\r\n",keypad);
                }
            }
            
    } else if (index == 3) { // NOW PLAYING

            uLCD.cls();
            
            // Draw border
            uLCD.filled_circle(0,0,10,AQUA);   
            uLCD.filled_circle(0,128,10,AQUA);   
            uLCD.filled_circle(128,0,10,AQUA);   
            uLCD.filled_circle(128,128,10,AQUA);   
            uLCD.filled_rectangle(0,0,128,3,AQUA);   
            uLCD.filled_rectangle(124,0,128,128,AQUA);  
            uLCD.filled_rectangle(0,0,3,128,AQUA);  
            uLCD.filled_rectangle(0,125,128,128,AQUA);             
   
            // Print NOW PLAYING     
            uLCD.color(AQUA);
            uLCD.locate(1,2);
            uLCD.text_width(1);
            uLCD.text_height(1); 
            uLCD.printf("  Now playing..."); 
            uLCD.color(GREEN);
            uLCD.text_width(1);
            uLCD.text_height(1);
            uLCD.locate(1,5); 
            uLCD.printf("%s\r\n",title);    // song title
            uLCD.locate(1,7); 
            uLCD.printf("%s\r\n",artist);
            uLCD.filled_rectangle(15,35,114,35, GREEN);
            uLCD.filled_rectangle(15,67,114,67, GREEN);            
            uLCD.filled_rectangle(15,35,15,67, GREEN);
            uLCD.filled_rectangle(114,35,114,67, GREEN);            


            // MUSIC SYMBOL #1           
            uLCD.filled_rectangle(30,76,45,78, BLUE);
            uLCD.filled_rectangle(30,76,32,91,BLUE);
            uLCD.filled_rectangle(43,76,45,91,BLUE);
            uLCD.filled_circle(29,91,3,BLUE);
            uLCD.filled_circle(42,91,3,BLUE);                
            
            
            // MUSIC SYMBOL #2             
            uLCD.filled_rectangle(58,84,73,86,PURPLE);
            uLCD.filled_rectangle(58,84,60,99,PURPLE);
            uLCD.filled_rectangle(71,84,73,99,PURPLE);
            uLCD.filled_circle(56,99,3,PURPLE);
            uLCD.filled_circle(70,99,3,PURPLE);        
            
            // MUSIC SYMBOL #3            
            uLCD.filled_rectangle(87,76,102,78, PINK);
            uLCD.filled_rectangle(87,76,89,91,PINK);
            uLCD.filled_rectangle(100,76,102,91,PINK);
            uLCD.filled_circle(86,91,3,PINK);
            uLCD.filled_circle(99,91,3,PINK);   
            
            
 
            // Print STOP message
            uLCD.color(RED);           
            uLCD.text_width(1.0);
            uLCD.text_height(1.0);       
            uLCD.locate(1,14);
            uLCD.printf(" Hit STOP to end");
            
        }
    
}

void get_song() {

    // Read value
    int value=mpr121.read(0x00);
    value +=mpr121.read(0x01)<<8;
 
    // Match keypad value to number   
    switch (value) {
        case 2:
            keypad = 1;
            break;
        case 4:
            keypad = 2;
            break;
        case 8:
            keypad = 3;
            break;
        case 16:
            keypad = 4;
            break;
        case 32:
            keypad = 5;
            break;
        case 64:
            keypad = 6;
            break;
        case 128:
            keypad = 7;
            break;
        case 256:
            keypad = 8;
            break;
        case 512:
            keypad = 9;
            break;
        case 1024:
            keypad = 10;
            break;
       }
             
       update_screen(2);

}


void play_song() {
    
    FILE *wave_file;
    switch (keypad) {
        case 1:
            wave_file=fopen("/sd/wavfiles/dura.wav","r");
            title = "      Dura";
            artist = "  Daddy Yankee";
            title_size = 1;
            artist_size = 1;
            break;
        case 2:
            wave_file=fopen("/sd/wavfiles/despacito.wav","r");
            title = "    Despacito";
            artist = "    Luis Fonsi";
            title_size = 1;
            artist_size = 1;
            break;
        case 3:
            wave_file=fopen("/sd/wavfiles/disco.wav","r");
            title = "      Disco";
            artist = "  Maxine Night";
            title_size = 1;
            artist_size = 1;
            break;
        case 4:
            wave_file=fopen("/sd/wavfiles/california.wav","r");
            title = "   California";
            artist = "     Phantom  ";
            title_size = 1;
            artist_size = 1;
            break;
        case 5:
            wave_file=fopen("/sd/wavfiles/christmas.wav","r");
            title = "   All I Want";
            artist = "  Mariah Carey";
            title_size = 1;
            artist_size = 1;
            break;
        case 6:
            wave_file=fopen("/sd/wavfiles/beethoven.wav","r");
            title = "   Symphony 9";
            artist = "    Beethoven";
            title_size = 1;
            artist_size = 1;
            break;
        case 7:
            wave_file=fopen("/sd/wavfiles/queen.wav","r");
            title = "    Rock You";
            artist = "      Queen";
            title_size = 1;
            artist_size = 1;
            break;
        case 8:
            wave_file=fopen("/sd/wavfiles/losing_it.wav","r");
            title = "    Losing It";
            artist = "     Fisher";
            title_size = 1;
            artist_size = 1;
            break;
        case 9:
            wave_file=fopen("/sd/wavfiles/better_not.wav","r");
            title = "   Better Not";
            artist = "    Louis TC";
            title_size = 1;
            artist_size = 1;
            break;
        case 10:
            wave_file=fopen("/sd/wavfiles/drinkee.wav","r");
            title = "     Drinkee";
            artist = "   Sofi Tukker";
            title_size = 1;
            artist_size = 1;
            break;
       }
        update_screen(3);     
        waver.play(wave_file);      
        fclose(wave_file);

        

}


void stop_song() {
    
        play = false; 
        

}



int main(){
        
        
        interrupt.mode(PullUp);
        start.mode(PullUp);
        interrupt.fall(&key);
        start.fall(&b1);
        stop.mode(PullUp);
        wait_ms(10);
        stop.attach_deasserted(&stop_song);
        stop.setSampleFrequency();
        
        
        
        
        while(1) { // One jukebox cycle
        
            
            // Reset, draw menu screen
            keypad = 0;
            update_screen(1);
    
            // Wait for user to select song AND press play        
            while ((keypad == 0)||(play==false)) {
                if (newKey) {
                    newKey = false;
                    get_song();                  
                }
            }
    
            play_song();            

            // Reset values before starting again                
            play = false;
            newKey = false;
            keypad = 0;
            
            
            
        }

    
    
}