Project 5

iPoduino v2.0

Overview

Microcontrollers often communicate with other devices, like sensors, actuators, or maybe... an MP3 player module. In this project, will explore how embedded systems transmit and receive data through the UART communication protocol.

Small checkpoints will prepare you for the final task: You will create an MP3 player with a "Play/Pause" toggle button and a "Skip/Next Song" button, using the DFPlayer Mini module. Songs are -loaded onto a microSD card which you will insert into the module. The system will output mono sound through a small speaker.

Concepts

UART

Embedded within the Arduino Nano is a device called the Universal Asynchronous Receiver-Transmitter (UART). It may communicate with another UART by transmitting or receiving messages known as packets. This is done in serial, meaning packets are sent one bit of data at a time. UARTs also communicate asynchronously, so there is no clock to time when packets are transmitted or received.

Serial Communication with Arduino

We can use the UART in our Arduino Nano to transmit data to another UART device. To do so, we will enlist the help of the Serial Library, which is already installed in the Arduino IDE.

The data within each packet sent with UART is one byte in size, meaning if the data contained an int, its value could only be in the range -128 to 127 (signed) or 0 to 255 (unsigned). We’ll see how this comes into play later.

Every UART can both transmit and receive packets, which is referred to as duplex communication. They communicate over their TX and RX pins; recall that the TX pin on one device connects to the RX pin on the other.

Remember how we set the baud rate of our Nano using Serial.begin(9600)? When a UART receives a transmission, it reads each bit at the speed of the baud rate (measured in bits per second). Both the transmitting and receiving UART must have the same baud rate for proper communication.

There are three core functions of the Serial library:

  1. Serial.write(val) sends data from the Arduino board to another UART device. You will use it to transmit one byte at a time, meaning the int value passed as an argument must be in the range -128 to 127 (signed) or 0 to 255 (unsigned).
  2. When the Arduino receives data, we need to check its receive buffer, a “mailbox” or an array of recently received bytes. Serial.available() will return an int, the number of bytes currently in the UART buffer. If the number is zero, nothing has been received.
  3. If the UART buffer does have data in it, you will read the byte at the front of the buffer using Serial.read(), which returns an int.

Universal Serial Bus (USB) on the Arduino

USB is a serial communication protocol used widely by modern computers. It defines the standards by which devices transmit data over USB cables. When you plug the Arduino Nano into your computer, upload a sketch, and execute a program with Serial.print(), data transmits between the Nano and your computer using the USB protocol.

Hidden behind the scenes is the UART. Data is transmitted between the computer and Arduino Nano through a chip that converts USB signals to UART signals. Those converted signals are then transmitted to and from the UART within the Nano’s microcontroller.

With this in mind, remember that the Arduino’s USB port is hardwired to the TX and RX pins of the board. Do not upload a sketch to an Arduino while the board is connected via the TX/RX pins to another Arduino. Do not attempt to use Serial.print() under these conditions either.

Software Serial

The SoftwareSerial library enables UART communication over other digital pins of the Arduino board. Why do we need it? Suppose you connect the Arduino over USB to your PC and use the Serial Monitor. At the same, you want the Arduino to connect to another UART device. The Arduino Nano only has one physical UART, so we use Software Serial to emulate a second UART connection over separate digital pins.

#include <SoftwareSerial.h>
const int rxPin = 2;
const int txPin = 3;
SoftwareSerial mySerial(rxPin, txPin);

The code above creates an object of the SoftwareSerial class that manages a new UART connection over the digital pins passed to the constructor. Then, you just use the pins like you would normally!

There are several limitations of SoftwareSerial: It cannot transmit and receive data at the same time. If multiple software serial ports are used, only one can receive data at a time. Lastly, not all digital pins support SoftwareSerial. Find out more here.

Pull-Up Resistors

Suppose you use a digital input pin on the Arduino board, but it’s not connected to anything. Is the state of the pin HIGH or LOW? For it to be HIGH, the pin would need to be connected to the VCC power source. For the state to be LOW, the pin would need to be connected to GND. When the state is indeterminate like this, the pin is said to have a floating signal, which we should avoid.

The solution is what we call a pull-up resistor. The input pin is connected to a high-value resistor R1 whose other terminal is attached to VCC (as depicted below).

The intent is to set the input pin to the HIGH voltage. We often use a 10kΩ resistor to do so. Now, the input pin has an effective resistance in the range of 100 MΩ. That’s right: mega-ohms.

The resistance of the pull-up resistor R1 and effective resistance of the input pin divide the voltage VCC such that the voltage at the input pin is equal to VCC (HIGH).

Now, let’s introduce the button: one terminal attached to the input pin and the other GND.

When the button is pressed, the voltage at the input pin is shorted to GND (LOW).

With this circuit, the input pin will either be VCC or GND (HIGH or LOW). Let’s see how it would look on a breadboard:

In the layout above, the pushbutton is connected to an external pullup resistor. Its state (HIGH or LOW) is read from pin D2 of the Arduino Nano.

Internal Pull-Up Resistors

When you use a button, you should combine it with a pull-up resistor. Instead of building an external circuit, you can use an internal pull-up resistor in the Arduino board. You may do so by setting the pin mode as follows:

pinMode(pin, INPUT_PULLUP);

The layout above is for a pushbutton that uses the Arduino Nano’s internal pullup resistor.

DFPLayer Mini MP3 Player

The Arduino Nano has too little memory to load and play audio files. Instead, we use a separate device to store and manage the audio media: The DFPlayer Mini is a small MP3 module that connects to an Arduino board (or other microcontrollers) over UART.

Though it supports a variety of control modes, we will use the module's serial mode. In serial mode, we need only connect the module's TX/RX, Power, Ground, and speaker pins. Using UART, the Arduino will send commands to the DFPlayer Mini to playback songs, pause, change volume, etc. This is facilitated by a custom Arduino library.

Explore more about the DFplayer Mini at its wiki page.

Datasheet and Pinout Diagram

As an exercise of technical documentation literacy, we will not provide the pinout diagram. Instead, you can access the datasheet here.

Remember that you are looking for the following in the datasheet’s pinout diagram: TX, RX, Power (VCC), Ground (GND), Speaker +, and Speaker -. (Hint: Look at Section 2 of the datasheet).

Read Section 1.2, 1.4 for information about the supported file types, file naming conventions, and folder (a.k.a. directory) structure for the MicroSD card.

Using the DFPLayer Mini with Arduino

You can download the DFPlayer Mini library v1.0.5 here. We recommend this version as newer ones have produced errors in our testing. It can be used in your code with the following include:

#include <DFRobotDFPlayerMini.h>

Below is sample code that demonstrates the module in serial mode. The program plays a audio file named “0001.mp3” for five seconds, then pauses it for five seconds, then resumes. Then, in the loop, it cycles through songs every 5 seconds. Use this as a reference for the commands to send to the MP3 module.

#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
				
// Use pins 2 and 3 with SoftwareSerial to communicate with DFPlayer Mini 
// and leave RX and TX open to the connected computer for debugging
const int PIN_MP3_TX = 2; // Connects to module's RX
const int PIN_MP3_RX = 3; // Connects to module's TX
				
// Create the player object which will serve as an interface for our DFPlayer commands
DFRobotDFPlayerMini player;
				
void setup() {
	// Initialize the pins for SoftwareSerial. No pinMode calls needed.
	SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
				
	// Initialize USB serial port for debugging
	Serial.begin(9600);
				
	// Initialize software serial port for DFPlayer Mini
	softwareSerial.begin(9600);
				
	// Start communication with DFPlayer Mini using player.begin  
	// player.begin returns true if the connection was a success
	// and false if it failed
	if (!player.begin(softwareSerial))  {
		Serial.println("Connecting to DFPlayer Mini failed!");
	}

	// Set the player volume to maximum (0 to 30).
	player.volume(30);

	// Play the "0001.mp3" file in the "mp3" folder on the microSD card.
	player.play(1);

	// Delay the next command by 5 seconds.
	delay(5000);

	// Pause the playback.
	player.pause();

	// Delay the next command by 2 seconds.
	delay(2000);

	// Resume the playback from pause.
	player.start();

	// Here are some useful debugging functions
	// Sometimes they don't return valid values. In that case, ignore them.
	Serial.println(player.readFileCounts()); // Returns number of files in microSD 
	Serial.println(player.readCurrentFileNumber()); // Returns current file number being played
}

// Change songs every 5 seconds.
void loop() {
	// Delay the next command by 5 seconds.
	delay(5000);

	// Skip to the next song.
	player.next();
}
	

Installing Arduino Libraries

Here is a quick recap on how you can install Arduino libraries in the Arduino IDE 2.0.0+

  1. Download the library as a .zip
  2. In the Arduino IDE, go to Sketch → Include Library → Add .ZIP Library…
  3. Select the .zip of the library and click Open.

You're done! Just make sure to #include the library header file so that your code compiles.

DFRobot DFPlayerMini Download

Arduino Nano Pinout

Thinking about using a pin but you don’t know what it does? Refer to the Arduino Nano pinout diagram, or scroll further to find the full datasheet.
~ represents pins that are PWM capable.

Requirements

UART Echo

  • You must write a program in which the Arduino board “echoes” back any small unsigned integer (0-255) sent to it over UART.
  • When the user enters an integer (0-255) into the Arduino IDE Serial Monitor from their computer, the value is sent to the Arduino board. The board must send the same value back to the computer.
  • The Arduino will only “echo” back a value sent to it once. It should not resend the value multiple times.
  • The program must run in an infinite loop.

External Pull-Up Resistor Circuit

  • Using the Arduino board, you must build a digital LED circuit which is activated by a pushbutton connected to an external pull-up resistor.
  • When the pushbutton is pressed, the built-in LED (pin D13) on the Arduino board should turn ON.
  • The build-in LED must turn OFF with the pushbutton is released.
  • The LED must be brightly lit when turned ON.
  • The LED must be completely dark when turned OFF.
  • The circuit must be built on a breadboard.

Internal Pull-Up Resistor Circuit

  • Using the Arduino board, you must build a digital LED circuit which is activated by a pushbutton connected to an internal pull-up resistor.
  • When the pushbutton is pressed, the built-in LED (pin D13) on the Arduino board should turn ON.
  • The build-in LED must turn OFF with the pushbutton is released.
  • The circuit must NOT use an external pull–up resistor.
  • The LED must be brightly lit when turned ON.
  • The LED must be completely dark when turned OFF.
  • The circuit must be built on a breadboard.

iPoduino

  • You must build a MP3 Player with speaker sound using the DFPlayerMini module.
  • The player must be pre-loaded with 3 songs.
  • Each song must be at least 30 seconds in duration.
  • The player must have two buttons.
  • One of the player’s buttons must toggle the music between “Play” mode and “Pause” mode.

    • In “Play” mode, the player must playback a song. It should resume the song that was previously paused if the “Skip/Next Song” button was not pressed.
    • In “Pause” mode, no song should be played.

  • The second button should be the “Skip/Next Song” button, which interrupts the current song and plays a new song.

    • Each press of this button must cycle through all songs loaded on the MicroSD card.
    • If the player was in “Pause” mode when the “Skip/Next Song” button is pressed, the player must immediately enter “Play” mode.

  • The speaker must be silent when no song is played. No static or white noise.
  • The speaker must clearly output music when a song is played.
  • The circuit must be built on a breadboard.

Parts

Part Name Qty
Jumper Wire ?
Breadboard 1
Arduino Nano 1
MicroSD Card 1
Pushbutton Switch 2
Speaker, 0.5W, 8Ω 1
Resistor, 1kΩ 1
Resistor, 10kΩ 1
DFPlayer Mini Module 1
Mini USB Cable 1

Schematics

Instructions

Checkpoint 1

  1. Connect the Arduino Nano to your computer and open the Arduino IDE. You will write a small program that echos small byte-sized values between the Nano and your computer.
  2. Upload your sketch to the Arduino Nano, and verify that the program executes as expected. Open the Arduino IDE Serial Monitor, enter small integer values, and observe the communication between the computer and the Nano.

Checkpoint 2

  1. Build the circuit from Schematic A (External Pull-Up Resistor Circuit) on your breadboard. You will design a digital LED circuit with an external pull-up resistor and pushbutton.
  2. Upload your sketch to the Arduino Nano, and verify that the program executes as expected.

Checkpoint 3

  1. Build the circuit from Schematic B (Internal Pull-Up Resistor Circuit) on your breadboard. You will design a digital LED circuit with an internal pull-up resistor and pushbutton.
  2. Upload your sketch to the Arduino Nano, and verify that the program executes as expected.

Checkpoint 4

  1. Build the circuit from Schematic C (iPoduino) on your breadboard. Use the sample code provided in the Concepts sections to guide your Arduino program. If you get stuck on breadboard layout, open the hint below:
  2. Upload your sketch to the Arduino Nano, and verify that the circuit meets the design requirements.

Deliverables (Enrolled Students Only)

Students enrolled in the course must submit the deliverables below to the corresponding Canvas course assignment.

Place the following files in a single folder:

  • iPoduino sketch file
  • Video of the iPoduino (Schematic C) on a breadboard

Compress the folder to a zip file and rename the file using the format “ops_project5_lastname_firstname.zip” Then, submit the zip file to the Project 5 Canvas assignment.