Lecture fichier MP3 (DFPlayer) avec RFID

Bonjour,

j’avais fait un peu d’Arduino il y a une dizaine d’années et j’y reviens lentement maintenant.

Mon projet est de lire un fichier mp3 avec un DFPlayer lorsqu’un badge RFID est à proximité du capteur.

Voici mon code actuel

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <SPI.h>
#include <RFID.h>

#define SS_PIN 10
#define RST_PIN 9

RFID rfid(SS_PIN, RST_PIN);

// Setup variables:
    int serNum0 = 0;
    int serNum1 = 0;
    int serNum2 = 0;
    int serNum3 = 0;
    int serNum4 = 0;
    
SoftwareSerial mySoftwareSerial(6, 7); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
// void printDetail(uint8_t type, int value);

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  SPI.begin(); 
  rfid.init();
  
  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
  
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true){
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  
  myDFPlayer.volume(20);  //Set volume value. From 0 to 30
}

void loop()
{                
     presence_badge();
     if (serNum0 == 71
     && serNum1 == 208 
     && serNum2 == 174
     && serNum3 == 51
     && serNum4 == 10)   
     {
          myDFPlayer.play(1);
          serNum0 = 0;
          serNum1 = 0;
          serNum2 = 0;
          serNum3 = 0;
          serNum4 = 0;
      }
}

void presence_badge()
{
 if (rfid.isCard()) {
        if (rfid.readCardSerial()){ 
            if (rfid.serNum[0] != serNum0
                && rfid.serNum[1] != serNum1
                && rfid.serNum[2] != serNum2
                && rfid.serNum[3] != serNum3
                && rfid.serNum[4] != serNum4
                )
                                       {      
                                            serNum0 = rfid.serNum[0];
                                            serNum1 = rfid.serNum[1];
                                            serNum2 = rfid.serNum[2];
                                            serNum3 = rfid.serNum[3];
                                            serNum4 = rfid.serNum[4];
                                       }
                                  }
                    }
rfid.halt();
}

Le problème est que, lorsque j’approche le badge, le capteur le lit bien, mais il faut éloigner le badge pour que la lecture du fichier audio ne se fasse.
L’objectif est quand le badge reste à proximité du capteur.

J’ai cherché 2 jours dessus, en fouinant ci et là sur le net, mais sans résultat.

Quelqu’un peut m’aider sur ce sujet ?

Merci beaucoup

vos cartes RFID ont un identifiant sur 5 octets ? quel hardware ?

quelle bibliothèque utilisez vous ? la plus fréquente c'est celle de Miguel Balboa MFRC522

Je pense que c’est celle qu’on trouve ici, le Github serait ici (auteur Henri de Jong)

Moi, je mettrais une variable booléenne pour savoir que le badge a été reconnu, et ne pas le relire, ni relancer la lecture dans ce cas. Ça pourrait être fait comme ça (pas testé, et ça pourrait certainement être optimisé) :

#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <SPI.h>
#include <RFID.h>

#define SS_PIN 10
#define RST_PIN 9

RFID rfid(SS_PIN, RST_PIN);

// Setup variables:
int serNum0 = 0;
int serNum1 = 0;
int serNum2 = 0;
int serNum3 = 0;
int serNum4 = 0;
bool badgeOK = false;

SoftwareSerial mySoftwareSerial(6, 7); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
// void printDetail(uint8_t type, int value);

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  SPI.begin();
  rfid.init();

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  myDFPlayer.volume(20);  //Set volume value. From 0 to 30
}

void loop()
{
  if (!badgeOK) {
    badgeOK = presence_badge();
    myDFPlayer.play(1);
  }
}

bool presence_badge()
{
  if (rfid.isCard()) {
    if (rfid.readCardSerial()) {
      if (rfid.serNum[0] != serNum0
          && rfid.serNum[1] != serNum1
          && rfid.serNum[2] != serNum2
          && rfid.serNum[3] != serNum3
          && rfid.serNum[4] != serNum4
         )
      {
        serNum0 = rfid.serNum[0];
        serNum1 = rfid.serNum[1];
        serNum2 = rfid.serNum[2];
        serNum3 = rfid.serNum[3];
        serNum4 = rfid.serNum[4];
      }
    }
  }
  rfid.halt();
  if (serNum0 == 71
      && serNum1 == 208
      && serNum2 == 174
      && serNum3 == 51
      && serNum4 == 10) return true;
  return false;
}

le test

if (rfid.serNum[0] != serNum0
          && rfid.serNum[1] != serNum1
          && rfid.serNum[2] != serNum2
          && rfid.serNum[3] != serNum3
          && rfid.serNum[4] != serNum4
         )
      {
        serNum0 = rfid.serNum[0];
        serNum1 = rfid.serNum[1];
        serNum2 = rfid.serNum[2];
        serNum3 = rfid.serNum[3];
        serNum4 = rfid.serNum[4];
      }

ne sert vraiment pas à grand chose, c'est plus rapide de les copier dedans même si elles sont identiques...

et sans doute utilisez un tableau d'octets (unsigned char ou uint8_t) au lieu des int et faire un memcpy() pour dupliquer les infos vu que serNum est déclaré comme cela unsigned char serNum[5];et vous pouvez utiliser alors memcmp() pour comparer 2 numéros

const uint8_t bonneCarte[] = { 71, 208, 174, 51, 10};
...
if (memcmp(rfid.serNum, bonneCarte, 5) == 0) { /* match */ ...} else {/* no match */...}

Merci à tous pour ces premières réponses.

@J-M-T: le code était fait avec la bibliothèque de Henri de Jong effectivement.

J'ai refais d'autres tests depuis avec celle de Miguel Balboa qui est plus utilisé et donc avec plus d'exemple sur internet.
J'ai fait un premier tuto pour déjà allumer des leds suivant les badges présentés et déjà ça, ça fonctionne.

J'ai enlevé le premier test en mettant directement les valeurs du badge dans la vérification.

@lesept : merci pour le code fourni, on a plus besoin d'enlever le badge pour commencer la lecture. Seulement elle continue même quand on enlève le badge. Le but est que la musique s'arrête une fois que le badge est enlevé. Mais c'est déjà mieux que ce que j'avais réussi à faire tout seul. Un grand merci.

J'imagine que le mieux pour maintenant détecter si le badge est toujours présent c'est de continuer à ajouter des booléens ?

Question annexe :
j'ai fait un essai tout simple avec :

void loop()
{
    if (rfid.isCard())
    {      
            myDFPlayer.play(1);     
    }
}

Et là encore, tant que le badge est présent, il ne lance pas la lecture. Est-ce que la fonction (rfid.isCard()) est "bloquante" ? C'est à dire que tant qu'on fait pas un rfid.halt, il ne pourra pas passer à la suite du programme ?

Merci pour votre aide

Oui, je pensais que c'était ce que tu voulais.
Dans ce cas, la loop peut tout simplement devenir :

void loop () { if (presence_badge()) myDFPlayer.play(1); }

Si ça ne marche pas, il faut faire autrement (un peu usine à gaz, il doit y avoir plus simple) :

bool musicOK = false;

void loop()
{
  badgeOK = presence_badge();
  if (badgeOK && !musicOK)  {
     musicOK = true;
     myDFPlayer.play(1);
  }
}

Si tu passes à l'autre bibliothèque, tu peux t'inspirer de ça...

J’ai avancé un peu sur mon projet, mais … ça ne fonctionne toujours pas.

Voilà le code avec les dernières avancées

#include "Arduino.h"
#include <SoftwareSerial.h>
#include "DFRobotDFPlayerMini.h"
#include <SPI.h>
#include <MFRC522.h>

SoftwareSerial mySoftwareSerial(6, 7); // RX, TX
DFRobotDFPlayerMini myDFPlayer;

#define SS_PIN 10 
#define RST_PIN 9 

MFRC522 rfid(SS_PIN, RST_PIN); 

#define led_verte 3 
#define led_rouge 4 

String badgeOk[]={"47 d0 ae 33"};

int etat_led_verte = 0;
unsigned long temps_defini = 2000;

void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200); 
  SPI.begin();
  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while (true) {
      delay(0); // Code to compatible with ESP8266 watch dog.
    }
  }
  Serial.println(F("DFPlayer Mini online."));
  myDFPlayer.volume(20);  //Set volume value. From 0 to 30 



  // Init MFRC522 
  pinMode(led_verte,OUTPUT); 
  pinMode(led_rouge,OUTPUT); 

  // led eteintes a l'init 
  digitalWrite(led_verte,LOW); 
  digitalWrite(led_rouge,LOW);

// Init SPI bus 
rfid.PCD_Init();

}
void loop()
{
  if(detection_badge() == true)
  {
     digitalWrite(led_verte,HIGH);
     digitalWrite(led_rouge,LOW);
     unsigned long start=millis();
     while(detection_badge())
     {
        if(millis()>=(start+temps_defini))
        {
//            Serial.print("-detecter-");
//            delay(50);
//            digitalWrite(led_rouge, LOW);
            while(detection_badge()); 
            break;
        }
      }
    }
  else
  {
      digitalWrite(led_rouge,HIGH);
      digitalWrite(led_verte,LOW);
  } 
}
  
bool detection_badge()
{
  if (rfid.PICC_IsNewCardPresent())
  {  
     if (rfid.PICC_ReadCardSerial())
     {
        String badge=String(rfid.uid.uidByte[0],HEX) + " " + String(rfid.uid.uidByte[1],HEX) + " " + String(rfid.uid.uidByte[2],HEX) + " " + String(rfid.uid.uidByte[3],HEX);
        for(int y = 0; y < (sizeof(badgeOk)/sizeof(String)) ; y++)
        {
          if(badgeOk[y] == badge)
          {
            return true; 
           }
          else return false;
          rfid.PICC_HaltA();  
        }
     }
     else return false;
  }
}

Donc là, j’ai un système qui allume la LED verte uniquement quand le badge est présent, et la LED s’éteint dès qu’on retire le badge. J’ai plus qu’à faire pareil avec le DFPlayer.

J’ai essayé de le placer ici :

void loop()
{
  if(detection_badge() == true)
  {
     digitalWrite(led_verte,HIGH);
     digitalWrite(led_rouge,LOW);
     myDFPlayer.play(1)
     ...

Quand je pose le badge, la LED verte s’allume toujours, puis la petite led bleue du DFPlayer s’allume aussi, mais la musique ne se lance réellement que lorsque que je retire le badge.

J’ai essayé très rapidement de lancer la lecture sur le changement de statut de la LED verte, mais ça n’avait pas eu l’air de fonctionner. Je referais un essai.

Je ne comprends pas pourquoi ça bloque.
Si quelqu’un a une idée, je suis preneur.

C’est normal, ton code lance la musique continuellement. Il ne peut effectivement la jouer que lorsque tu arrêtes de la lancer.
Mets un booléen qui détecte le premier passage du badge. Tu lances la musique lorsque ce booléen passe à true, et tu l’arrêtes lorsque le badge n’est plus présent

J’ai pas tout à fait comme ça, mais c’est une méthode approchante. J’ai mis un compteur qui s’incrémente à chaque lecture du badge et la musique ne se lance que lorsque le compteur est à 1.
Je repasse le compteur à 0 dès que le badge est enlevé, et j’obtiens le fonctionnement que je voulais.

Merci pour votre aide vraiment précieuse !