I enjoy making silly projects. In fact, I am sometimes quite proud of making them and showing them off. I get an idea, make it a reality and it means little to me that it is silly - it is a kind of a freedom that one only experiences at the early and late bands of life.
I am sure that you have seen these, so-called, daily affirmations. Gems of wisdom that we must ponder with regularity to make us better people. So, in my late teens and early twenties, a few of us (and we are still friends) hit upon a number of "phrases" that stuck with us over the years. To be clear, these were not "affirmations" in any sense of the word. In fact, most were inappropriate, insensitive and obscene.
My idea was to capture these phrases and construct a "box" that would randomly play one when a button was pressed. It is a gift.
Here is what I came up with:
These DFPlayer boards are really pretty remarkable at a couple of bucks (bay clones). You record one or more (up to 255, I think) mp3 files on an sd card and then using a simple controller, you can play a selected file under program control. They even have an onboard amplifier that can drive a little 8 Ohm speaker with decent quality and volume. I chose an Arduino ProMini 5V clone as the controller.
The entire project is enclosed in an old speaker meant to connect to a PC.
The back side shows the trigger switch (one press will play one "phrase" at random. You can also see the power jack. I used one of the many old wall warts I have on hand. The ProMini has an onboard regulator using the "raw" pin and then, the Vcc pin drives the DFplayer.
The lower panel comes off to allow access to the controller and the SD card.
Thus, you can attach a USB to Serial board and reprogram it easily.
You can also easily remove the SD card and add / subtract and change phrases. I used Audacity to record and trim the mp3 files and I highly recommend that program.
The code is simple and was cobbled together from the existing demo code on the DFPlayer Wiki. All I really had to add was the "random" playing ability and a "random" seed on start up. The only real challenge was in getting the busy signal to work. I saw a number of software techniques to detect when a file was finished playing but I used the simpler hardware technique by reading the busy pin. For reasons I don't understand, I had to read it twice after a short delay. Again, I don't understand that but it works without fail with all the files that I tested, including ones with pauses in them.
That's it...another silly project.
I am sure that you have seen these, so-called, daily affirmations. Gems of wisdom that we must ponder with regularity to make us better people. So, in my late teens and early twenties, a few of us (and we are still friends) hit upon a number of "phrases" that stuck with us over the years. To be clear, these were not "affirmations" in any sense of the word. In fact, most were inappropriate, insensitive and obscene.
My idea was to capture these phrases and construct a "box" that would randomly play one when a button was pressed. It is a gift.
Here is what I came up with:
These DFPlayer boards are really pretty remarkable at a couple of bucks (bay clones). You record one or more (up to 255, I think) mp3 files on an sd card and then using a simple controller, you can play a selected file under program control. They even have an onboard amplifier that can drive a little 8 Ohm speaker with decent quality and volume. I chose an Arduino ProMini 5V clone as the controller.
The entire project is enclosed in an old speaker meant to connect to a PC.
The back side shows the trigger switch (one press will play one "phrase" at random. You can also see the power jack. I used one of the many old wall warts I have on hand. The ProMini has an onboard regulator using the "raw" pin and then, the Vcc pin drives the DFplayer.
The lower panel comes off to allow access to the controller and the SD card.
Thus, you can attach a USB to Serial board and reprogram it easily.
You can also easily remove the SD card and add / subtract and change phrases. I used Audacity to record and trim the mp3 files and I highly recommend that program.
The code is simple and was cobbled together from the existing demo code on the DFPlayer Wiki. All I really had to add was the "random" playing ability and a "random" seed on start up. The only real challenge was in getting the busy signal to work. I saw a number of software techniques to detect when a file was finished playing but I used the simpler hardware technique by reading the busy pin. For reasons I don't understand, I had to read it twice after a short delay. Again, I don't understand that but it works without fail with all the files that I tested, including ones with pauses in them.
Code:
/*-------------------------------------------------------------------------
- Broatway -
-An MP3 Player to provid serenity from the wisdom of the ages
This software is offered strictly, as is, with no warrenties or guarantees.
*** USE IT AT YOUR OWN RISK ***
----------------------------------------------------------------------------
*/
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#define BUSYPIN 2 // connect DFPlayer Busy pin to Arduino GPIO 2
#define BUTTONPIN 3 // connect button pin to Arduino GPIO 3
#define nFILES 19 // total number of files on SD card
#define DefPlay 1 // default file to play on power up
//#define DEBUG // comment out to suppress serial monitor output
SoftwareSerial SSerial(10, 11); // RX, TX
DFRobotDFPlayerMini MP3;
void printDetail(uint8_t type, int value);
void DFPbusy(void); // wait for busy to go HIGH
void setup()
{
pinMode(BUSYPIN, INPUT); // Busy pin
pinMode(BUTTONPIN, INPUT); // Button pin (pressed is LOW)
SSerial.begin(9600);
#ifdef DEBUG
Serial.begin(9600);
delay(3000);
#endif
#ifdef DEBUG
Serial.println();
Serial.println("Broatway");
Serial.println("Initializing DFPlayer ...");
#endif
if (!MP3.begin(SSerial)) { //Use softwareSerial to communicate with mp3.
#ifdef DEBUG
Serial.println("Unable to begin:");
Serial.println("Check connection!");
Serial.println("Check for SD card inserted");
Serial.println("Check for good power supply");
#endif
}
MP3.volume(30); //Set volume value. From 0 to 30
// seed prng
int R1 = analogRead(3) & 0x7 ;
delay (10) ;
int R2 = (analogRead(3) & 0x7) << 3 ;
delay (10) ;
int R3 = (analogRead(3) & 0x7) << 6 ;
delay (10) ;
int R = R1 + R2 + R3 ;
randomSeed(R);
MP3.play(1); // this auto plays the first file on startup
DFPbusy();
#ifdef DEBUG
Serial.println("Broatway Starting....");
#endif
}
void loop()
{
// last two files played for re-draws
// initialize these to the default file
static int lastfn = DefPlay; // preserve through function calls
static int lastfn2 = DefPlay; // " "
int fn;
// don't really need this additional info once it is setup
// #ifdef DEBUG
// if (MP3.available()) {
// Serial.println();
// printDetail(MP3.readType(), MP3.read()); //Print the detail message from DFPlayer
// Serial.println();
// }
// #endif
fn = random(1, nFILES + 1); // draw file number
if ((fn == lastfn) || (fn == lastfn2)) { // re-draw if it is a repeat of either of the last two files played
do {
#ifdef DEBUG
Serial.print(" FN=");
Serial.print(fn);
Serial.println(" Re-draw file number");
#endif
fn = random(1, nFILES + 1);
} while ((lastfn == fn) || (lastfn2 == fn));
}
while (digitalRead(BUTTONPIN) == 1); // wait for button press
#ifdef DEBUG
Serial.print("Playing file #");
Serial.print(fn);
#endif
// refresh the last two plays
lastfn2 = lastfn;
lastfn = fn;
MP3.play(fn);
DFPbusy();
#ifdef DEBUG
Serial.println(" finished");
#endif
while (digitalRead(BUTTONPIN) == 0); // wait for button release
}
void printDetail(uint8_t type, int value) { // we don't use this detailed report
switch (type) {
case TimeOut:
Serial.println("Time Out!");
break;
case WrongStack:
Serial.println("Stack Wrong!");
break;
case DFPlayerCardInserted:
Serial.println("Card Inserted!");
break;
case DFPlayerCardRemoved:
Serial.println("Card Removed!");
break;
case DFPlayerCardOnline:
Serial.println("Card Online!");
break;
case DFPlayerUSBInserted:
Serial.println("USB Inserted!");
break;
case DFPlayerUSBRemoved:
Serial.println("USB Removed!");
break;
case DFPlayerPlayFinished:
Serial.print("Number:");
Serial.print(value);
Serial.println("Play Finished!");
break;
case DFPlayerError:
Serial.print("DFPlayerError:");
switch (value) {
case Busy:
Serial.println("Card not found");
break;
case Sleeping:
Serial.println("Sleeping");
break;
case SerialWrongStack:
Serial.println("Get Wrong Stack");
break;
case CheckSumNotMatch:
Serial.println("Check Sum Not Match");
break;
case FileIndexOut:
Serial.println("File Index Out of Bound");
break;
case FileMismatch:
Serial.println("Cannot Find File");
break;
case Advertise:
Serial.println("In Advertise");
break;
default:
break;
}
break;
default:
break;
}
}
void DFPbusy(void) {
while (digitalRead(BUSYPIN) == 0); // wait until it is high (not playing)
delay(100);
while (digitalRead(BUSYPIN) == 0); // Have to do a double here
delay(100);
}
That's it...another silly project.