Accessing DFPlayer from multiple arduinos

Moin.

I'm trying to figure out a project that would require 2 or 3 arduino nano, and all 3 of them should be able to play a different mp3 file when needed. Is it possible to have all 3 of them access the same serial port on a DFPlayer mp3 module, i.e. by means of diodes or similar? I've been googling and only kept finding the reverse case, i.e. using multiple mp3 modules on one arduino.

Multiple serial lines on the same port is asking for trouble.

You could have one run the player and be an SPI bus master, hang the other Arduinos on the bus as slaves that the master polls when the player is idle.

You could connect the Arduinos and player in a ring with each TX connected to the RX of the next one. Each board can send text as long as the next one copies it and sends it along, the player will not do so but it will send feedback and each Arduino has to be made to not step on music being played.

added: or you could use ESP8266 wifi boards and skip the wires. You still need to make some kind of traffic control if you want to make sure a sound file gets to finish before the next starts.

Thanks for the info. ESP8266 would be by far the cleanest way, but I really don't want to use 4 of them with additional wifi floating around in an already flooded apartment.. plus, I have a bunch of Arduinos laying around still that I can use.

Do you happen to know a source for a "serial forwarding" example?

Easy. Just use 1 Nano. Then there is no problem.

Using multiple Arduino in the same project is sometimes necessary, but otherwise a mistake. Many beginners make this error. At this point, you have not described the rest of your project, so at this point I would assume using multiple Arduino would be a mistake.

You're right, it might be possible to do it all with a single Nano, but I am not sure if that's not way beyond my time and skill limit right now.

Simply put, the project is a kitchen timer very specific to my needs:

  • 3 rotary knobs to set the time, using rotary encoders with pushbutton
  • 3 I2c 7-segment LCD displays to show the time
  • 2 additional buttons to set 2 specific timers (these are optional, but nice to have)
  • The whole thing should be able to play a unique alert mp3 sound for each of the 5 alarms

I have worked with the DFPlayer before, at least. But I'm not sure if I even have enough inputs for all the rotary encoders + their buttons + 2 extra buttons, plus 3 software I2c ports for the displays. But I'm still in the planning phase, I got the rotary encoders and displays on the way, but they will take a while.

Sounds like 1 Arduino will be fine. Post a link to your i2c displays please. Most will have some kind of pins or jumpers to set different address, so you can attach all of them to the normal i2c pins.

They're generic TM1637 displays, with no jumpers that I can find.

arakon: They're generic TM1637 displays, with no jumpers that I can find.

Bad news, tm1637 is not i2c. If they were sold to you that way, complain and get a refund. Buy displays with ht16k33 chip instead. If they were sold as "2-wire interface" then you can't complain because it is true that the interface uses 2 wires. But it is not i2c.

Also, tm1637 are not LCD displays, they are LED. But maybe that was just a typo?

With tm1637 you may be able to share the data wires between the 3 displays and have 3 separate clock wires. I'm not certain of that, I've never tried it, but it would save you a couple of pins.

So... 4 Arduino pins for the displays (hopefully), 9 pins for the rotary encoders, 2 more for buttons and one for the DFplayer. 16 in total. Using the analog pins as digital pins, you should have enough.

Ah, I forgot the Nano has 2 extra pins, D6 & D7. They are analog only, and have no internal pull-ups, but as long as you use external pull-up resistors, you can read buttons connected to them with analogRead().

Oops.. yes, LED of course. They were sold without much info at all, unfortunately I had only looked up some basics first and that turned out to be "2 wires, i2c".. found out later that it's an "i2c like" interface instead.

Thanks for the info so far. Just gotta figure out how to allow 5 independant timers to run down without them pausing input from the encoders.

That’ll just happen: millis() will continue in the background as normal while your code checks the encoders.

PaulRB: Ah, I forgot the Nano has 2 extra pins, D6 & D7. They are analog only, and have no internal pull-ups, but as long as you use external pull-up resistors, you can read buttons connected to them with analogRead().

Default analog read is very slow, blocks > 1600 cycles. OTOH you can connect many buttons with different resistors to 1 analog pin. Good for 1 button at a time, DFPlayer Mini has 2 pins set up to do that according to docs.

Buttons (with diode and optional debounce cap ea) in a matrix save on pins, can read multiple buttons down at once and read really fast without blocking.

With parallel to serial shift registers on SPI bus you can read loads of buttons. Default SPI is 512KB/sec.

From the looks of it, the analog pins can also be used to drive the displays, so that'd free up some digital pins?

GoForSmoke: Default analog read is very slow, blocks > 1600 cycles

True, but since accuracy is not important, this can be sped up significantly. Cross that bridge if/when you come to it.

GoForSmoke: Buttons (with diode and optional debounce cap ea) in a matrix save on pins, can read multiple buttons down at once and read really fast without blocking.

Also true. Would you recommend having the rotary encoder A&B outputs as part of that matrix? It's easy to miss edges, and having to scan them as part of a matrix would make it even easier to miss edges.

If the A&B encoder outputs are not part of the matrix, then the OP has only 5 buttons, which would require a 3x2 matrix and you have no pin savings.

BUT back to the idea mentioned in the first post: using doides, 5 buttons could be encoded into 3 pins, provided they will not be pressed simultaneously, which, by the OP's description, they might not?

arakon: From the looks of it, the analog pins can also be used to drive the displays, so that'd free up some digital pins?

The analog pins are also digital pins, you can use any you want in any way you want. Except A6 & A7 which are analog only, so they could be used to read buttons (albeit slowly) but can't be used as outputs.

Buttons will never be used at once/same time, so that’s not an issue. Neither is accuracy, for that matter… It’s a kitchen timer, whether the pasta is done after 20 minutes or 20 minutes and 30 milliseconds isn’t critical.

If I find that I don’t have enough button pins, I’ll probably go for the resistor method with analogRead, as this would be the easiest to set up, and possibly extend.

I got the rotary encorders today, but am hitting a first snag… apparently the way the code is written, it’s not possible to run 3 encoder readings in parallel.
First, a disclaimer… I can’t really code. I can usually piece together projects from bits and pieces of examples and existing projects.
This is what I am using as a basis: Timer.ino by noveldevices
This works by itself (I redirected all display outputs for now to serial console).

This is my code so far (had to attach is, too large to use with the code tag)… please keep in mind that it’s a complete mess at this time, since I am still experimenting and am still missing half my hardware in the first place.
I triplicated all timers, variables etc for the 3 timers.

What works: The “tea” timers appear to be working okay. Pressing the button on the rotary encoder starts and stops a countup instead of down, which is consistent with the original code when the timer is set to zero.

What doesn’t work: Reading the encoder (I currently have only one hooked up, to pins 2/3). If I use my exact code and remove all references to timers/encoders 2 and 3 and the tea timers, it starts working, so my guess is that they somehow interfere with each other, possibly due to the “while” loop. If someone could nudge me in the right direction, it’d be greatly appreciated.

I apologize for any physical and mental pain my code monster might cause.

timer.ino (13.2 KB)

I haven't looked at your attachment but I did look at the code you linked to above. It uses a hardware interrupt to capture the signal edges caused by movement of the encoder, which is a good way to avoid missing edges, which is very easy to do otherwise. Unfortunately, most Arduino have only two interrupt pins to use this way, and you would need 3. Fortunately there may be a solution. The atmega chip can detect and respond to interrupts on any pin, but the Arduino core does not have any functions built-in to enable that to be used. There is a library (at least one, probably) that will add that capability to your sketch. It's called something like the "Pin Change Interrupt Library".

Thanks so far, that does explain why it doesn't work with 3 interrupts. I tried to figure out the interrupt library, but I'm completely lost so far.. I also found a direct encoder reading library that doesn't use interrupts, but that doesn't want to play nice with the rest of the code.. I'll keep digging. Edit: And now that I realized that the encoder libray keeps the absolute position and doesn't allow me to reset it, I managed to work around it to the point where I can read all 3 encoders' direction, which is all I really need, I guess. It seems fairly inefficient, though.. I'm seriously considering switching over to a Leonardo or an ESP8266.. the latter I have around, but I feel it may not have enough pins, the former I'd have to order.

Leonardo because it has more external interrupt pins? If you don't have a shield you want to use with it, I would go for Pro Micro instead.

But should be possible to get nano working with pin change interrupts. Post your best attempt. Actually, no it will be too big to post. Start a new sketch, just with code to read 3 encoders and print results to serial monitor. You can merge that with your other code later, once you know you've got it working.