Skip to main content

Layout sound on demand!

Here we go...all the sounds that you have collected over the years can now be heard from your railroad. In this article you will wire a sound playing module to a speaker and a Nano with 6 wires.

  Imagine a button to announce the next train ready to leave, a light sensor noticing a stock car at the loading chute making some cattle noises, wheels squealing around a curve, or on my layout, elephants and lions in the wild!

DFPlayer Mini pinout
  So, save some sounds, (or “songs” called from here on), in MP3 format, onto a micro (u) SD card using your personal computer. Reading the documentation makes it a bit confusing, from: the order matters in which you drag the files to the uSD card, to: having 100 folders with each 255 sounds and commands calling which file in a folder?!? What I did was save my sound files as 001.mp3, 002.mp3 and so forth in the root folder of the drive, and had no trouble getting them to play. Remember to properly “Eject” the card using your operating system software before removing it from the computer. Insert it into the uSD Card slot and when you power it all up, expect to hear some sounds!


  We are using the DFPlayer Mini, $8.90 from the original creators DFRobot, $9.06 at Amazon or as low as $1.52 at Ebay and $1.08 at AliExpress. With as little as power, ground and two more wires connected to the Nano, as well as the two wires to the speaker ( < 3 Watt ), you are ready to play. If you have an application where a user could press any one of 20 buttons to play 20 different “songs”, you won’t even need an Arduino, just read and build the AD KEY Mode example shown in paragraph 2 in this section online.  In this article, however, we will be using the I/O Mode, since we also want the Nano to trigger on an input, like a train passing by or a person pushing a button and then play the “songs”.  Any 8 Ohm speaker would work, just know that the amplifier on the Mini can only deliver 3 Watts and it is powered from the Nano’s regulator. Here are 10 speakers from Amazon for $9. Do know that the science of speakers making sound are still at work here and an enclosure like a baffle might still be needed to give you the best sound.  This article is not for audiophiles, you would have already installed the Kipnis Outer Limits Theatre equipment in your train room!

  First the wiring diagram: as shown in the next diagram, we will connect the speaker to the DFPlayer Mini with two wires.  Note that your speaker might have a + and/or - sign for its connections, so hook the + to the SPK_1 on the DFPlayer and the - to SPK_2. If no polarity, just connect the speaker wires to SPK_1 and SPK_2.

  Power (5Vdc) and ground from the Nano (5V and GND) to the DFPlayer (“VCC” @ pin 1 and “GND” @ pin 7 or 10 on the Mini). Searching Google will show you discussions on which GND to use on the Mini, on mine pin 7 and pin 10 are connected to each other with less than 0.01 ohms, so follow what you think is right.

Nano to DFPlayer Mini connections (thanks to fritzing)

To control the DFPlayer from the Nano, we need the orange wire from Nano pin D3 to RX and to get status from the player we want the yellow wire between the Nano pin D2 and the TX on the player.

  The bulk of the code is already done for us in a library that we can download, so install it using Sketch → Include Library → Manage Libraries. Do a search for DFPlayerMini and install the one by DFPlayer (currently version 1.0.5). Now all we need to use the code is the #include statement:
#include "DFRobotDFPlayerMini.h"

  And a player object to use:
DFRobotDFPlayerMini myDFPlayer;

  A software serial port is needed to talk to the DFPlayer Mini, and that library is included with:
#include "SoftwareSerial.h"

  The create the software serial port, since the default hardware one is already used by the communications towards the USB port, we add:
#define SWRXPIN                      2
#define SWTXPIN                      3
SoftwareSerial mySoftwareSerial( SWRXPIN, SWTXPIN );   // RX pin and TX pin to DFPlayer

  In setup() we set the baud rate to talk to the DFPlayer (9600 is the default), as well as the baud rate (I like 115,200) to give us some information into the Serial Port Monitor (Ctrl+Shift+M) with the well known Serial.println() commands.


  VERSION_STR needs to be defined as expected, so always use something you can search for with your favorite file search tool when you come back in 3 years to look for the code. Higher up in the file, add something like:
#define VERSION_STR "ML2020-01 Sound by DFPlayer Mini ver 0.001"

  From here you would like to know that the DFPlayer has a good working uSD Card inserted and maybe that there are some files on it that can be played.  There are quite a few error messages that the DFPlayer can tell when something goes wrong, but we will write code here for the “happy path” and assume all is well all the time. You should definitely invest a little more time to catch most of the possible errors before you install this under your layout. Six months later when something goes wrong, you would want to plug it into a computer’s USB port and quickly see what the problem might be. There are error messages like BUSY, SLEEPING, CHECKSUM MISMATCH, FILE INDEX OUT of BOUNDS and FILE NOT FOUND that might not show up in your first hundred hours playing with it, only when you least expect it!

  So in setup() we wait for the DFPlayer to tell us all is well, and only then do we continue to loop(), where we do some work to decide what to play. Again, the “happy path” does not take into account that you might remove the uSD Card while it is playing, so that code to check while inside loop(), would be your homework.  Maybe a function called checkIfAllIsWell() could be used by both setup() and loop() to accomplish the task.

  And now a real program. In this example, when you connect pin 4 to ground, using something like a push button switch or a BD20 track sensor, it will play all the mp3 files in the base or root folder of the uSD card, one after the other as the pin goes low every time. If there is only one file on the card, it would play it every time the pin goes low.

Upload and enjoy!

Thank you to Dr. Kamm of the Sue Line RailRoad in Shreveport for pointing us towards the DFPlayer Mini. 

  A few more notes:
  • When you turn the DFPlayer on without or with a bad uSD card, you’ll notice a very dim red LED on the player. When the card is good, the LED will be quite bright.
  • To avoid crackling noises when a song starts and/or stops, use software like Audacity to fade the sounds in at the beginning and fade out at the end.
  • It does not seem possible for the DFPlayer to tell you how much time is left in a file, so if timing is important in your application, use a stopwatch to time them and hardcode the values in the Arduino.  MP3 of WAV files can be used, sampled at as low as 8 kHz and as high as 48 kHz
  • The uSD card can be as small as 2 GB and as big as 32 GB. Formatted with FAT16 or FAT32 as needed.
  • When you try to upload the code to the Nano and it fails on first attempt, make sure that you have selected, under Tools, the correct Board, Processor and Port. If you bought an Arduino at a very low price, it is very likely that you need to select ATmega328P (Old Bootloader)” as the processor.

Comments

Popular posts from this blog

Signal Masts in JMRI 4.14, for beginners...

Here are all the notes and files from the Plano Train Show Clinic. You need to have an internal sensor ( IMCOMPORT ) with the port in the value like COM10 or /dev/ttyUSB0 , whatever Device Manager (or /dev/ttyUSBx) shows for the connected Arduino. If you have Panels -> Script Output open, you will see the message:  !!! Please add IMCOMPORT with the port in the value!!! The basic idea here is to use the Comment in the Signal Head field to define the position of the Pixel in the string commented to the Arduino, as well as the RGB colors to show for Clear, Approach and Stop (00:00 FF 00: BBAA 00: FF 0000). With all the Heads in the Table, run the python script and now you can update the colors in the Comment "live", keeping in mind that a message is only sent when a Head changes color. We then put the Heads in Masts and use the Signal Mast Logic to do the magic. I like the original Panel Editor more and it works fine as long as you keep using Mast pairs, which require

The One Pin Signal System, using an Arduino

The One (RRRduino) Pin Signal System! Part I NeoPixels: Yes, you read that right, you can control a whole signal system with up to 200 lights by using a single Arduino pin. And this was not my idea, all the credit and the patent goes to my friend Tom, but since I already had something using the same technology up and running using only a Nano, I do not feel too bad telling you about it. Short video first! There is a tiny 8 pin chip out there called a WS2811 which is a three channel LED driver, and you might find them on the interweb as NeoPixel LED Driver Chips. They need power and ground, typically 5 Vdc, and data to be put in the three registers inside the chip, one for each LEDs it can control. So, in most cases out there today, the LEDs connected are Red, Green and Blue (RGB for short) and by setting the three registers each with an 8 bit value (which in English means a value from 0 to 255, since 2 8 = 256, but since 0 is an acceptable value too, the maximum is 2 8 - 1

Not RRRduino, unless you have an MQTT connection via Ethernet or WiFi

JMRI code to connect to an MQTT broker, to publish and subscribe to the messages for signal masts. Of course, we agree to a standard for the MQTT topics, and since you were not here, we settled on "mast.xxxx" where xxxx is a number starting at zero. This MQTT topic is used as the User Name in a JMRI signal mast. Created as a Virtual Mast with the Aspect used as the payload in the message. And, yes, the device under the real mast needs to be programmed with the same name and code for each of the "aspect" payloads to be implemented. A yellow and red LED'd dwarf signal can not do a "Clear" aspect, so make sure "Clear" is maybe set to yellow for "Approach" as well.    Virtual Masts with agreed upon User Names. Comments are for the One Wire Signals on the NeoPixel string (see prior post)   Virtual Mast The Jython (or Python) code shown here below, is to attach a Listener to each Signal Mast, and to publish a message