Comment passer d'une fonction bloquante a une fonction non bloquante

Bonjour les genius! :slight_smile:

Sa fait quelques jours que je bloque sur mon projet a cause du fait que la fonction de mon programme est bloquante , j'ai beau chercher comment modifier le code pour que la fonction soit non bloquante mais sans réponse.:confused:

Projet : Création d'un programme qui calculera la distance entre le sonar (HC SR04) et l'obstacle puis qui émettra des beep (Buzzer Actif) en fonction des différents intervalles de distance.

PS:Je débute depuis quelque semaine en programmation sur Arduino , donc je tient a m’excuser d'avance pour l'illisibilité de mon code.

#define VITESSE 340

const int USTrig = 8;
const int USEcho = 9;
const int buzzer = 2;

float distance = 0.0;

void setup() {
pinMode(buzzer,OUTPUT);
pinMode(USEcho, INPUT); 
pinMode(USTrig, OUTPUT);


digitalWrite(USTrig,LOW);

Serial.begin(9600);
}

void loop() {
  
  int i;
  digitalWrite(USTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(USTrig, LOW);

  unsigned long duree = pulseIn(USEcho, HIGH);

  if(duree > 30000)
  {
    Serial.println("Onde perdue, mesure echouer !");
   
    }

    else 
    {
   
  duree = duree/2;

  float temps =  duree/1000000.0;
  distance = temps*VITESSE;
  distance = distance*100;

  Serial.print("Distance = ");
  Serial.println(distance); //affiche la distance mesurée (en cm)
    }
    
  if (distance > 150.0 && distance < 200.0)
  {
    for(i=0; i<80; i++)
    {
      digitalWrite(buzzer, HIGH);
      delay(1000);
      digitalWrite(buzzer, LOW);
      delay(1000);
    }
    
  }

 else if(distance > 100.0 && distance < 150.0)
 {
  for(i=0 ; i<80; i++)
 {
  digitalWrite(buzzer, HIGH);
  delay(500);
  digitalWrite(buzzer, LOW);
  delay(500);
 }
 }
 else if(distance > 50.0 && distance < 100.0)
 {
  for(i=0 ; i<80; i++)
  {
    digitalWrite(buzzer, HIGH);
    delay(250);
    digitalWrite(buzzer, LOW);
    delay(250);
  }
 }
  else if(distance < 50.0)
  {
    for(i=0 ; i<80; i++)
    {
      digitalWrite(buzzer, HIGH);
      delay(50);
      digitalWrite(buzzer,LOW);
      delay(50);
    }
  }
    else 
    {
      digitalWrite(buzzer,LOW);
    }
    
  }

lisez ces exemples

introduire-le-temps
Several Things at a Time

C'est normal que vous soyez bloqué. Vous lancez des séquences d'une cinquantaine de secondes pour exciter votre buzzer. Donc la prochaine analyse aura lieu quand la boucle qui excite le buzzer sera terminée.

Pour y pallier, il y a deux solutions:

  • soit utiliser les interruptions ; placer la détection à l'intérieur de celle-ci (en prenant garde qu'il n'y ait pas de conflit de timer)
  • soit utiliser un séquenceur.; créer autant d'objets "séquenceur" qu'il y a de cas ; la détection étant un cas, les différents modes d'excitation représentants chacun un autre cas.

Un intervenant a fait une bibliothèque simple de séquencement, mais je ne l'ai pas retrouvée. A mon sens, il devrait se signaler.

Mais attention, si pendant une séquence d'excitation donnée, la distance mesurée change, vous aller basculer de séquence : à gérer.

Cordialement.

Pierre

Le programme blinkWithoutDelay qui fait parti des programmes chargés avec l'environnement Arduino est un exemple de ce que l'on peut faire pour se passer de delay() pour faire des temporisations.
Cela impose aussi une adaptation du programme car il faut alors tourner dans loop en permanence et n'exécuter certaines fonctions (mesure de la distance, allumage/extinction d'un buzzer ou d'une LED) qu'à des moments précis

Tu peux aussi voir là:[Lib] SoftTimer - Une lib pour faciliter les taches périodique ou liées au temps - Réalisations et Projets Finis - Arduino Forum

Bonjour,

Il faut que tu utilises la fonction millis(). Tu calcules la durée du bip en fonction de la distance et tu inverses la sortie du buzzer à chaque durée.
Ce qui donne par exemple:

#define VITESSE 340

const int USTrig = 8;
const int USEcho = 9;
const int buzzer = 2;

float distance = 0.0;

void setup() {
  pinMode(buzzer, OUTPUT);
  pinMode(USEcho, INPUT);
  pinMode(USTrig, OUTPUT);

  digitalWrite(USTrig, LOW);

  Serial.begin(9600);
}

void loop() {
  static unsigned long lastInversionTime=0; // millis de la dernière inversion du buzzer
  unsigned long tempoBip;         // durée du bip
  
  int i;
  digitalWrite(USTrig, HIGH);
  delayMicroseconds(10);
  digitalWrite(USTrig, LOW);
  
  unsigned long duree = pulseIn(USEcho, HIGH);

  if (duree > 30000)
  {
    tempoBip=0;
    Serial.println("Onde perdue, mesure echouer !");
  }
  else
  {
    duree = duree / 2;

    float temps =  duree / 1000000.0;
    distance = temps * VITESSE;
    distance = distance * 100;

    Serial.print("Distance = ");
    Serial.println(distance); //affiche la distance mesurée (en cm)

    if (distance>200.0)
      tempoBip=0;
    else if (distance>150.0)
      tempoBip=1000;
    else if (distance>100.0)
      tempoBip=500;
    else if (distance>50.0)
      tempoBip=250;
    else
      tempoBip=50;  
  }

  if (tempoBip==0)
  {
      digitalWrite(buzzer, LOW);    // trop loin -> arrête le buzzer
  }
  else
  {
    if (millis()-lastInversionTime>=tempoBip)
    {
      digitalWrite(buzzer,!digitalRead(buzzer));   // inverse le buzzer
      lastInversionTime=millis();
    }
  }
}

Rebonjour :slight_smile: !

Merci pour vos réponses, sa m'aide énormément ! Je prendrais le temps de bien lire les exemples et je vous tiendrais au courant de la suite de mon projet.

Cordialement Amenosos.

fdufnews:
Le programme blinkWithoutDelay qui fait parti des programmes chargés avec l'environnement Arduino est un exemple de ce que l'on peut faire pour se passer de delay() pour faire des temporisations.
Cela impose aussi une adaptation du programme car il faut alors tourner dans loop en permanence et n'exécuter certaines fonctions (mesure de la distance, allumage/extinction d'un buzzer ou d'une LED) qu'à des moments précis

+1, BlinkWithoutDelay est le premier truc à étudier, ça a été le déclencheur pour moi