Output Devices

Design Files

Group Assignment

Playing Audio Using Low-Bitrate (8KHz) Audio Files

My original plan was to replicate the functions of the Bare Conductive Touchboard and use an SD card reader, amplifier and speaker to play MP3 files when the capacitive sensor is touched. During research, I discovered another way to play audio, using low-bitrate (8KHz) audio files. The benefit of this, is that the only hardware needed is a speaker attached to an Arduino, so would reduce costs.

I got the example code to work and updated the audio clip to me saying 'elephant'. I followed the guide at http://highlowtech.org/?p=1963:

  1. Open Arduino IDE
  2. Install PCM library by going to Sketch > Install Library > Search for PCM > click Install
  3. Open the example code by going to File > Examples > PCM > Playback
  4. Connect an 8ohm 0.2W speaker to an Arduino Uno by connecting the positive wire to digital pin 11 and the negative to the ground pin. (Make sure it is 0.2W because when I used a 2W speaker a warning popped up on the computer saying it is disabling USB devices because it is drawing to much power.)
  5. Upload the code to the Arduino
  6. Listen for the audio file to play when the code has finished uploading.

However with more understanding of the system, it doesn't seem to be possible to add multiple audio clips because it is stored in the Arduino's Flash memory which is a lot smaller than using RAM. According to http://highlowtech.org/?p=1963 the arduino will be able to store approx. 4 seconds of audio. Also the program has been designed to be done with an Arduino Uno chip, and doesn't work with the ATMega32U4 because it only has 1x 8 bit timer whereas the code needs two.

Playing Audio Using DFPlayer Mini

So I moved away from the low-bitrate audio and researched how to play mp3 files on an Arduino. I kept coming across ways to do it with a shield, but for this assignment, I needed it to be more DIY and for the talking puzzle I need to keep within the grant budget. During my research, I discovered the DFPlayer Mini module and learnt the basics from the video below. I used the circuit layout from the video which is easier to see at http://educ8s.tv/arduino-mp3-player/ and found out more information about the module at https://www.dfrobot.com/blog-445.html


Using the example sketches

Continuous Audio

  1. Download code from http://educ8s.tv/arduino-mp3-player/
  2. Add mp3 files to SD card
  3. Insert SD card into DFPlayer module
  4. Upload code to Arduino Uno

Result: Played audio files very quietly. When one audio clip ends, another one begins. Need to work out how to link a different track to each button and for it to play once and then stop.

Play Specific Tracks

  1. Go to Sketch > Include Library > Manage Libraries ... > search for DFPlayer > install DFPlayer Mini MP3 by Makuna. (Press more info to be sent to Github page with links to more info or follow this link)
  2. Go to File > Examples > DFPlayer Mini MP3 by Makuna > Play Mp3
  3. Plug the SD card into the computer and create a folder on it called mp3.
  4. Add 3 mp3 files to the folder and name them 0001.mp3, 0002.mp3 and 0003.mp3
  5. Remove the SD card and plug it into the DFPlayer module
  6. In the PlayMP3 code type // before the line
    DFMiniMp3 mp3(Serial1);
    to turn the line into a comment and uncomment the lines
    SoftwareSerial secondarySerial(10, 11); 
        DFMiniMp3 mp3(secondarySerial);
  7. Click Verify
  8. Click Upload
  9. Open Serial Monitor and change the Baud Rate to 115200 baud, to match the code.
Result: Plays 3 specific mp3 files from a folder in the SD card. Now I should be able to use the code line below to specify an audio file to be played on the press of a button, changing the number in the brackets for each audio file.
mp3.playMp3FolderTrack(1);

Buttons

  1. Go to File > Examples > Digital > Button
  2. I combined some of the code from the Button example with some of the code from MP3Play
Result: The audio files play, but seemingly randomly. Turns out it is because a pullup resister is needed on the switches.

  1. Go to File > Examples > Digital > DigitalInputPullup
  2. Copy the code into the relevant sections of the button/mp3 code
  3. Change the line
    if(buttonstate4 == HIGH)
    to
    == LOW
    for each button. This is because the internal pull up resistor inverts the logic, so off = 1 (high) and on = 0 (low).
  4. Can change the Baud Rate in the code and serial monitor to 9600 baud (optional)

This is the code I used to play specific tracks on the press of a button, with digital pullup resistors.


// it expects the sd card to contain these three mp3 files
// but doesn't care whats in them
//
// sd:/mp3/0001.mp3
// sd:/mp3/0002.mp3
// sd:/mp3/0003.mp3

const int buttonPin2 = 2;     // the number of the pushbutton pin
const int buttonPin3 = 3;     // the number of the pushbutton pin
const int buttonPin4 = 4;     // the number of the pushbutton pin
const int ledPin = 13;      // the number of the LED pin
int buttonState2 = 0;         // variable for reading the pushbutton status
int buttonState3 = 0;         // variable for reading the pushbutton status
int buttonState4 = 0;         // variable for reading the pushbutton status

#include <SoftwareSerial.h>
#include <DFMiniMp3.h>

// implement a notification class,
// its member methods will get called 
//
class Mp3Notify
{
public:
  static void OnError(uint16_t errorCode)
  {
    // see DfMp3_Error for code meaning
    Serial.println();
    Serial.print("Com Error ");
    Serial.println(errorCode);
  }

  static void OnPlayFinished(uint16_t globalTrack)
  {
    Serial.println();
    Serial.print("Play finished for #");
    Serial.println(globalTrack);   
  }

  static void OnCardOnline(uint16_t code)
  {
    Serial.println();
    Serial.print("Card online ");
    Serial.println(code);     
  }

  static void OnCardInserted(uint16_t code)
  {
    Serial.println();
    Serial.print("Card inserted ");
    Serial.println(code); 
  }

  static void OnCardRemoved(uint16_t code)
  {
    Serial.println();
    Serial.print("Card removed ");
    Serial.println(code);  
  }
};

// instance a DFMiniMp3 object, 
// defined with the above notification class and the hardware serial class
//
//DFMiniMp3<HardwareSerial, Mp3Notify> mp3(Serial1);

// Some arduino boards only have one hardware serial port, so a software serial port is needed instead.
// comment out the above definition and uncomment these lines
SoftwareSerial secondarySerial(10, 12); // RX, TX
DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(secondarySerial);

void setup() 
{
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
  pinMode(buttonPin4, INPUT_PULLUP);
  
  Serial.begin(9600);

  Serial.println("initializing...");
  
  mp3.begin();
}


void loop() {
  //read the pushbutton value into a variable
  int sensorVal = digitalRead(2);
  //print out the value of the pushbutton
  Serial.println(sensorVal);
  
  // read the state of the pushbutton value:
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState2 == LOW) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    // play track 1:
    Serial.println("track 1"); 
  mp3.playMp3FolderTrack(1);  // sd:/mp3/0001.mp3
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }

// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState3 == LOW) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    // play track 2:
    Serial.println("track 2"); 
  mp3.playMp3FolderTrack(2);  // sd:/mp3/0002.mp3
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }

  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState4 == LOW) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    // play track 3:
    Serial.println("track 3"); 
  mp3.playMp3FolderTrack(3);  // sd:/mp3/0003.mp3
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}
Move components over to Leonardo

I tested the DFPLayer with an Arduino Uno, because it makes it easier to troubleshoot by using the same board as the example I'm following. However the board I made in Inputs week has the same microcontroller as an Arduino Leonardo, so I moved the components over to a Leonardo and luckily the code worked using the same pins as the Uno.

Adding components to my milled board

Using the ATMega32U4 pinout diagram, the Eagle Schematic of my board and the current circuit layout of the button/mp3 setup on the Arduino Leonardo, I mapped out a circuit diagram to add the DFPlayer to my board.

Photo

The current set up on the Arduino Leonardo uses digital pin 11 to connect to the RX pin on the DFPlayer module, but my board has no copper trace coming out of digital pin 11, so I tried changing it to pin 12 which is accessible and it worked. It just required a change in the code from

SoftwareSerial secondarySerial(10, 11);
to
SoftwareSerial secondarySerial(10, 12);

This section is part of my final project here.

Photo