projet Halloween avec lumière synchronisée a la musique

Slt a tous me revoilà avec un nouveau projet qui comme d'habitude fonctionne très bien mais pas comme je le voudrais.

donc pour faire court dans quelque jours les gosses vont débarquer pour avoir des bonbon.
trop cool " ma famille et moi même sommes fan d'halloween "

cette année je voulais les effrayer un peu,

je donc trouvé le projet suivant :

avec un arduino uno , un dfplayer, un détecteur PIR, un HP 3W , et un led strip RGB plus quelques scary song

je veux détecter leurs arrivé, lire un MP3 et commander les led strip en fonction de cela. jusque la pas de souci et voici donc le programme qui fonctionne.

/*
    Projet d'annimation lumineuse halloween syncronisée en fonction 
    du son emis par un HP de 3W sur un DFplayer
*/


#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

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


const int buttonPin = 9;     // broche n9 sur PIR
int buttonState = 0;         // variable pour stocker le status du PIR
int busyPin = 5;             // broche n9 sur busy pin du MP3; // lecteur MP3 actif ou non
int busy = 0;
int LEDrouge = 6; //  broche n6 sur led strip rouge
int LEDverte = 7; //  broche n7 sur led strip vert
int LEDbleu  = 8; //  broche n6 sur led strip bleu

int sensorPin = A0;    // echantillonage de la sortie HP
int sensorValue = 0;  // variable pour stocker la valeur de l'echantillonage
int button = 0;

//***************************************SETUP*************************************


void setup () {
  
  pinMode(buttonPin, INPUT);
  pinMode(LEDrouge, OUTPUT);
  pinMode(LEDverte, OUTPUT);
  pinMode(LEDbleu, OUTPUT);
  
  pinMode(busyPin, INPUT);
  pinMode(buttonPin, INPUT);
  
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);  //utilisation de softwareSerial pour communiquer avec le mp3.
  myDFPlayer.volume(15);  //reglage volume. de 0 a 30

  static unsigned long temps = millis();
  

       //----Set different EQ----
  
  //  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  //  myDFPlayer.EQ(DFPLAYER_EQ_POP);
  //  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  //  myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
  //  myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
    myDFPlayer.EQ(DFPLAYER_EQ_BASS);

  
}

//.................................BOUCLE PRINCIPALE.........................................
void loop () {

  

  digitalWrite(LEDbleu, HIGH);
  digitalWrite(LEDverte, HIGH);
  digitalWrite(LEDrouge, HIGH);
  
  do {
    button = digitalRead(buttonPin); // ataché au detecteur PIR
     } while (button == 1);




  //myDFPlayer.play (5);  //Play haunted mp3
  myDFPlayer.next();  // lis le prochain morceau.
  

  delay(100);
  do {
    sensorValue = analogRead(sensorPin);

    
    
            if (sensorValue >= 550) {

              digitalWrite(LEDrouge, LOW);
              digitalWrite(LEDbleu, LOW);
              digitalWrite(LEDverte, LOW);
              delay (50); 
            }
            
                    if (sensorValue <= 500) {
                
                      digitalWrite(LEDrouge, LOW);
                      digitalWrite(LEDbleu, HIGH);
                      digitalWrite(LEDverte, HIGH);
                    }



    
    busy = digitalRead(busyPin);
  } while (busy == 0); // a zero quand le son est actif
}

//...................................... FIN DE LA BOUCLE ......................

Mon souci est que j'au un dizaine de titres , mais sont trop long : environ 6 minutes chaqun, je voulais donc
en lire qu'une parti environ 60 secondes , mais voila
mon prog se sert de la fonction Busy du DFplayer et donc je n'arrive pas a sortir de la boucle tant que le HP débité du son,

j'ai essayer une boucle millis mais je n'arrive pas a trouver le bon endroit pour la couler

si someone a une idée

merci a tous.

seb

Bonjour,

La fonction loop() n'est pas censée contenir des morceaux de code bloquant. Comment veux-tu gérer plusieurs actions en même temps si tu monopolises ton processeur sur une partie de code. Ta façon de structurer ton programme n'est pas bonne. Ta boucle loop() doit contenir une suite de fonctions qui teste rapidement les événements et agir en conséquence. Chaque fonction s'occupe d'une chose (boutons, gestion du lecteur mp3, détecteur, leds,...) et utilise les variables pour passer des informations aux autres.

merci a toi

je ne pense pas que mon code soit bloquant pour le moment

il utilise juste la fonction Busy du dfplayer qu'il test a chaque tour pour continuer a effectuer l'échantillonnage de la sortie HP.

d'une certaine manière je dis que c'est bloquant car tant que le morceau joué n'est pas fini et que le status de Busy ne change pas je n'arrive pas a sortir de cette boucle.

tandis que j'aimerais que seulement les 60 premiere seconde soit joué sans possibilité d'être coupé.
puis après les 60 premières secondes si le PIR capte un mouvement on passe le morceau suivant et ainsi de suite pour tous les autres morceaux.

après avoir bidouillé mon code dans tous les sens avec la fonction miles, la seule chose que j'arrive a faire
c'est par ex jouer un morceau 60s puis attente de 60s et ainsi de suite.

a priori je n'ai pas tout saisi dans cette fonction, en temps normal je me creuserai la tete jusqu'as ce que cela fonction mais la Halloween arrive , et je n'ai pas avancé sur la partie hardware. " impression 3D et sur la partie amplification du son et la partie contrôle lumineuse des led 3W RGB par IRL 520 mosfet .

merci man

goldoseb:
merci a toi

je ne pense pas que mon code soit bloquant pour le moment

il utilise juste la fonction Busy du dfplayer qu'il test a chaque tour pour continuer a effectuer l'échantillonnage de la sortie HP.

d'une certaine manière je dis que c'est bloquant car tant que le morceau joué n'est pas fini et que le status de Busy ne change pas je n'arrive pas a sortir de cette boucle.

tandis que j'aimerais que seulement les 60 premiere seconde soit joué sans possibilité d'être coupé.
puis après les 60 premières secondes si le PIR capte un mouvement on passe le morceau suivant et ainsi de suite pour tous les autres morceaux.

après avoir bidouillé mon code dans tous les sens avec la fonction miles, la seule chose que j'arrive a faire
c'est par ex jouer un morceau 60s puis attente de 60s et ainsi de suite.

a priori je n'ai pas tout saisi dans cette fonction, en temps normal je me creuserai la tete jusqu'as ce que cela fonction mais la Halloween arrive , et je n'ai pas avancé sur la partie hardware. " impression 3D et sur la partie amplification du son et la partie contrôle lumineuse des led 3W RGB par IRL 520 mosfet .

merci man

Bonjour
pourquoi utiliser la fonction busy du dfplayer ?
si tu detecte un mouvement tu lance le morceau N+1 que tu stop ( verif milli() - actuel) au bout de 60 secondes

Il suffit de stocker la valeur retournée de la fonction millis() dans une variable nommée par exemple start au démarrage du morceau.

    static unsigned long start = millis();

Ensuite au début de la boucle do while il faut comparer avec la durée voulue :

  do {
    if (millis() - start >= 60000)
        break;

@+

Ou faire comme dit Artouste, sauf si tu as des morceaux qui ont une durée inférieure à 60s.

merci pour vos commentaires

j'ai donc essayé d'inclure la fonction millis et comme dans mes essai cela donne toutes sortes de choses
mais pas celles attendues.

voici le code

do {
    button = digitalRead(buttonPin); // ataché au detecteur PIR
     } while (button == 1);




  //myDFPlayer.play (5);  //Play haunted mp3
  myDFPlayer.next();  // lis le prochain morceau.

   static unsigned long start = millis();
  
  
  do {


    if (millis() - start >= 5000)
        break;
    
    sensorValue = analogRead(sensorPin);

    
    
            if (sensorValue >= 550) {

              digitalWrite(LEDrouge, LOW);
              digitalWrite(LEDbleu, LOW);
              digitalWrite(LEDverte, LOW);
              delay (50); 
            }
            
                    if (sensorValue <= 510) {
                
                      digitalWrite(LEDrouge, LOW);
                      digitalWrite(LEDbleu, HIGH);
                      digitalWrite(LEDverte, HIGH);
                    }



    
    busy = digitalRead(busyPin);
  } while (busy == 0); // a zero quand le son est actif
}/code]

pourtant j'ai bien mis la fonction millis juste après la ligne de lecture du dfplayer

et au début de la boucle do/while      le comparateur de temps

seb @+

Essaie d'afficher les valeurs : la valeur de start et de millis() sur le moniteur série, en ajoutant un petit delay(1000) avant le while pour éviter que cela s'affiche trop vite.

goldoseb:
merci pour vos commentaires

j'ai donc essayé d'inclure la fonction millis et comme dans mes essai cela donne toutes sortes de choses
mais pas celles attendues.

voici le code

do {

button = digitalRead(buttonPin); // ataché au detecteur PIR
    } while (button == 1);

//myDFPlayer.play (5);  //Play haunted mp3
 myDFPlayer.next();  // lis le prochain morceau.

static unsigned long start = millis();
 
 
 do {

if (millis() - start >= 5000)
       break;
   
   sensorValue = analogRead(sensorPin);

if (sensorValue >= 550) {

digitalWrite(LEDrouge, LOW);
             digitalWrite(LEDbleu, LOW);
             digitalWrite(LEDverte, LOW);
             delay (50);
           }
           
                   if (sensorValue <= 510) {
               
                     digitalWrite(LEDrouge, LOW);
                     digitalWrite(LEDbleu, HIGH);
                     digitalWrite(LEDverte, HIGH);
                   }

busy = digitalRead(busyPin);
 } while (busy == 0); // a zero quand le son est actif
}/code]

pourtant j'ai bien mis la fonction millis juste après la ligne de lecture du dfplayer

et au début de la boucle do/while      le comparateur de temps

seb @+

Bonjour
Tu a un declencheur/initiateur d'evenement = PIR , c'est quoi exactement ?
les capteurs PIR cheap à peanuts € presentent un niveau "haut" aprés detection dont la durée peut etre +/- ajustée
ton souhait se resume à :
detecter un changement d'etat "PIR" de LOW à HIGH
lancer la lecture du morceau N
stopper la lecture du morceau N si durée > 60 seconde (si durée < le stop est automatique à la fin)

  • préparer le prochain morceau à suivre
  • attendre nouveau stimuli du PIR

slt c'est bien un détecteur de mvt cheap a vraiment peanuts 2,30€

mais pour le moment j'utilise un capteur ir encore plus cheap 0,50€ pour faire les tests

effectivement mon souhait et le suivant

-détecter un mouvement a plusieurs mètres avec mon PIR et donc un changement d'état High/Low

-lancer la lecteur d'un morceau

-ne pas pouvoir interrompre la lecture les 60 premières secondes puis pouvoir le faire seulement si il y as un changement d'état high/low et/ou interruption automatique a la fin du morceau

  • jouer un autre morceau après une nouvelle detection si les 60 sec se sont écoulé ou si le morceau et fini

c'est pour cela que j'utilise la fonction Busy

je fais des essai sur la fonction millis mais comme je le dis cela donne des truc bizarres , comme indiqué par M hbachetti je fais des essaie aussi avec le moniteur maintenant. pour y voir plus clair

des que j'ai fais des test je vous les posts.

grand merci @+

voici le code avec le moniteur et millis

/*
    Projet d'annimation lumineuse halloween syncronisée en fonction 
    du son emis par un HP de 3W sur un DFplayer
*/


#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

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


const int buttonPin = 9;     // broche n9 sur PIR
int buttonState = 0;         // variable pour stocker le status du PIR
int busyPin = 5;             // broche n9 sur busy pin du MP3; // lecteur MP3 actif ou non
int busy = 0;
int LEDrouge = 6; //  broche n6 sur led strip rouge
int LEDverte = 7; //  broche n7 sur led strip vert
int LEDbleu  = 8; //  broche n6 sur led strip bleu

int sensorPin = A0;    // echantillonage de la sortie HP
int sensorValue = 0;  // variable pour stocker la valeur de l'echantillonage
int button = 0;

//***************************************SETUP*************************************


void setup () {
  
  pinMode(buttonPin, INPUT);
  pinMode(LEDrouge, OUTPUT);
  pinMode(LEDverte, OUTPUT);
  pinMode(LEDbleu, OUTPUT);
  
  pinMode(busyPin, INPUT);
  pinMode(buttonPin, INPUT);
  
  Serial.begin (9600);
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);  //utilisation de softwareSerial pour communiquer avec le mp3.
  myDFPlayer.volume(15);  //reglage volume. de 0 a 30

  static unsigned long temps = millis();
  

       //----Set different EQ----
  
  //  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  //  myDFPlayer.EQ(DFPLAYER_EQ_POP);
  //  myDFPlayer.EQ(DFPLAYER_EQ_ROCK);
  //  myDFPlayer.EQ(DFPLAYER_EQ_JAZZ);
  //  myDFPlayer.EQ(DFPLAYER_EQ_CLASSIC);
    myDFPlayer.EQ(DFPLAYER_EQ_BASS);

  
}

//.................................BOUCLE PRINCIPALE.........................................
void loop () {

  Serial.println("");
  Serial.println("Attente de détection");

  digitalWrite(LEDbleu, HIGH);
  digitalWrite(LEDverte, HIGH);
  digitalWrite(LEDrouge, HIGH);

  
  
  do {
    button = digitalRead(buttonPin); // ataché au detecteur PIR
     } while (button == 1);
     delay (1000);

  Serial.println("Détection activée");


  //myDFPlayer.play (5);  //Play haunted mp3
  myDFPlayer.next();  // lis le prochain morceau.


  static unsigned long start = millis();
  

  delay(100);
  do {
    sensorValue = analogRead(sensorPin);


    if (millis() - start >= 10000)
        break;

    Serial.print(sensorValue);
    Serial.print(" ");

    
    
            if (sensorValue >= 550) {

              digitalWrite(LEDrouge, LOW);
              digitalWrite(LEDbleu, LOW);
              digitalWrite(LEDverte, LOW);
              delay (50); 
            }
            
                    if (sensorValue <= 500) {
                
                      digitalWrite(LEDrouge, LOW);
                      digitalWrite(LEDbleu, HIGH);
                      digitalWrite(LEDverte, HIGH);
                    }



    
    busy = digitalRead(busyPin);


    Serial.print(millis());
    Serial.print(" ");

    Serial.print(start);
    Serial.print(" ");

    
    delay (1000);
    
  } while (busy == 0); // a zero quand le son est actif
}

//...................................... FIN DE LA BOUCLE ....................../code]

donc a priori tout ce passe bien pour la premiere boucle mais après le premier break
il ne rentre plus dans la boucle.

de se fais plus d'animation lumineuse  et plus de retour sur millis et Start

donc a priori tout ce passe bien pour la premiere boucle mais après le premier break
il ne rentre plus dans la boucle.

de se fais plus d'animation lumineuse et plus de retour sur millis et Start

Ce qui est normal puisque tu as déclaré ta variable start en static

static unsigned long start = millis();

De ce fait, la variable est mise à jour seulement au moment de sa création. Décompose ta ligne en deux.

  1. déclaration de ta variable en static (sans valeur)
  2. mise à jour de ta variable avec millis()

Ou enlève simplement le static car la variable ne doit pas être statique.

Ce qui est normal puisque tu as déclaré ta variable start en static

Oups ... désolé

:D. Pas grave hbachetti, c'est pas facile quand on a l'habitude de travailler avec plusieurs fonctions. On écrit du code sans forcément voir l'ensemble. Perso, je n'ai même pas pensé à supprimer le 'static' car pour moi je passe d'une fonction à l'autre dans la loop().

Même les plus grand Font des erreurs

Donc j'ai bien retiré static de la déclaration millis, et effectivement maintenant le temps est bien pris en compte a chaque boucle et me permet de sortir de la boucle après le temps déterminé.

mais un problème subsiste encore . quand en arrive a la fin du timer , la musique continue d'être jouer et c'est très bien, mais l'animation lumineuse s'arrête , je suppose que le break n'est pas a la bonne place.

ou la boucle d'échantillonnage lumineuse devrait pouvoir être indépendante de la détection et du timer et de se fait fonctionner des qu'il y a le moindre son?

Et c'est là le problème de ton architecture trop linéaire. Tu veux rendre tes fonctions indépendantes les une des autres mais tu les enfermes dans un scénario figé.
Tu dois donc créer des fonctions séparées les une des autres et les appeler dans la loop(). Chaque fonctions restent indépendantes des autres dans le temps mais elles peuvent interagissent entre elles grâce aux variables globales.

merci zlika

effectivement je vois bien que la majorité de mes programmes son complètement linéaire .

seulement voila j'apprend sur le tas , et je te le promet j'essai d'apprendre a complexifier mes prog

mais petit a petit en assimilant fonction après fonction et en bidouillant très souvent.

je pense que tu veux que je cree des fonction style

void animation lumineuse

void musique

etc

puis les appeler dans ma. void loop

Exactement.

La plupart du programme est déjà écrit. Il faut juste identifier et découper les fonctions.

  • détection PIR
  • gestion de l'animation des leds
  • gestion du timer (60 seconde)
  • gestion de la détection morceau MP3 terminé

Toutes ces fonctions sont dans la boucle car elles te retourneront des événements à travers des variables globales

La gestion du Player MP3 est juste une fonction que tu appelles pour lancer ou stopper une lecture dans les fonctions de la loop().

Tu peux éventuellement utiliser une variable avec enum pour renseigner tes fonctions de l'état actuel. Sa valeur déterminera les actions à effectuer et en la modifiant, tu passes à l'étape suivante.