Buzzer et millis

Bonjour

Dans le cadre d'un cours je dois utiliser un buzzer qui fait un son pendant 1s toute les 3s mais j'ai des difficultés

void beeper();
void setup() {
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
beeper();
}
void beeper()
{
  unsigned long attente =millis();
  
  if(millis()-attente >= 3000){
    tone(5,100,10);
    Serial.print(attente);
  
  }
  
}

je dois aussi afficher le signal du temps ce que je pense savoir faire mais ils me demandent aussi d'afficher le signal envoyé au buzzer que je ne comprend pas vraiment.

Afficher le signal envoyé au buzzer

On ne peut pas envoyer les 1 et les 0, je suppose qu'il faut écrire "Buzzer en marche" au moment ou il commence à sonner et "Buzzer arrété" quand il a fini. (C'est pratique si le prof est mal entendant :grin: ).

  • tu ne gères que la mise en marche du buzzer, tu ne gères pas son extinction
  • à chaque fois que tu rentres dans la fonction beeper(), tu effaces et relis ton "top départ" (variable attente, mal nommée d'ailleurs)
  • tu lis l'heure
  • immédiatement tu testes si 3 sec. ont passé, le test dit donc faux,
  • tu sors de la fonction
  • tu sorts de loop(), puis tu y revient immédiatement
    Ca ne marche pas car tu réinitilalises sans arrêt ton "point de départ"

Il faut que tu gères un état, c-à-d une variable qui se souvient si

  • tu es en attente de 3 s (et ça sonne quand les 3 s sont passées) c'est l'etat SILENCE
  • tu es en attente de 1 s (et ça s'arrête de sonner au bout) c'est l'état SONNERIE

Ton prog doit tester l'état courant pour savoir ce qu'il doit faire, et tenir à jour cette variable état quand tu passes d'un état à l'autre.

Remarque: pour un prog aussi simple, pas besoin d'utiliser millis(), des appels à, delay() suffisent.

biggil:

  • tu ne gères que la mise en marche du buzzer, tu ne gères pas son extinction
  • à chaque fois que tu rentres dans la fonction beeper(), tu effaces et relis ton "top départ" (variable attente, mal nommée d'ailleurs)
  • tu lis l'heure
  • immédiatement tu testes si 3 sec. ont passé, le test dit donc faux,
  • tu sors de la fonction
  • tu sorts de loop(), puis tu y revient immédiatement
    Ca ne marche pas car tu réinitilalises sans arrêt ton "point de départ"

Il faut que tu gères un état, c-à-d une variable qui se souvient si

  • tu es en attente de 3 s (et ça sonne quand les 3 s sont passées) c'est l'etat SILENCE
  • tu es en attente de 1 s (et ça s'arrête de sonner au bout) c'est l'état SONNERIE

Ton prog doit tester l'état courant pour savoir ce qu'il doit faire, et tenir à jour cette variable état quand tu passes d'un état à l'autre.

Remarque: pour un prog aussi simple, pas besoin d'utiliser millis(), des appels à, delay() suffisent.

Ok, merci pour l'aide je vais essayer de refaire ça ( et pour la fonction millis c'est une contrainte je suis obligé de l'utiliser)
aussi , comment faire un état pour un buzzer ? pour une led je vois on fait simplement un if si la led est allumé et un autre si elle est éteinte mais comme pour le buzzer on passe par tone je vois pas comment faire.

Ok , du coup j'ai utilisé des booléen pour faire les états et j'ai fait ça , en le mettant du coup dans mon loop.

 unsigned long maintenant =millis();
unsigned long dernier=0;
bool buzzer=false; 

  if((buzzer==true)&&(maintenant-dernier>=1000))
  {
   buzzer=false;
   dernier=maintenant;
   noTone(12);
  
  }

  if((buzzer==false)&&(maintenant-dernier>=3000))
  {
   buzzer=true;
   dernier=maintenant;
  tone(12,100);
  }

  
}

J'ai pas pu encore testé parce que je n'ai pas mon matériel sur moi mais pensez vous que c'est bien ?

noepham:
Ok , du coup j'ai utilisé des booléen pour faire les états et j'ai fait ça , en le mettant du coup dans mon loop.

 unsigned long maintenant =millis();

unsigned long dernier=0;
bool buzzer=false;

if((buzzer==true)&&(maintenant-dernier>=1000))
 {
  buzzer=false;
  dernier=maintenant;
  noTone(12);
 
 }

if((buzzer==false)&&(maintenant-dernier>=3000))
 {
  buzzer=true;
  dernier=maintenant;
 tone(12,100);
 }

}



J'ai pas pu encore testé parce que je n'ai pas mon matériel sur moi mais pensez vous que c'est bien ?

J'ai pu testé et selon quel if je met en premier soit il fait aucun bruit soit il ne s'arrête pas. Je ne comprend pas vraiment pourquoi

hello
tu utilises la variable "maintenant" mais il faut la tenir à jour
le mieux est d'utiliser la fonction millis() en direct
de plus, tu te faciliterai la vie en utilisant "Serial.print"
lance ce code et ouvre ton moniteur à 1000000 bauds

const byte buzzer  = 12;
const byte NOTE = 100;
unsigned long dernier=0;
bool buz=false;
void setup()
{
  Serial.begin(1000000);
  pinMode(buzzer,OUTPUT);digitalWrite(buzzer,LOW);
  Serial.println("pret ");
  }
void loop()
{
  if((buz)&&((millis()-dernier)>=1000))
  {
   Serial.print("pour 3 secondes ");Serial.print('\t');
   buz=false;Serial.print("Buzer = false ");Serial.print('\t');
   dernier=millis();Serial.println("Buzer = notone ");
   noTone(buzzer);
  }
  if((!buz)&&((millis()-dernier)>=3000))
  {
   Serial.print("pour 1 seconde ");Serial.print('\t');Serial.print('\t');
   buz=true;Serial.print("Buzer = true ");Serial.print('\t');
   dernier=millis();Serial.println("Buzer = tone ");
  tone(buzzer,NOTE);
  }
}

dfgh:
hello
tu utilises la variable "maintenant" mais il faut la tenir à jour
le mieux est d'utiliser la fonction millis() en direct
de plus, tu te faciliterai la vie en utilisant "Serial.print"
lance ce code et ouvre ton moniteur à 1000000 bauds

const byte buzzer  = 12;

const byte NOTE = 100;
unsigned long dernier=0;
bool buz=false;
void setup()
{
 Serial.begin(1000000);
 pinMode(buzzer,OUTPUT);digitalWrite(buzzer,LOW);
 Serial.println("pret ");
 }
void loop()
{
 if((buz)&&((millis()-dernier)>=1000))
 {
  Serial.print("pour 3 secondes ");Serial.print('\t');
  buz=false;Serial.print("Buzer = false ");Serial.print('\t');
  dernier=millis();Serial.println("Buzer = notone ");
  noTone(buzzer);
 }
 if((!buz)&&((millis()-dernier)>=3000))
 {
  Serial.print("pour 1 seconde ");Serial.print('\t');Serial.print('\t');
  buz=true;Serial.print("Buzer = true ");Serial.print('\t');
  dernier=millis();Serial.println("Buzer = tone ");
 tone(buzzer,NOTE);
 }
}

Merci beaucoup pour l'aide! Par contre je sais pas si c'est mon buzzer ou le code qui fait ça mais après les une seconde de bruit du buzzer , il ne devrait plus avoir de son mais il y a quand même une sorte de bruit de fond , c'est pas très grave mais c'est juste pour savoir si c'est normal ou pas

je dois utiliser un buzzer qui fait un son pendant 1s toute les 3s

Il semble que l’usage de millis() n’est pas imposé ni les affichages. pas besoin de faire de l’over-engineering: comme tone() prend aussi une durée et travaille en asynchrone on peut faire

 const byte pinBuzzer  = 12;
void setup() {
  pinMode(pinBuzzer, OUTPUT); // LOW par defaut
}

void loop() {
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s’arrête tout seul
  delay(3000); // on attend 3 secondes avant de recommencer
}

hello JML

en #3 notre ami dit que milli() lui est imposé

autrement, oui ta solution est bien vue :slight_smile:

Ah damned :wink:

 const byte pinBuzzer  = 12;
void setup() {
  pinMode(pinBuzzer, OUTPUT); // LOW par defaut
  millis(); // répond à la demande d’utiliser millis()
}

void loop() {
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
  delay(3000); // on attend 3 secondes avant de recommencer
}

Ou un peu moins foutage de gueule (mais le prof ne va pas aimer)

 const byte pinBuzzer  = 12;
void setup() {
  pinMode(pinBuzzer, OUTPUT); // LOW par defaut
}

void loop() {
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
  unsigned long t0 = millis();
  while (millis()-t0 <=3000); // on attend 3 secondes avant de recommencer
}

Bon je sors....

PS: c’est typiquement une définition de programme qui se prête bien à la programmation par machine à états (cf mon tuto éventuellement)

J-M-L:
Ah damned :wink:

 const byte pinBuzzer  = 12;

void setup() {
  pinMode(pinBuzzer, OUTPUT); // LOW par defaut
  millis(); // répond à la demande d’utiliser millis()
}

void loop() {
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
  delay(3000); // on attend 3 secondes avant de recommencer
}




Ou un peu moins foutage de gueule (mais le prof ne va pas aimer)


const byte pinBuzzer  = 12;
void setup() {
  pinMode(pinBuzzer, OUTPUT); // LOW par defaut
}

void loop() {
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
  unsigned long t0 = millis();
  while (millis()-t0 <=3000); // on attend 3 secondes avant de recommencer
}




Bon je sors....


PS: c’est typiquement une définition de programme qui se prête bien à la programmation par machine à états ([cf mon tuto éventuellement](http://forum.arduino.cc/index.php?topic=470879.0))

Encore merci pour l'aide ! J'ai une autre question , je dois aussi avoir un écran qui affiche une valeur quand un capteur est actionné mais affiche l'heure quand il ne l'est pas , pour seulement afficher les valeurs je voyais faire quelque chose comme ça

oled.writeFillRect(0,50,128,16,BLACK);
oled.setCursor(0,50);
oled.print(BPM);
oled.print(" BPM");
oled.display();
x++;
}
Mais du coup je dois faire deux états différents comme les précédents code pour avoir l'heure ? et juste comment avoir l'heure tout court ?

le système à modéliser: un buzzer + un afficheur + un capteur

  • Le buzzer sonne 1s toutes les 3 secondes. il est donc indépendant du capteur, il faut juste relancer un son d'une seconde toutes les 3 secondes

  • l'écran dépend du temps qui passe (pour afficher "l'heure") et du capteur

on a donc deux machines à états (deux systèmes), on peut appliquer l'approche du tuto:

const byte pinBuzzer = 12;
unsigned long tempsBuzzer;

enum : byte {AFFICHE_HEURE, AFFICHE_VALEUR} etatEcran = AFFICHE_HEURE;
unsigned long tempsAfficheur;
const byte pinCapteur = 2; // avec pullup -> LOW veut dire activé

void gererBuzzer()
{
  if (millis() - tempsBuzzer >= 3000) {
    tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
    tempsBuzzer = millis();
  }
}

void afficheHeure(bool forcerAffichage = false)
{
  if (forcerAffichage || (millis() - tempsAfficheur >= 1000)) {
    // plus d'une seconde a passé
    Serial.print(F("Temps: "));
    Serial.println(millis() / 1000); // on affiche des secondes qui défilent
    tempsAfficheur = millis();
  }
}

void afficheValeur(bool forcerAffichage = false)
{
  if (forcerAffichage || (millis() - tempsAfficheur >= 1000)) {
    // plus d'une seconde a passé
    Serial.print(F("Valeur: "));
    Serial.println(random(0, 100)); // on affiche une valeur aléatoire
    tempsAfficheur = millis();
  }
}

void gererEcran()
{
  switch (etatEcran) {
    case AFFICHE_HEURE:
      // on affichait l'heure. on teste si le capteur est actionné
      if (digitalRead(pinCapteur) == LOW) { // si oui on bascule sur l'affichage de valeur
        afficheValeur(true); // true -> on force l'affichage immédiat
        etatEcran = AFFICHE_VALEUR;
        delay(15); // anti-rebond du pauvre
      } else {
        afficheHeure(); // on laisse l'affichage se faire toutes les secondes, on ne force pas le raffraichissment
      }
      break;
    case AFFICHE_VALEUR:
      // on affichait l'heure. on teste si le capteur est relâché
      if (digitalRead(pinCapteur) == HIGH) { // si oui on rebascule sur l'heure
        afficheHeure(true); // true -> on force l'affichage immédiat
        etatEcran = AFFICHE_HEURE;
        delay(15); // anti-rebond du pauvre
      } else {
        afficheValeur();  // on laisse l'affichage se faire toutes les secondes, on ne force pas le raffraichissment
      }
      break;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(pinBuzzer, OUTPUT);
  pinMode(pinCapteur, INPUT_PULLUP);
  tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
}

void loop() {
  gererBuzzer();
  gererEcran();
}

J-M-L:
le système à modéliser: un buzzer + un afficheur + un capteur

  • Le buzzer sonne 1s toutes les 3 secondes. il est donc indépendant du capteur, il faut juste relancer un son d'une seconde toutes les 3 secondes

  • l'écran dépend du temps qui passe (pour afficher "l'heure") et du capteur

on a donc deux machines à états (deux systèmes), on peut appliquer l'approche du tuto:

const byte pinBuzzer = 12;

unsigned long tempsBuzzer;

enum : byte {AFFICHE_HEURE, AFFICHE_VALEUR} etatEcran = AFFICHE_HEURE;
unsigned long tempsAfficheur;
const byte pinCapteur = 2; // avec pullup -> LOW veut dire activé

void gererBuzzer()
{
 if (millis() - tempsBuzzer >= 3000) {
   tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
   tempsBuzzer = millis();
 }
}

void afficheHeure(bool forcerAffichage = false)
{
 if (forcerAffichage || (millis() - tempsAfficheur >= 1000)) {
   // plus d'une seconde a passé
   Serial.print(F("Temps: "));
   Serial.println(millis() / 1000); // on affiche des secondes qui défilent
   tempsAfficheur = millis();
 }
}

void afficheValeur(bool forcerAffichage = false)
{
 if (forcerAffichage || (millis() - tempsAfficheur >= 1000)) {
   // plus d'une seconde a passé
   Serial.print(F("Valeur: "));
   Serial.println(random(0, 100)); // on affiche une valeur aléatoire
   tempsAfficheur = millis();
 }
}

void gererEcran()
{
 switch (etatEcran) {
   case AFFICHE_HEURE:
     // on affichait l'heure. on teste si le capteur est actionné
     if (digitalRead(pinCapteur) == LOW) { // si oui on bascule sur l'affichage de valeur
       afficheValeur(true); // true -> on force l'affichage immédiat
       etatEcran = AFFICHE_VALEUR;
       delay(15); // anti-rebond du pauvre
     } else {
       afficheHeure(); // on laisse l'affichage se faire toutes les secondes, on ne force pas le raffraichissment
     }
     break;
   case AFFICHE_VALEUR:
     // on affichait l'heure. on teste si le capteur est relâché
     if (digitalRead(pinCapteur) == HIGH) { // si oui on rebascule sur l'heure
       afficheHeure(true); // true -> on force l'affichage immédiat
       etatEcran = AFFICHE_HEURE;
       delay(15); // anti-rebond du pauvre
     } else {
       afficheValeur();  // on laisse l'affichage se faire toutes les secondes, on ne force pas le raffraichissment
     }
     break;
 }
}

void setup() {
 Serial.begin(115200);
 pinMode(pinBuzzer, OUTPUT);
 pinMode(pinCapteur, INPUT_PULLUP);
 tone(pinBuzzer, 100, 1000); // buzz à 100Hz pendant une seconde et s'arrête tout seul
}

void loop() {
 gererBuzzer();
 gererEcran();
}

Et si par exemple on devait changer la valeur du temp du graphique que renvoie la led avec un potentiomètre , on ferait

valeur=analogread(pinpotentiomètre);
percent=map(sensorvalue,0,1023,0,100);

et après ?

Je vous laisse étudier le code et le tuto

Quand vous l’aurez compris la réponse sera évidente

:slight_smile:

void afficheValeur(bool forcerAffichage = false)
{if (forcerAffichage || (millis() - tempsAfficheur >= 1000)) {
// plus d'une seconde a passé
valeur=analogread(pinpotentiomètre);[color=#222222][/color]
percent=map(valeur,0,1023,0,100);
 int graph=analogRead(0);
  oled.setTextColor(WHITE);
  int y=60-(value/16);
  oled.writeLine(lastx,lasty,x,y,WHITE);
  lasty=y;
  lastx=x;
tempsAfficheur = millis();
if(percent>90)
{
y=y+30;
x=x+30;
}
if(percent<90)
{
y=y-30;
x=x-30;
}[color=#222222][/color]
}

Honnêtement je vois pas quoi faire de plus , je dois changer la valeur du x ou du y si je bouge le potentiomètre ?

mettre votre code dans la fonction afficheValeur() est une bonne idée.

cependant:

  • le code contient du marquage de couleur.... incompilable
  • il n'est pas indenté... bref illisible
  • il utilise des tonnes de variables (valeur, percent, graph, x, y, lastx, lasty) dont on ne sait d'où ils viennent.
  • x et y sont recalculés après l'affichage, y est une variable locale donc sera perdue après sortie de la fonction
  • graph n'est même pas utilisé et est une variable locale donc sera perdue après sortie de la fonction

bref, il y a un peu de boulot.

-> faites le nettoyage et Postez un code complet qui compile.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.