SONS et LUMIERES simultanés

Bonjour,

Je suis totalement novice (48h) dans le monde Arduino mais j'ai dû m'y mettre pour un projet spécifique.
Malgré que je sois une tanche j'ai réussi à faire fonctionner ce que je voulais, sauf que mes 2 loops doivent tourner en simultané plus ou moins en permanence, à savoir:
une loop de sons mp3 via dfplayer (fonctionne très bien en solo)
une loop de leds rgb séquencées en fading (fonctionnent très bien en solo)

en voulant ''grouper'' les 2 codes, le résultat est que mes leds jouent 1 séquence, puis les sons prennent le relais mais les leds ne jouent plus la séquence et restent allumées sur une couleur.
Dans les 2 cas ils sont en fonction delay.
Après quelques recherches j'ai cru comprendre que le plus adapté était d'utiliser millis et non delay, mais honnêtement ça me dépasse un peu.
Bien que j'arrive à assimiler le principe, question programmation je suis quasi zéro.

y aurait-il un code simplifié de faire tourner mon arc en ciel de leds en même temps que ma séquence de sons?
ou une piste pour m'aider svp

(arduino UNO r3)

un immense merci d'avance !

Voici mon code (enfin, des codes copiés-collés-modifiés, plutôt)

#include "Arduino.h"

#include "SoftwareSerial.h"

#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX

DFRobotDFPlayerMini myDFPlayer;
const int ledRouge=6;
const int ledVert=5;
const int ledBleu=3;
const int DELAY=30;

void setup()

{
pinMode(ledRouge, OUTPUT); //Patte 6 reliée à la cathode de la LED rouge
pinMode(ledVert, OUTPUT); //Patte 5 reliée à la cathode de la LED vert
pinMode(ledBleu, OUTPUT); //Patte 3 reliée à la cathode de la LED bleu
mySoftwareSerial.begin(9600);

Serial.begin(115200);

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);

}

Serial.println(F("DFPlayer Mini online."));

myDFPlayer.volume(25); //Set volume value. From 0 to 30

}

void loop()

{
// fade from green to blue
for(int i=0; i<255; i++) {
analogWrite(ledRouge, 0);
analogWrite(ledVert, 255-i);
analogWrite(ledBleu, i);
delay(DELAY);
}

// fade from blue to red
for(int i=0; i<255; i++) {
analogWrite(ledRouge, i);
analogWrite(ledVert, 0);
analogWrite(ledBleu, 255-i);
delay(DELAY);
}

// fade from red to green
for(int i=0; i<255; i++) {
analogWrite(ledRouge, 255-i);
analogWrite(ledVert, i);
analogWrite(ledBleu, 0);
delay(DELAY);
}
myDFPlayer.play(1); //Play the first mp3

delay(5000);

myDFPlayer.next(); //Play next mp3

delay(5000);

myDFPlayer.next(); //Play next mp3

delay(5000);

myDFPlayer.next(); //Play next mp3

delay(5000);

}

La solution du fainéant serait de faire une fonction avec ton animation de leds et d'appeler cette fonction en boucle à la place de tes delay (5000), la boucle étant réglée pour durer les 5000 ms en question.

Pour régler cette durée, tu peux utiliser millis. La loop deviendrait alors simplement

for (byte i=1;i<5;i++) {
myDFPlayer.play(i);
unsigned long chrono =millis () ;
while (millis () - chrono < 5000) animation () ;
}

Et tu crées une fonction en déplaçant tes lignes de code qui allument les leds entre les lignes

void animation () {
// tes lignes ici
}

Un très grand merci ! c'est génial
je suis en train de tester donc la séquence de leds ""tourne"" bien pendant que les sons sont joués

en revanche je rencontre un petit souci avec ces derniers, aurais-je supprimé (ou pas) quelque chose qu'il ne faut pas?
le souci est le suivant:
la 1ère piste joue une dizaine de secondes
la 2eme piste joue une quinzaine,
la suivante une bonne vingtaine et la 4ème (dernière) ne lit qu'une demi seconde et tourne en boucle ou revient aux précédentes comme un disque rayé

une idée?

mon code se retrouve donc ainsi:

#include "Arduino.h"

#include "SoftwareSerial.h"

#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11); // RX, TX

DFRobotDFPlayerMini myDFPlayer;
const int ledRouge=6;
const int ledVert=5;
const int ledBleu=3;
const int DELAY=30;

void setup()

{
pinMode(ledRouge, OUTPUT); //Patte 6 reliée à la cathode de la LED rouge
pinMode(ledVert, OUTPUT); //Patte 5 reliée à la cathode de la LED vert
pinMode(ledBleu, OUTPUT); //Patte 3 reliée à la cathode de la LED bleu
mySoftwareSerial.begin(9600);

Serial.begin(115200);

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);

}

Serial.println(F("DFPlayer Mini online."));

myDFPlayer.volume(25); //Set volume value. From 0 to 30

}

void animation()

{
// fade from green to blue
for(int i=0; i<255; i++) {
analogWrite(ledRouge, 0);
analogWrite(ledVert, 255-i);
analogWrite(ledBleu, i);
delay(DELAY);
}

// fade from blue to red
for(int i=0; i<255; i++) {
analogWrite(ledRouge, i);
analogWrite(ledVert, 0);
analogWrite(ledBleu, 255-i);
delay(DELAY);
}

// fade from red to green
for(int i=0; i<255; i++) {
analogWrite(ledRouge, 255-i);
analogWrite(ledVert, i);
analogWrite(ledBleu, 0);
delay(DELAY);
}
}
void loop(){
for (byte i=1;i<5;i++) {
myDFPlayer.play(i);
unsigned int chrono =millis () ;
while (millis () - chrono < 5000) animation () ;
}
}

J'ai corrigé une erreur que tu n'as pas prise en compte
C'est unsigned long et non unsigned int

Quel est ton besoin pour la lecture des pistes ? Ton animation dure 255303 ms soit 23 secondes. Donc impossible pour le code comme il est de changer de piste au bout de 5 secondes.

Si tu veux juste jouer les 5 premières secondes des pistes audio, il faut refaire le code différemment. C'est pour ça que je parlais de solution du fainéant...

Tu peux aussi accélérer les fades en diminuant la valeur de DELAY...

merci,

je cherche de toute façon une solution facile, donc de fainéant ça me convient :slight_smile:
je comprend mieux donc, la lecture des pistes dure la durée de séquence des leds, ok
donc soit je modifie le délai des leds pour arriver à 5 sec soit je rallonge les pistes audio

mais le coup des 5 sec n'est pas indispensable:

est-il plus simple de zapper le délais entre les pistes, si on fait juste un dfplayer.next :

si j'ai une piste de 5 sec, une poste de 30sec, une piste de 3 min...
si je lui donne pas d'instructions de délai entre les pistes, il va automatiquement les lire en entier les unes après les autres.
si c'est plus simple je peux partir sur ça. c'est même plus logique.

en revanche la séquence des leds étant la reproduction d'un tuning échelle réelle j'aimerais autant rester à peu près dans ce timing.

est-ce donc envisageable (je récapitule espérant être assez claire):

le player part de la piste 1 et lit les suivantes entièrement automatiquement (sans paramétrage de delay)
et pendant ce temps mon animation de leds continue à tourner

?
encore merci

La bibliothèque a une méthode appelée readState qui permet de savoir si un morceau est terminé. Mais il va falloir retourner la chaussette pour l'utiliser : ce sera l'animation qui tournera et vérifiera de temps en temps si le morceau en cours est terminé.

ReadState encore la valeur 513 pendant que le morceau est en cours.

Donc il faut éliminer la fonction, et la remettre dans la loop en modifiant un peu :

 // fade from green to blue
  for(int i=0; i<255; i++) {
    analogWrite(ledRouge, 0);
    analogWrite(ledVert, 255-i);
    analogWrite(ledBleu, i);

if (myDFPlayer.readState()!=513) {
trackNumber = (trackNumber+1)%totalTracks;
myDFPlayer.play(trackNumber);
} 

    delay(DELAY);
  }

  // fade from blue to red
  for(int i=0; i<255; i++) {
    analogWrite(ledRouge, i);
    analogWrite(ledVert, 0);
    analogWrite(ledBleu, 255-i);

if (myDFPlayer.readState()!=513) {
trackNumber = (trackNumber+1)%totalTracks;
myDFPlayer.play(trackNumber);
} 

    delay(DELAY);
  }

  // fade from red to green
  for(int i=0; i<255; i++) {
    analogWrite(ledRouge, 255-i);
    analogWrite(ledVert, i);
    analogWrite(ledBleu, 0);

if (myDFPlayer.readState()!=513) {
trackNumber = (trackNumber+1)%totalTracks;
myDFPlayer.play(trackNumber);
} 

    delay(DELAY);

Il faut définir des choses dans l'en tête

int trackNumber = 1;
const int totalTracks = 5;

Et lancer la lecture de la première track en fin de setup

myDFPlayer.play(1);

À tester...

Merci mille fois pour le temps consacré à m'aider, j'apprécie énormément.
Je testerai ça sous peu

cela semble fonctionner (sauf que le delay des leds doit être placé avant le if sinon c'est le son qui tourne au ralenti :slight_smile: )

quelques ajustements à faire car il ne lit pas toutes les pistes en entier. Faut que je trouve comment régler cela mais encore merci, ton aide a été ô combien précieuse.

EDIT:
j'ai résolu le problème en utilisant enableloopall au lieu de play, et retiré la fonction du loop

Super !