Lidar & Boucle for - Sortir sous changement de conditions

Bonjour,
dans le cadre de la création d'un maquette pédagogique j'utilise un Lidar TF-Mini S dont j'exploite la mesure pour activer des LEDs associées à des sens et leurs portées :

  • de 10cm > active la sortie X / entre 10 et 30 > sortie Y etc...
    Sur un intervalle de distance donné(else if (distance > Vue && distance < LL) j'utilise une boucle for pour faire un chenillard sur 8 led via un 74HC595.

Sur les autres intervalles mes sorties fonctionnent relativement bien entre elles,
selon la mesure de distance.
Mais, à l'instant où je remplie la condition pour rentrer dans les boucles for (voir sous tache "void Activation_LigneLat()" )qui réalisent mon chenillard ... la mesure se fige (je le vois en activant le moniteur série) et je dois attendre la fin d'exécution de la boucle for (ça dure environ 10 sec).
10 secondes pendant lesquelles j'aurais beau reculer/avancer la cible il faudra attendre la fin pour que des nouvelles mesures soient générées pas le Lidar.

La question (enfin) : comment pourrais-je forcer une sortie de ce chenillard relativement simultanément après la perte de la condition qui a activé son déclenchement ?
Je joins le code plus bas.
PI : J'ai essayé d'ajouter un test de dans la condition de maintien des boucles for, ça ne marche pas voire ça bloque tout....

MERCI BEAUCOUP pour votre temps.

BONUS : et preneur de vos tips pour éviter les allumages parasites des sorties d'un 74HC595 , j'ai ouvert tous les forums, je n'ai pas trouvé la solution adaptée (du moins qui fonctionne pour moi ie resistance avant le GND sur borne OE etc...

#include <SoftwareSerial.h>
#include "TFMini.h"
TFMini tfmini;

//===================================================================
//=================SECTIONS DECLARATION DE VARIABLES=================

//ENTREES ARDUINO & AFFECTATION DES PINS
SoftwareSerial SerialTFMini(10, 11);
int I_BPStart = 2;
int I_PosPot_Detect = 23;
int I_PosPot_Expo = 22;
int I_PosPot_Ouie = 26;
int I_PosPot_Odorat = 28;
int I_PosPot_LL = 30;
int I_PosPot_Vue = 34;
int I_PosPot_Lorenz = 32;
int I_PosPot_Gout = 36;


//SORTIES ARDUINO & AFFECTATION DES PINS
int O_InitOK = 25; //Allumage LED confirmation bonne alimentation.
int O_Ready = 27; //Allumage LED confirmation reception BP Start.
int O_Ouie = 31;
int O_Odorat = 33;
int O_Vue = 35;
int O_Lorenzini = 37;
int O_Gout = 39;
int Verrou_74HC = 6; // (12) ST_CP [RCK] on 74HC595
int Horl_74HC = 5; // (11) SH_CP [SCK] on 74HC595
int Data_74HC = 4; // (14) DS [S1] on 74HC595


//DECLARATION VARIABLES INTERNES & AFFECTATION DE VALEURS
int Ouie = 500; //On indique la distance en dessous de laquelle nous souhaitons voir la led s'allumer
int Odorat = 300;
int LL = 100;
int Vue = 50;
int Lorenzini = 30;
int Gout = 10;
int Tare = 5;
int DelaiSens = 300;
int Delai_MExpo = 500;
int DelaiInit = 100;
byte leds_74HC = 0;

//========================================================
//=================SECTION INITIALISATION=================
void setup() // Initialisation des Variables & Fonctions du PROG.
{
  Serial.begin(115200);       //Initialisation du port serie avec Baud Rate de connexion
  while (!Serial);            // Attente de réponse du terminal série
  Serial.println ("Initializing...");
  SerialTFMini.begin(TFMINI_BAUDRATE);    //Initialisation du baud rate software
  tfmini.begin(&SerialTFMini);            //Initialisation du Capteur TFMini-S
  //réglages des types d'entrées.
  pinMode(I_BPStart, INPUT_PULLUP);
  pinMode(I_PosPot_Detect, INPUT_PULLUP);
  pinMode(I_PosPot_Expo, INPUT_PULLUP);
  pinMode(I_PosPot_Ouie, INPUT_PULLUP);
  pinMode(I_PosPot_Odorat, INPUT_PULLUP);
  pinMode(I_PosPot_LL, INPUT_PULLUP);
  pinMode(I_PosPot_Vue, INPUT_PULLUP);
  pinMode(I_PosPot_Lorenz, INPUT_PULLUP);
  pinMode(I_PosPot_Gout, INPUT_PULLUP);
  //réglages des types de sorties et mise à zéro.
  digitalWrite(O_InitOK, LOW);
  pinMode(O_InitOK, OUTPUT);
  digitalWrite(O_Ready, LOW);
  pinMode(O_Ready, OUTPUT);
  digitalWrite(O_Gout, HIGH);
  pinMode(O_Gout, OUTPUT);
  digitalWrite(O_Lorenzini, HIGH);
  pinMode(O_Lorenzini, OUTPUT);
  digitalWrite(O_Vue, HIGH);
  pinMode(O_Vue, OUTPUT);
  digitalWrite(O_Odorat, HIGH);
  pinMode(O_Odorat, OUTPUT);
  digitalWrite(O_Ouie, HIGH);
  pinMode(O_Ouie, OUTPUT);
  pinMode(Verrou_74HC, OUTPUT);
  pinMode(Horl_74HC, OUTPUT);
  pinMode (Data_74HC, OUTPUT);
}

//=======================================================================================================
//=============== SECTIONS DES SOUS-FONCTIONS APPELEES DANS LA BOUCLE PRINCIPALE "LOOP"==================

//------Fonction de récupération des valeurs du capteur TFMini-S-------//
void getTFminiData(int* distance, int* strength)
{
  static char i = 0;
  char j = 0;
  int checksum = 0;
  static int rx[9];
  if (SerialTFMini.available())
  {
    rx[i] = SerialTFMini.read();
    if (rx[0] != 0x59)
    {
      i = 0;
    }
    else if (i == 1 && rx[1] != 0x59)
    {
      i = 0;
    }
    else if (i == 8)
    {
      for (j = 0; j < 8; j++)
      {
        checksum += rx[j];
      }
      if (rx[8] == (checksum % 256))
      {
        *distance = rx[2] + rx[3] * 256;
        *strength = rx[4] + rx[5] * 256;
      }
      i = 0;
    }
    else
    {
      i++;
    }
  }
}

//------Fonction Mise à jour 74HC595-------//
void Maj_Registre_Decal()
{
  digitalWrite(Verrou_74HC, LOW);
  shiftOut(Data_74HC, Horl_74HC, LSBFIRST, leds_74HC);
  digitalWrite(Verrou_74HC, HIGH);
}


//------Fonction d'activation Sens Ligne Latérale-------//
void Activation_LigneLat()
{
  leds_74HC = 0;
  Maj_Registre_Decal();

  for (int i = 0; i < 8; i++)
  {
    bitSet(leds_74HC, i);
    Maj_Registre_Decal();
    delay(200);
  }
  leds_74HC = 0;
  Maj_Registre_Decal();
  for (int i = 7; i >= 0; i--)
  {
    bitSet(leds_74HC, i);
    Maj_Registre_Decal();
    delay(200);
  }
  leds_74HC = 0;
  Maj_Registre_Decal();
  delay(200);
}


//------Fonction d'activation du Mode de Pilotage via Detecteur de Distance (TFMini-S)-------//
void Mode_Auto()
{
  delay(DelaiInit);
  int distance = 0;
  int strength = 0;

  getTFminiData(&distance, &strength);
  while (!distance)
  {

    getTFminiData(&distance, &strength);
    if (distance)
    {
      Serial.print(distance);
      Serial.print("cm\t");
      Serial.print("strength: ");
      Serial.println(strength);

      if (distance < Gout)
      {
        LL_Activ = false;
        digitalWrite(O_Ouie, HIGH);
        digitalWrite(O_Odorat, HIGH);
        digitalWrite(O_Vue, HIGH);
        digitalWrite(O_Lorenzini, HIGH);
        digitalWrite(O_Gout, LOW);
      }
      else if  (distance > Gout  & distance < Lorenzini)
      {
        LL_Activ = false;
        digitalWrite(O_Ouie, HIGH);
        digitalWrite(O_Odorat, HIGH);
        digitalWrite(O_Vue, HIGH);
        digitalWrite(O_Lorenzini, LOW);
        digitalWrite(O_Gout, HIGH);
      }
      else if  (distance > Lorenzini && distance < Vue)
      {
        LL_Activ = false;
        digitalWrite(O_Ouie, HIGH);
        digitalWrite(O_Odorat, HIGH);
        digitalWrite(O_Vue, LOW);
        digitalWrite(O_Lorenzini, HIGH);
        digitalWrite(O_Gout, HIGH);
      }
      else if  (distance > Vue && distance < LL) //<<<<<<<<<<< c'est ici que ça chi... que ça devient complexe.
      {
        digitalWrite(O_Ouie, HIGH);
        digitalWrite(O_Odorat, HIGH);
        digitalWrite(O_Vue, HIGH);
        digitalWrite(O_Lorenzini, HIGH);
        digitalWrite(O_Gout, HIGH);
        Activation_LigneLat();
      }
      else if  (distance > LL && distance < Odorat)
      {
        LL_Activ = false;       
        digitalWrite(O_Ouie, HIGH);
        digitalWrite(O_Odorat, LOW);
        digitalWrite(O_Vue, HIGH);
        digitalWrite(O_Lorenzini, HIGH);
        digitalWrite(O_Gout, HIGH);
      }
      else if  (distance > Odorat )//&& distance < Ouie)
      {
        LL_Activ = false; 
        digitalWrite(O_Ouie, LOW);
        digitalWrite(O_Odorat, HIGH);
        digitalWrite(O_Vue, HIGH);
        digitalWrite(O_Lorenzini, HIGH);
        digitalWrite(O_Gout, HIGH);
      }

      //Pour le moniteur série
      if ( distance <= 0) {
        Serial.println("Hors de portee");

      }
    }
  }
}

  //===================================================================================
  //=============== SECTION DE LA BOUCLE PRINCIPALE DE TRAVAIL "LOOP"==================

  void loop()
{
  delay(DelaiInit);
  leds_74HC = 0;
  Maj_Registre_Decal();
  digitalWrite(O_InitOK, HIGH);

  Mode_Auto();
}

Oui, bien sûr puisque la boucle for est bloquante.
2 possibilités :

  • interrompre la boucle for en introduisant une condition de sortie supplémentaire dans le 2nd argument du for. Mais cela impose de faire des mesures dans la boucle en question et c'est un peu moche comme manière de faire.
  • en fait, ton application se prête bien à l'utilisation d'une machine à état. Voir le tuto ci-dessous
    Programmation Automate fini / Machine à état - #78 by J-M-L

Dans quelles conditions?

  • il y a un Output Enable qui désactive toutes les sorties
  • il y a RCLK qui transfère le contenu du registre à décalage dans le registre de sortie lorsqu'on a fini le chargement.

Bonjour @fdufnews !

tout d'abord merci pour votre temps et votre réactivité !
J'ai bien regardé le tuto PDF il est super cool mais je n'ai pas l'impression qu'il puisse m'aider dans le sens où dans le fond j'arrive à faire varier mes états selon la distance et les actions quo en découlent. Je recherche par contre à gagner en réactivité dans la réponse à variation de conditions. et ceux pour une boucle for.

merci !

Bonjour,

Je pense comprendre qu’en fait j’utilise trop de fonction bloquante.
J’ai l’impression que l’utilisation millis() peut m’aider.
Dans les exemples d’utilisation comme blink without delay, on traite du temps. Mais peut-on s’en servir pour traiter des actions liés à l’état d’un capteur ? Du moins intellectuellement je n’arrive pas à le re-transposer.

Dsl si je ne suis pas clair

C'est pour ça que je te proposais d'utiliser une machine à état.
Le passage d'un état au suivant peut être conditionné par un changement d'état sur un IO aussi bien que sur l'écoulement d'une temporisation (en utilisant millis()), ou le positionnement d'une variable dans une autre partie du code.
Les actions déclenchées par un état ne sont pas bloquantes et retournent le plus rapidement possible dans l'automate ce qui assure la réactivité de l'ensemble.

On peut très bien avoir plusieurs machines à états qui tournent en parallèle.
Exemple une machine séquence la succession des acquisitions et leurs traitements alors qu'une seconde s'occupe de l'affichage.
On voit que si on veut que l'affichage soit fluide il faut que les acquisitions et les traitement ne soient pas bloquants et réciproquement pour que les acquisitions et le traitement se déroulent au bon rythme il faut que l'affichage ne soit pas bloquant non plus.

Il faut voir cela dans son ensemble on ne peut pas ajouter à posteriori un morceau d'automate au milieu d'un bloc de code qui monopolise tout le temps CPU.

Bonjour @fdufnews !
Dsl je n’avais pas vu votre message merci pour la piste je vais creuser !

Et c’est problème réglé sur le 74h595 :ok_hand:t2: ! Merci pour votre temps !

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