ultra son et MP3

Bonjour à tous,

Je tente de faire un petit montage (que je pensais simple) qui consiste a jouer un mp3 aléatoirement quand mon capteur ultrason est a une distance de moins de 50cm.

Si je veux jouer un son seul ou dans un répertoire (CMD_PLAY_W_INDEX, CMD_PLAY_WITHFOLDER, …) cela fonctionne, par contre avec CMD_SHUFFLE_PLAY que j’ai défini pas moyen.

Mon MP3 est un yx5300.

voici le sketch :

//code rearranged by Javier Muñoz 10/11/2016 ask me at javimusama@hotmail.com
#include <SoftwareSerial.h>

#define ARDUINO_RX 5//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6//connect to RX of the module

#define trigPin 13
#define echoPin 12


SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial wich pins are TX and RX

////////////////////////////////////////////////////////////////////////////////////

static int8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string
                                 //0X7E FF 06 command 00 00 00 EF;(if command =01 next song order) 
#define NEXT_SONG 0X01 
#define PREV_SONG 0X02 

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E))
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED
                
#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define CMD_SHUFFLE_PLAY 0X18//

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output
////////////////////////////////////////////////////////////////////////////////////


void setup()
{
  Serial.begin(9600);//Start our Serial coms for serial monitor in our pc
mySerial.begin(9600);//Start our Serial coms for THE MP3
delay(500);//Wait chip initialization is complete
   sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card  
delay(200);//wait for 200ms
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);

}

void loop()
{
  if(measureDistance(trigPin,echoPin)<50){
    
sendCommand(CMD_SET_VOLUME, 0X0F);//volume
sendCommand(CMD_SHUFFLE_PLAY, 0);//player
delay(5000);//wait to avoid errors

}
delay(300);
}

void sendCommand(int8_t command, int16_t dat)
{
 delay(20);
 Send_buf[0] = 0x7e; //starting byte
 Send_buf[1] = 0xff; //version
 Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
 Send_buf[3] = command; //
 Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
 Send_buf[5] = (int8_t)(dat >> 8);//datah
 Send_buf[6] = (int8_t)(dat); //datal
 Send_buf[7] = 0xef; //ending byte
 for(uint8_t i=0; i<8; i++)//
 {
   mySerial.write(Send_buf[i]) ;//send bit to serial mp3
   Serial.print(Send_buf[i],HEX);//send bit to serial monitor in pc
 }
 Serial.println();
}

long measureDistance(int trigger,int echo){
   long duration, distance;
  
  digitalWrite(trigger, LOW);  //PULSE ___|---|___
  delayMicroseconds(2); 
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10); 
  digitalWrite(trigger, LOW);
  
  duration = pulseIn(echo, HIGH);
  distance = (duration/2) / 29.1;
   Serial.println("distance:");
   Serial.println(distance);
  return distance;

}

Merci d’avance pour tout éclairage que vous pourrez m’apporter.

Amicalement,

Emorej

As-tu testé l'exemple de la bibliothèque ArduinoSerialMP3Player ?

Oui, c’est d’ailleurs une partie de mon sketch.

Mais la commande shuffle n’est pas utilisée (ou alors je ne l’ai pas vue…)

Tu as raison, j'avais vu la ligne 45 mais pas cherché dans la suite.

Tu peux tester en ajoutant ce qu'il faut pour le faire marcher, du genre :

case 'f':
      Serial.println("Shuffle");
      sendCommand(CMD_SHUFFLE_PLAY  , 0x00);
      break;

Est-ce que tu vois quelque chose sur la console lorsque tu testes le shuffle ? Ces lignes devraient afficher un message

// Check for the answer.
  if (mp3.available())
  {
    Serial.println(decodeMP3Answer());
  }

Cela ne marche toujours pas... Quand je met un 0x00 ou 0 voici ce qu'il me retourne

distance: 8 7EFFFFFFFF6600FFFFFFFEF 7EFFFFFFFF618000FFFFFFEF

C'est bizarre : tu devrais obtenir

7EFF0618000000EF

|500x357Donc en effet, il y a une erreur quelque part.

Il y a ici un exemple de code qui utilise la fonction shuffle.

Il fait :

/** Random playing */
void shufflePlay() {
  send_kt_command(0x18, 0, 0, 20);
}

avec

/** Fonction de bas niveau pour envoyer une commande au module KT403A */
void send_kt_command(byte command, byte data_h, byte data_l, unsigned long cmd_delay) {
  Serial.write(COMMAND_BYTE_START);
  Serial.write(COMMAND_BYTE_VERSION);
  Serial.write((byte) 0x06);
  Serial.write(command);
  Serial.write((byte) 0x00);
  Serial.write(data_h);
  Serial.write(data_l);
  Serial.write(COMMAND_BYTE_STOP);
  // 16-bits checksum is optionnal
  delay(cmd_delay);
}

Essaye ce code...

Je rame un peu avec ce code…(mais je continue d’explorer)

De mon coté j’ai trouvé ceci :

void loop() {
  if (measureDistance(trigPin, echoPin) < 50) {
    int randTrackNo;
    randTrackNo = random(1, 6);
    sendCommand(CMD_PLAY_W_INDEX, randTrackNo);
    Serial.print("Playing track:");
    Serial.println(randTrackNo);
    delay(1000);  //wait to avoid errors
  }
  delay(300);
}

Ca fonctionne ,MAIS comme mes sons ne sont pas tous identique en minutage, si l’on reste dans les 50cm, un autre démarre etc…et c’est plutôt chiant de caler le “Delay” du coup…

Il faut que tu utilises un ‘drapeau’ : une variable qui indique qu’un morceau est en train d’être joué et qu’il ne faut pas faire de mesure pendant ce temps. Le temps en question, tu dois le décider : 1 secondes, 5 secondes ? Et tu chronomètres avec millis() : dès que ce temps est dépassé tu changes la valeur du drapeau.

Oulala, je replonge dans mon livre de chevet : "Arduino pour les nuls" :)

hello, me revoilà… :roll_eyes:

J’ai finalement opter pour l’option :

void loop() {
  if (measureDistance(trigPin, echoPin) < 50) {
    int randTrackNo;
    randTrackNo = random(1, 6);
    sendCommand(CMD_PLAY_W_INDEX, randTrackNo);
    Serial.print("Playing track:");
    Serial.println(randTrackNo);
    delay(1000);  //wait to avoid errors
  }
  delay(300);
}

Sauf qu’il ne lit que les nombres impairs ???

une idée?

Je précise avoir tester avec Nano et Uno. et que quand je fais un test de lecture avec CMD_PLAY_WITHFOLDER 0X0F en indiquant 0x0102 il me lit bien le n°002.mp3 du dossier 01...donc pas un problème de codage ou de fichier j'ai tester plusieurs modules mp3 yx5300 idem sur chaque.

J'ai trouver sur le forum un problème identique : https://forum.arduino.cc/index.php?topic=532053.0

Sinon pour aujourd'hui ce sera que les impaires :)

Il n’y a pas de raison qu’il ne joue que les impairs, random(1,6) renvoie un nombre entre 1 et 5 compris.
Par contre, c’est pas vraiment des nombres aléatoires, mais une série de nombres qui sera la même à chaque exécution.
Essaye d’ajouter

 randomSeed(analogRead(0));

dans le setup pour que les séries soient différentes.
Sinon, tu peux utiliser la bibli TrueRandom qui génère de l’aléatoire plus aléatoire…

Si tu veux faire un shuffle, tu peux le coder toi-même. Il suffit de faire une liste de nombres allant de 1 à ton nombre de pistes N et de la mélanger.
Ca peut se faire comme ça :

for (int i=0;i<100;i++) {
  int indice1 = random(1,N);
  int indice2 = random(1,N);
  int a = liste[indice1];
  liste[indice1] = liste[indice2];
  liste[indice2] = a;
}

100 est le nombre de fois que tu mélanges. Ce nombre peut être changé, je l’ai choisi au hasard.

Merci pour ta réponse encore une fois :wink:

j’ai bien ajouter randomSeed :

void setup() {
  Serial.begin(9600);  //Start our Serial coms for serial monitor in our pc
  mySerial.begin(9600);  //Start our Serial coms for THE MP3
  delay(500);  //Wait chip initialization is complete
  sendCommand(CMD_SEL_DEV, DEV_TF);  //select the TF card
  delay(200);  //wait for 200ms
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  randomSeed(analogRead(A0));
}

void loop() {
  if (measureDistance(trigPin, echoPin) < 10) {
    int randTrackNo;
    randTrackNo = random(1, 73);
    sendCommand(0x03, randTrackNo);
    Serial.print("Playing track:");
    Serial.println(randTrackNo);
    delay(1000);  //wait to avoid errors
  }
  delay(300);
}

Mais je t’assure qu’il ne lit que les impaires…un truc de fou :o

La broche A0 est bien libre ?

Regarde le tableau de la réponse #5 : il semble qu'il range les tracks par groupes de 2. Si tu envoies :

  • 7EFF0603000001EF : il lit la première
  • 7EFF0603000002EF : il lit la seconde Donc c'est un peu plus subtil : ton nombre aléatoire doit être choisi entre 1 et 73/2 = 36 (le nombre de groupes -- je ne suis pas sûr à 100% de ça) et tu dois faire un seconde tirage aléatoire (1 ou 2) pour choisir la première ou la seconde track...

C'est du moins comme ça que je le comprends.

Oui la broche A0 est bien libre, pour le 0x30 : 01, 02 etc... c'est les track pas des groupe? si? car si je fais sendCommand(0x03, 0x03); il me joue bien la piste 003.mp3 par contre si je fais sendCommand(0x03, 0x04); il ne joue rien...et si je fais sendCommand(CMD_PLAY_WITHFOLDER, 0x0104);, là le 004.mp3 du dossier 01 est bien joué.

là, voici ce qu'il me retourne :

distance: 182 distance: 5 7E FF 6 3 0 0 3F EF Playing track:63 distance: 182 distance: 141 distance: 141 distance: 138 distance: 138 distance: 139 distance: 11 distance: 8 7E FF 6 3 0 0 22 EF Playing track:34

le 63 est bien jouer, mais pas le 34...

Oui, mon explication était foireuse :( C'est bizarre cette histoire de nombre impair...

oui, je pige pas…et comme je le disais dans le topic : https://forum.arduino.cc/index.php?topic=532053.0 il a le même problème…bon, pour aujourd’hui j’ai renommer tout mes fichiers en impaire.mp3 par contre c’est possible de lui dire de ne sortir que les impaire? Ceci éviterait les blancs…

mon cade actuel :

#include <SoftwareSerial.h>

#define ARDUINO_RX 5  //should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6  //connect to RX of the module

#define trigPin 13  //for the distance module
#define echoPin 12

SoftwareSerial mySerial(ARDUINO_RX, ARDUINO_TX);//init the serial protocol, tell to myserial wich pins are TX and RX

////////////////////////////////////////////////////////////////////////////////////
//all the commands needed in the datasheet(http://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf)
uint8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string
//0X7E FF 06 command 00 00 00 EF;(if command =01 next song order)
#define NEXT_SONG 0X01
#define PREV_SONG 0X02

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E))
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
#define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED

#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output
////////////////////////////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(9600);  //Start our Serial coms for serial monitor in our pc
  mySerial.begin(9600);  //Start our Serial coms for THE MP3
  delay(500);  //Wait chip initialization is complete
  sendCommand(CMD_SEL_DEV, DEV_TF);  //select the TF card
  delay(200);  //wait for 200ms
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  randomSeed(analogRead(A0));
}

void loop() {
  if (measureDistance(trigPin, echoPin) < 200) {
    int randTrackNo;
    randTrackNo = random(0, 142);
    sendCommand(CMD_SET_VOLUME, 0x50);
    sendCommand(0x03, randTrackNo);
    Serial.print("Playing track:");
    Serial.println(randTrackNo);
    delay(5000);  //wait to avoid errors
  }
  delay(300);
}

void sendCommand(int8_t command, int16_t dat) {
  delay(20);
  Send_buf[0] = 0x7e; //starting byte
  Send_buf[1] = 0xff; //version
  Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
  Send_buf[3] = command; //
  Send_buf[4] = 0x00;  //0x00 = no feedback, 0x01 = feedback
  Send_buf[5] = (int8_t)(dat >> 8);  //datah
  Send_buf[6] = (int8_t)(dat);  //datal
  Send_buf[7] = 0xef;  //ending byte
  for (uint8_t i = 0; i < 8; i++) {
    mySerial.write(Send_buf[i]) ;  //send bit to serial mp3
    Serial.print(Send_buf[i], HEX);  //send bit to serial monitor in pc
    Serial.print(" ");
  }
  Serial.println();
}

long measureDistance(int trigger, int echo) {
  long duration, distance;

  digitalWrite(trigger, LOW);  //PULSE ___|---|___
  delayMicroseconds(2);
  digitalWrite(trigger, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger, LOW);

  duration = pulseIn(echo, HIGH);
  distance = (duration / 2) / 29.1;
  Serial.print("distance: ");
  Serial.println(distance);
  return distance;
}

emorej: si je fais

sendCommand(CMD_PLAY_WITHFOLDER, 0x0104);

là le 004.mp3 du dossier 01 est bien joué.

Je pense que tu as intérêt à utiliser cette commande : le 01 correspond au répertoire dans lequel sont rangés les fichiers. Si on met 00, il s'emmêle et loupe des tracks.

Le problème est identifié ailleurs. Il indique un site où on peut télécharger une autre bilbiothèque avec une commande simple pour lire une track :

myDFPlayer.play(1);