Arduino MP3 player controled by 433MHz RF receive

Hello everyone,
I'm new here.
I want read MP3 files on my arduino nano, and control it with boutons on RF device.

For that, I use 433MHZ receive,

and I use MP3 DFPlayer,
https://www.amazon.fr/dp/B07Z5D1TX8?psc=1&ref=ppx_yo2ov_dt_b_product_details

I can read MP3 players, and I can associate action when I push buttons A, B, etc ....

I use RCSwitch.h and DFRobotDFPlayerMini.h librairies.

When trying to control my DFPlayer MP3 module, I encountered numerous detection issues. I suspect that the DFPlayer MP3 module heavily utilizes my Arduino's resources, and I might not be using interrupts correctly on pin D2 with RCSwitch. The provided code example was not very helpful, and when I declared my function to decode received signals as an interrupt, it didn't work as expected.

Someone have an Idea ?

void setup() {
  initRFDevices();
  INITDFPLAYER();
  init_pin();
  setVolume(15);
  Serial.begin(9600);
  if(DEBEUG){Serial.begin(9600);
  }
  
  if(TEST){test();} // TEST not used = test function
}
unsigned long previousData = 0; // Variable to save the previousData

void loop();
    unsigned long data = RF_receive(); // Acquire value

    if (data != 0 && data != previousData) {
        rc_communication(data); // send new value
        previousData = data; // Update previousData
    }
}
void initRFDevices() { 
 
  mySwitch.enableReceive(digitalPinToInterrupt(INTERRUPT_PIN)); // enable Receive on interrupt pin D2

  Serial.begin(9600);
}

unsigned long RF_receive() {
  unsigned long key_push = 0;
  if (mySwitch.available()) {
    key_push = mySwitch.getReceivedValue();
    mySwitch.resetAvailable();
  }
  return key_push;
}
unsigned long RF_receive() {
  unsigned long key_push = 0;
  if (mySwitch.available()) {
    key_push = mySwitch.getReceivedValue();
    mySwitch.resetAvailable();
  }
  return key_push;
}

unsigned long previousInfo =0;
// Define a structure to map received values to corresponding actions
struct ActionMapping {
  unsigned long value;
  void (*action)();
};

// Define the actions corresponding to the values received
void actionToucheA() {
  Serial.println("Touche A Pressed");
  playMusic2(1);
}

void actionToucheB() {
  Serial.println("Touche B Pressed");
  stopMusic();
}

// Create a table mapping received values to corresponding actions
ActionMapping actions[] = {
  {ToucheA, actionToucheA},
  {ToucheB, actionToucheB}
  // Add other mappings as required 
};

// Function to manage RF communication 
void rc_communication(unsigned long info) {
  // Browse the mapping table to find the corresponding action 
  for (size_t i = 0; i < sizeof(actions) / sizeof(actions[0]); ++i) {
    if (info == actions[i].value) {
      // Execute the corresponding action 
      actions[i].action();
      return;
    }
  }
  
  // If no matching action found 
  Serial.println("No corresponding action found for the value received. ");
}
SoftwareSerial mySerial(7, 8); // RX, TX

DFRobotDFPlayerMini myDFPlayer;

void INITDFPLAYER(){
  mySerial.begin(9600);
  if (!myDFPlayer.begin(mySerial)) {
    Serial.println("DFPlayer Mini cannot be initialized! ");
    while (true);
  }
}
void playMusic(int tracknumber) {
  myDFPlayer.play(tracknumber); // play tracknumber
  K2000();
}
void pauseMusic() {
  myDFPlayer.pause(); // Pause music playback 
    K2000();

}

void stopMusic() {
  myDFPlayer.stop(); // Stop music playback 
    

}

void setVolume(int volume) {
  myDFPlayer.volume(volume); // Volume control 
}

void playMusic2(int tracknumber) {
  myDFPlayer.play(tracknumber); // play tracknumber
}

My receiver is connected to pin D2 with a 10kOhm pull-up resistor.


Here, you have the decoding done by RCSwitch.

Thanks a lot for your help

I don’t have your wireless modules and could only contribute on DFR Player aspects. And handicapped even at that as you don’t seem to have shown all your initialisation code?

I assume you are familiar with the player? Its sensitivity to supply voltage, timing, uSD file organisation, etc?

Have you tried to confirm your suspicion by stripping as much as possible except the DFR code?

Hello @Terrypin,

Thank you for your help.

You're right; I haven't shown all of my initialization code. However, I believe it might not be helpful for you because it's only the pinMode declarations for another function that is not used here.

void init_pin(void){  

  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(LED5, OUTPUT);
  pinMode(LED6, OUTPUT);
  pinMode(LED7, OUTPUT);
  pinMode(LED8, OUTPUT);

  Serial.begin(9600);
  
}

Yes, I'm familiar with this player, and my electric circuit is correct.

On my SD card, I have four files named 001, 002, 003, and 004.

If I only want to use my DFPlayer, it works correctly. I have already observed the serial communication with an oscilloscope, and all registers sent by the DFPlayer libraries are correct.

The problem seems to arise with the RCswitch library. I don't know how to use interrupts on D2 to send another command.

Here's a post outlining my problem without any solutions : Gate / Door opener RCSwitch interrupts problem

And at least a couple of #include lines for your libraries. Anything else….?

yes !

#include "Arduino.h"
#include <RCSwitch.h>
#include <DFRobotDFPlayerMini.h>
#include <SoftwareSerial.h>

All functions used were mentioned in my initial message.

I may not be able to help you. But others may be encouraged more if you post your full code.

Also, "I encountered numerous detection issues." is too vague. I suggest specifying the exact errors. Are you sure they are not arising from poor Tx/Rx?

Yes I'm sure !

My issue arises when attempting to use my receiver to control the DFPlayer. Initially, the first command is sent successfully. However, the microcontroller fails to read the pin value on the receiver's PIN when the DFPlayer is active. For example, if I send a command to play the first song and then try to stop it, the second action is not recognized.

To address this, I need to employ interrupts. However, with RCSwitch, I encounter difficulties setting up interrupts. I prefer not to configure my Arduino to continuously check pin D2; instead, I want to activate this check only in the event of an interrupt.

If you think function gived was not helpfull here my full project.

actions_complexes.cpp (502 Octets)

actions_complexes.h (284 Octets)

Connexions_arduino_nano.cpp (339 Octets)

Connexions_arduino_nano.h (609 Octets)

Fonctions_test.cpp (7,6 Ko)

Fonctions_test.h (296 Octets)

KIT_K2000.ino (1,4 Ko)

Receive_Communication.cpp (1,6 Ko)

Receive_Communication.h (679 Octets)

Sound.cpp (732 Octets)

Sound.h (363 Octets)

thank a lot !

As a forum newcomer, did you see this:

That included:

"Post all your code.

Without your code, all your code, we cannot provide any answers about your code, other than the most vague and probably unhelpful of answers."

I'm surprised, because you showed part of your code in your opening post, correctly formatted. I simply asked to see your full code. (As I said, so that I could see the DFR parts.) You've now posted a set of ten links instead. Nine appear to be to your own libraries. And the single sketch does not include the original code in your first post, so I'm a tad confused..

Although I'm not familiar with RCSwitch, FWIW I too suspect a timing conflict with the player module. I've found it particularly sensitive to delays after play/pause/stop commands. And inconsistent, both between similar sketches and physically different modules and clone brands. Have you tried using what I think of as 'the execute style' approach, as detailed here in section 3?
http://www.robotsforfun.com/datasheets/DFPlayer.pdf

As a hobbyist (not a programmer) I'm uncomfortable with such non-intutive code, but it may be worth trying..

To be honest, I don't really follow your code. For example, after reconstructing as much of it as I can, your function void K2000(), seems to do nothing. Is it simply meant as a zero delay after playing?

You're clearly a far more experienced programmer than me, so hopefully one of the gurus might be able to help. However, this seems a fairly quiet forum category. If you ask a moderator about moving the thread to Programming Questions, perhaps you might get a better response.

I just split my code into multiple files. All .c files contain functions, while all .h files contain declarations, prototypes, pinouts, etc.

In KIT_K2000.ino, I call functions to execute.

All functions related to the DFPlayer are in Sound.cpp and Sound.h.

All small test functions are in Functions_test.cpp and Functions_test.h.

All receiver communications are in Receive_Comunication.cpp and Receive_Communication.h.

I'm using this approach because I don't want to have a big file with all my functions. Afterwards, I call functions in the .ino file to run my final program.

How can I contact a moderator to move the thread? I'm new to the Arduino forum.

I’ve done so on your behalf, using the Report > Other icon to the right of the Link icon at bottom right.

I note that you have again failed to answer several of my earlier questions.

EDIT, Tue 7 May 2024 15:32
But I also see that if you own the thread you can do it yourself. :slightly_smiling_face:
Use the heavy pencil icon and choose new category from the drop-down.

I have moved the topic as requested.

Carry on.

Now yes :slight_smile: !

Yes sorry,

On this datasheet : "Supports asynchronous serial communication mode, via which accept serial commands sent by upper computer."
As I understand, it refers to a PC or another microcontroller.

Yes, it's simply a function that has been defined but without any code implemented yet. I was in the process of writing it.

find ! Thanks a lot !

Thanks !

1 Like

On the internet, I have read this:
https://openclassrooms.com/forum/sujet/arduino-rcswitch

"So, the RCSwitch can't receive data while this function is running, and there's no other solution than to change the microcontroller for one that supports DMA (any ARM microcontroller) in order to be able to send data without blocking the rest of the code, or to use 2 Arduinos."

"The ATmega328p doesn't have DMA technologies, and it's not an ARM processor.

So, if anyone can confirm that, :slight_smile: !!!

Maybe they have another alternative. If not, I will be obligated to recreate a new PCB with 2 microcontrollers. One for decoding RF transmission and another to control LEDs and the DFplayer."

One ISP communication between us, and interrupt signal for the microcontroller to control the DFPlayer.

Here is the datasheet of the ATmega328p :
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf

Hope you get some expert assistance with your project, despite the rather discouraging news from that other site.

I expect you're also aware of this source too?
https://www.airspayce.com/mikem/arduino/RadioHead/

Sorry for responding only now, but my problem is that the Arduino Nano doesn’t have DMA (Direct Memory Access), which is the solution.

I tested my module on an STM32, which does have DMA, and it works perfectly. If anyone else is facing this issue, you can switch to STM32, ESP32, or even an Arduino Nano IoT, for example.

The ATmega328p is a very old microcontroller, so it doesn’t have DMA technology.