Bluetooth Music Box (4180 Final Project)

/media/uploads/nthawani3/4180.png

Overview

Final ECE 4180 project made by Scout Schultz and Neeta Thawani for Spring 2017. The music box is made to add to a mechanical process. Added functionality includes the ability to switch songs, pause/play/stop songs, reset to the first song, stop/start a figurine rotating, and change volume on command of a Bluetooth app.

Parts Required

https://a.pololu-files.com/picture/0J3125.1200.jpg?28bb58b9f86b823615475f062ba3ed2b

Mbed (Photo from pololu)

https://cdn.sparkfun.com//assets/parts/3/0/6/00544-02.jpg

SD Card (Photo from Sparkfun)

https://developer.mbed.org/media/uploads/4180_1/_scaled_classdbreakout.jpg

Audio Amplifier (Photo from Mbed)

https://developer.mbed.org/media/uploads/4180_1/speaker.jpg

Speaker (Photo from Mbed)

https://cdn.sparkfun.com//assets/parts/9/7/8/1/12889-01.jpg

External Power (Photo from Sparkfun)

https://cdn-shop.adafruit.com/1200x900/2479-01.jpg

Bluetooth (Photo from Adafruit)

https://ae01.alicdn.com/kf/HTB1fPY0LFXXXXccapXXq6xXFXXXH/Top-Quality-Sale-Price-50-pcs-a-Lot-font-b-Electrical-b-font-Accessories-Widely-Used.jpg

On/off switch (Photo from AllExpress)

/media/uploads/nthawani3/41802.png

Pint Outs

mbedAudio AmplifierSpeakerExternal Power
gndpwr-, in-
pwr+5V
p18in+
out++
out--
S
mbedSD CardExternal Power
14CS
11DI
VCC5V
13SCK
GNDGND
12DO
CD
mbedMOSFET ConnectormotorExternal power
GNDJP2-2 GND
JP2-1 RAW5V
P23JP2-3 Control
JP1-1Device(neg)
JP1-2Device(pos)
mbedBluetoothExternal Power
GNDCST
p10TXO
p9RXI
VIN5V
GNDGND
mbedOn/Off SwitchExternal Power
-GND
p22+

How It Works

When you open the box, the switch is released and the microcontroller starts playing music and spinning the dancer. The box will play the first song on the SD card and this song can be changed or paused using the Bluetooth LE control pad. If the song runs out, the box will begin playing the same song from the beginning. All of the songs are stored on the SD card, because there is ample space to put as many songs as you would like on the card. Songs should be in a .wav format and be sampled down in Audacity.

Bluetooth Module

https://cdn-learn.adafruit.com/assets/assets/000/023/221/medium800/projects_ControlPad.jpg?1424072838

(Photo from Adafruit)

We make use of the control pad on the Bluefruit LE app that can be downloaded to any smart phone. The control has eight buttons, a set of arrows and numbers 1 to 4.

Up arrow: Go up in volume.

Down arrow: Go down in volume.

Left arrow: Go back one song in vector.

Right arrow: Go to next song in vector.

'1': Play/pause song.

'2': Play/pause dancer while song is on.

'3': Stop song.

'4': Reset box song to first song.

How to Start Using Bluetooth

Turn on smart phone

Download the app from the app store (App is called Bluefruit LE)

Open the app and allow it to turn on your Bluetooth on your phone

Find your Bluetooth module. It should be called Adafruit Bluefruit LE

Click connect and choose the controller mode

Choose the control pad mode near the bottom of the list

You can now click button and control the music box

Code

Music Box Code

// Scout Schultz and Neeta Thawani
// ECE 4180 Final Project - BlueTooth Music Box
// Spring 2017

#include "mbed.h"
#include "rtos.h"
#include "SDFileSystem.h"
#include "wave_player.h"
//#include "uLCD_4DGL.h"
#include "PinDetect.h"
#include <vector>
#include <string>
#include "Motor.h"

//uLCD_4DGL uLCD(p28, p27, p29); // create a global lcd object

SDFileSystem sd(p11, p12, p13, p14, "sd"); //SD card
PwmOut Ctrl(p23);
AnalogOut DACout(p18);

wave_player waver(&DACout);

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

PinDetect lid(p22);

Serial pc(USBTX, USBRX); // tx, rx
Serial  blue(p9,p10);

volatile short paused = 0;
volatile short songnum = 0;
volatile short openLid = 0;
volatile short dancerEnable = 1;
string songname;
vector<string> songs;
float motorSpeed = 0.15f;
float volumeIncrement = 0.2;

//This function is for a thread that handles playing a song.
//Once the song ends, it will automatically play the song stored in songname
//(if songname is unchanged, it will just play the same song again and again)
void songThread(void const *argument)
{
    while(1) {
        FILE *wave_file;
        wave_file=fopen(songname.c_str(),"r");
        waver.play(wave_file);
        fclose(wave_file);
    }

}

void pauseSong()
{
    paused=1;
    Ctrl.write(0);
    waver.pause();
}

void resumeSong()
{
    paused=0;
    if(dancerEnable)
        Ctrl.write(motorSpeed);
    waver.resume();
}

void lidClosed()
{
    short tmp = paused; // preserve whether box was paused or not when opening
    pauseSong();
    openLid=0;
    paused = tmp;
}

void lidOpen()
{
    if(paused==0)
        resumeSong();
    openLid=1;
}

int main()
{
    //basic setup
    lid.mode(PullUp);
    wait(0.01);
    lid.attach_deasserted(&lidClosed);
    lid.attach_asserted(&lidOpen);
    lid.setSampleFrequency(50000); // 50 ms sample rate

    //Scan the directory for .wav files and build a vector of file names
    DIR *d;
    struct dirent *p;

    d = opendir("/sd");
    if (d != NULL) {
        while ((p = readdir(d)) != NULL) {
            //printf(" - %s\n", p->d_name);
            string fname = p->d_name;
            if(fname.find(".wav")!=string::npos) { // if it contains ".wav"
                //printf("%s\n\r",fname);
                songs.push_back("/sd/" + fname);
            }
        }
    } else {
        printf("Could not open directory!\n\r");
    }
    closedir(d);

    // Initialize a thread to handle playing the appropriate song
    songname = songs[0];
    Thread t1(songThread);
    // Check whether song should be playing or not at program start
    Thread::wait(50);
    if(lid==0)
        lidClosed();
    else //lid==0
        lidOpen();

    //Start the main loop, reading serial data from Bluetooth
    char bnum=0;
    while(1) {
        Thread::wait(100);
        led1= !led1;
        if(openLid==1) { //only perform actions if lid is open
            if (blue.getc()=='!' && openLid==1) { //Received a serial input
                if (blue.getc()=='B' && openLid==1) { //Received a button press
                    bnum = blue.getc(); //Save which button was pressed
                    if(blue.getc()=='1' && openLid==1) { //only execute on button press (not release)
                        switch(bnum) {
                            case '1':  //pause/play functionality
                                if(paused)
                                    resumeSong();
                                else //not paused
                                    pauseSong();
                                break;
                            case '2':  //enable/disable dancer
                                if(dancerEnable) { //disable the dancer
                                    dancerEnable=0;
                                    Ctrl.write(0);
                                } else { //enable the dancer
                                    dancerEnable = 1;
                                    if(paused==0)
                                        Ctrl.write(motorSpeed);
                                }
                                break;
                            case '3':  //stop functionality
                                waver.stop();
                                Thread::wait(50);
                                pauseSong();
                                break;
                            case '4':  //reset functionality
                                songnum=0;
                                songname = songs[0];
                                waver.stop();
                                Thread::wait(50);
                                resumeSong();
                                break;
                            case '5':  //increase volume
                                if(waver.getVolume()+volumeIncrement>1.0)
                                    waver.setVolume(1.0);
                                else
                                    waver.setVolume(waver.getVolume()+volumeIncrement);
                                break;
                            case '6':  //decrease volume
                                if(waver.getVolume()-volumeIncrement<0.0)
                                    waver.setVolume(0.0);
                                else
                                    waver.setVolume(waver.getVolume()-volumeIncrement);
                                break;
                            case '7':  //previous song in list
                                songnum--;
                                if(songnum<0) {
                                    songnum=songs.size()-1;
                                }
                                songname = songs[songnum];
                                waver.stop();
                                if(paused)
                                    waver.pause();
                                break;
                            case '8': //next song in list
                                songnum++;
                                if(songnum>=songs.size()) {
                                    songnum=0;
                                }
                                songname = songs[songnum];
                                waver.stop();
                                if(paused)
                                    waver.pause();
                                break;
                        }
                    }
                }
            }
        } else { //if lid is closed
            //flush the buffer
            while(blue.readable()) {
                blue.getc();
            }
            //otherwise it will execute commands immediately once you open box
        }
    }
}

How to Debug Issues

Song Playback Issues

-Be sure to change the SD card rate from 1 MB to 10 MB.

-Be sure you have the correct versions of the SD Card player and Waveplayer

-Be sure the project sample rate is correct in Audacity.

The process to correctly change a song:

1) Open song in Audacity.

2) Change the song to mono.

3) Resample the song to 16,000 Hz.

4) Change the project rate to 16,000 Hz.

5) Export song as a .wav file.

Bluetooth Issues

-Be sure your device is connected to correct Bluetooth module

-To stop the song, you must delay the pause for long enough that the song does not begin to play again. Be sure your wait is long enough.

-The code is written so that the buttons need to be pressed and released for functions to work. The control pad generally works when you simply press and do not release, so this led to a lot of double pressing and possibly restarting the song when you did not want to, which we mitigated by making sure functions only work when you press down on a button. We found the codes that are sent via bluetooth to the controller and choose those with a '1' in the 4th character to be the press of the buttons. The codes that are sent across bluetooth are as follows for when they are pressed and then released.

Up: !B516, !B507

Left: !B714, !B705

Right: !B813, !B804

Down: !B615, !B606

1: !B11:, !B10;

2: !B219, !B20:

3: !B318, !B309

4: !B417, !B408


Please log in to post comments.