MP3 player with RGB-signal LED (optionally battery powered)
License:
Attribution-ShareAlike (CC-BY-SA)
Created:
8 years ago
Updated:
8 years ago
Views:
21244
1 Collect
2 Comments
Share
169 Download (17.73 MB)
Donate to support Open Hardware

Introduction

This is a remote controlled MP3 player with an RGB-indicator light. It can optionally be battery powered. The MP3 player is a "FN-M16P Embedded MP3 Audio Module" aka DFPlayer Mini. It can play MP3/WAV files from a microSD Card or USB-stick. As it has a serial interface it can be controlled by a microcontroller. It includes a 3W amplifier to directly drive a small speaker. See the datasheet for more information. It is quite cheap and can be bought for less than 2€.

Main use cases are

  • remote door bell with different sounds and optical indicator
  • text2speech with prerecorded speech fragments
  • acoustical/optical alarm

The circuit consists of these main components

  • Arduino pro mini 3.3V
  • NRF24L01+
  • DFPlayerMini
  • RGB-LED

Power supply and consumption

The most difficult part is powering all components involved especially if battery powered. The voltage ranges are

  • Arduino: 3.35-12V
  • NRF24L01+: 1.9-3.6V
  • DFPlayerMini: 3.3-5.0V

Moreover the standby current of 15mA of the DFPlayer is much too high for battery use.

My solution is this:

  1. Use 3 batteries with about 4.5V as the power source
  2. NRF24L01+, ATMega328p and the LED are powered through the voltage regulator on the Arduino board which supplies a stable 3.3V
  3. the power supply of the DFPlayer is directly from the batteries as the voltage regulator can't supply the max. current of 1A
  4. the power supply of the DFPlayer is switchable using a high-side switch

This allows to drain the batteries down to 3.35V.

A battery powered actor is another challenge. Because MySensors doesn't offer a 'wake on radio' mechanism there is no other way than to cyclically wake the actor and ask the controller if there is anything to do. If this is done too often energy is wasted, if done too seldom it takes too long for the actor to react to commands. So it's a tradeoff between energy consumption and latency. As there is probably no optimal value for the sleep time for every one, the time can be set dynamically with a message from the controller to the actor. The default sleep time is 5s, a sleep time of 0 switches sleeping off completely. The DFPlayer is only switched on if a command is sent to it.

To reduce the energy consumption of the Arduino board the power LED can be disabled/removed as described here. But don't remove the voltage regulator!

With the power LED on the Arduino disabled I measured a sleep current of 33µA. During wake with just the Arduino and the NRF24L01 enabled the current is about 18mA. With all three LEDs of the RGB-LED enabled it's 40mA. Power consumption of the DFPlayer depends on the volume and signal played, but it seems to be in the range of 20 to 150mA. All measurements were made at 4.8V.

active time measurement Just requesting values from the controller takes about 0.5s when smart sleep is used. Assuming a sleep time of 5s and a battery capacity of 3000mAh this leads to a theoretical battery life time of 60 days. Increasing the sleep time to 30s will give a battery life time of about a year.

In my experiments 200ms were enough with Fhem as the controller. Thus the fixed 500ms timeout of the smart sleep feature isn't optimal in this case. I decided to use a modified smart sleep: Send out the requests to the controller and wait until the last response from the controller is received. Immediately afterwards we can go to sleep. With this approach the minimal active time is reached, which is about 102ms in my case. Too avoid staying active indefinitely if a response isn't received the MY_SMART_SLEEP_WAIT_DURATION_MS is still used as an upper limit.

This time can be influenced by setting

/**
 * @def MY_SMART_SLEEP_WAIT_DURATION_MS
 * @brief The wait period (in ms) before going to sleep when using smartSleep-functions.
 *
 * This period has to be long enough for controller to be able to send out
 * potential buffered messages.
 */
#ifndef MY_SMART_SLEEP_WAIT_DURATION_MS
#define MY_SMART_SLEEP_WAIT_DURATION_MS (500ul)
#endif

With all these modifications battery life time should be more than 200 days which I think is okay for now.

Measuring battery voltage is done on the switched power supply of the DFPlayer. I.e. the voltage divider doesn't draw any power as long as the DFPlayer is switched off. On the other hand battery measurement is currently only performed when the DFPlayer is switched on. To force a battery measurement without playing any sound one could i.e. send a volume change command.

If you don't want to power it with batteries use a power supply with 3.5-5.0V. In that case the MOSFET, transistor and corresponding resistors aren't needed and the VCC input of the DFPlayer can be directly connected to the power supply.

Change

// set to 0 if not powered by a battery
// and special power saving measures are not
// required
#define BATTERY_POWERED 1

to

// set to 0 if not powered by a battery
// and special power saving measures are not
// required
#define BATTERY_POWERED 0

and all DFPlayer power switching and battery measurement code will be disabled.

Controlling it

The DFPlayer can be controlled in different ways:

  1. by sending a 10 byte binary or hexadecimal message as described in the datasheet
  2. sending a 4 byte hexadecimal message containing just CMD, Feedback, Para_MSB, PARA_LSB (see datasheet)
  3. sending a 3 byte hexadecimal message containing just CMD, Para_MSB, Para_LSB (see datasheet)
  4. sending a ASCII-text command starting with !

1-3 allow full control over the DFPlayer, 4. only implements a subset of all possible commands but is easy to use.

Currently implemented commands for option 4 are:

  • !PLAY
  • !PREV
  • !NEXT
  • !MP3 [number of track in MP3 folder]
  • !SLEEP [sleep time in ms]
  • !OFF (switched DFPlayer off immediately)
  • !VOL [volume from 0-30]

I also wrote a module for the Fhem controller software, see DFPlayerMini module documentation for more information.

The DFPlayerBat node implements two children

  1. interface to DFPlayer

This child is of type S_CUSTOM. Commands must be sent as V_VAR1. Answers from the DFPlayer are sent to the controller as V_VAR2. V_VAR3 is the sleep time in milli seconds. 2. RGB-LED

The three color pins are connected to PWM outputs of the Arduino, i.e. each color intensity can be set in 256 steps. This child is of type S_RGB_LIGHT and expects a value as V_RGB.

Building

Connect all components as seen in the Fritzing picture. Flash the sketch on the Arduino. I never managaged to do this via the serial bootloader but used an ISP programmer instead. Once the circuit is connected to the power supply the LED will light up yellow. When the MySensors software finished initialization the LED will turn off briefly and will then go green for one second. If it is red instead, there is a problem with the DFPlayer. If it will stay yellow there is a problem with the MySensors initialization. Enable the MySensors logging by uncommenting

//#define MY_DEBUG

and watch the output in the serial monitor for further analysis.

Building a case

I bought some cheap speakers that make a nice case. They have a compartment for three AA batteries just as required and two speakers with 4 Ohm/3 Watt each. Moreover the case offers enough space for my additional PCB.

modified PCB

I modified the original small PCB by cutting the connection to the built-in amplifier chips. I soldered two wires to the PCB for VCC and GND. This allows to use all powering options of the speaker: batteries, USB and a specific power plug. And my circuit can be switched on and off with the small power switch.

The DFPlayer can be directly connected to USB and then appears as a mass storage device. This would allow to update the the SD-card without the need to open the case. Unfortunately I wasn't able to solder wires to the D+/D- pins of the micro USB connector. The solder just didn't stick to the pins.

Technical difficulties

The DFPlayer has some quirks/undocumented features. It takes several ms for the busy pin to go low after sending a play command. So switching the power supply off immediately if the pin is high switches it off before it even starts to play.

The 'track finished' sequence is sent twice. As this can confuse the controller it is filtered out in the sketch. This can be disabled by disabling

#define REMOVE_DUPLICATE_RESPONSE

Switching the DFPlayer on/off leads to some pop/click sounds from the speaker. According to the datasheet of the 8002 audio amplifier used in the DFPlayer this is due to a too small bypass capacitor CB. I haven't bothered to try to add a bigger one yet.