Led escalier avec sens de déplacement

Bonjour à tous,

Je suis en train de réaliser un projet d'allumage de leds dans mes escaliers avec un sens d'allumage (bas vers haut ou haut vers bas) et qui permet également de compter le nombre de personnes qui se trouve dans l'escalier (pour le pas éteindre si une personne serai encore présente)

ca fonctionne... sauf que :slight_smile: ... si l'on reste devant le capteur immobile le compteur de personne augmente (J'ai des animaux et difficile de leur expliquer de ne pas faire ça :D)

Voici le code si quelqu'un à une solution ou remarque ou encore simplification, cela m'arrangerai.
ps: je n'ai pas mis toute la partie d'allumage de la led.

#include "Adafruit_VL53L0X.h"

// address we will assign for all 4 sensor
#define LOX1_ADDRESS 0x30
#define LOX2_ADDRESS 0x31
#define LOX3_ADDRESS 0x32
#define LOX4_ADDRESS 0x33
int sensor1,sensor2, sensor3,sensor4;

// set the pins to shutdown for all 4 sensors
#define SHT_LOX1 6
#define SHT_LOX2 7
#define SHT_LOX3 8
#define SHT_LOX4 9

// objects for the vl53l0x
Adafruit_VL53L0X lox1 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox2 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox3 = Adafruit_VL53L0X();
Adafruit_VL53L0X lox4 = Adafruit_VL53L0X();

// this holds the measurement
VL53L0X_RangingMeasurementData_t measure1;
VL53L0X_RangingMeasurementData_t measure2;
VL53L0X_RangingMeasurementData_t measure3;
VL53L0X_RangingMeasurementData_t measure4;

  int old_dist_1 = 0;
  int old_dist_2 = 0;
  int old_dist_3 = 0;
  int old_dist_4 = 0; 

  int temp_bottom = 0; 
  int temp_top = 0;
  int nbr_p = 0;
  int id = 0;
  int itsOn = 0;
  int itsOnTimer = 30000;
  int turnOffLeds = 0;

  unsigned long time_passed_bottom;
  unsigned long time_passed_top;
  unsigned long time_passed_on;

void setID() {	
  // all reset
  digitalWrite(SHT_LOX1, LOW);    
  digitalWrite(SHT_LOX2, LOW);
  digitalWrite(SHT_LOX3, LOW);    
  digitalWrite(SHT_LOX4, LOW);  
  
  delay(10);
  // all unreset
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, HIGH);
  digitalWrite(SHT_LOX3, HIGH);
  digitalWrite(SHT_LOX4, HIGH);  
  delay(10);

  ///************************* sensor 1 activation 
  // activating LOX1 and reseting LOX2
  digitalWrite(SHT_LOX1, HIGH);
  digitalWrite(SHT_LOX2, LOW);
  digitalWrite(SHT_LOX3, LOW);
  digitalWrite(SHT_LOX4, LOW);

  // initing LOX1
  if(!lox1.begin(LOX1_ADDRESS)) {
    Serial.println(F("Failed to boot first VL53L0X"));
    while(1);
  }
  delay(10);

  ///************************* sensor 2 activation 
  // activating LOX2
  digitalWrite(SHT_LOX2, HIGH);
  delay(10);

  //initing LOX2
  if(!lox2.begin(LOX2_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  }
  
   ///************************* sensor3 activation  
  // activating LOX3
  digitalWrite(SHT_LOX3, HIGH);
  delay(10);

  //initing LOX3
  if(!lox3.begin(LOX3_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  }  
  
  
   ///************************* sensor4 activation  
  // activating LOX4
  digitalWrite(SHT_LOX4, HIGH);
  delay(10);

  //initing LOX4
  if(!lox4.begin(LOX4_ADDRESS)) {
    Serial.println(F("Failed to boot second VL53L0X"));
    while(1);
  } 
}

void read_quad_sensors() {
  
  lox1.rangingTest(&measure1, false); // pass in 'true' to get debug data printout!
  lox2.rangingTest(&measure2, false); // pass in 'true' to get debug data printout!
  lox3.rangingTest(&measure3, false); // pass in 'true' to get debug data printout!
  lox4.rangingTest(&measure4, false); // pass in 'true' to get debug data printout!
  
  if(round(measure1.RangeMilliMeter/10) < old_dist_1){
    id = 1;
    check_sens();
  }
  
  if(round(measure2.RangeMilliMeter/10) < old_dist_2){
    id = 2;
    check_sens();
  }
  
  if(round(measure3.RangeMilliMeter/10) < old_dist_3){
    id = 3;
    check_sens();
  }
  
  if(round(measure4.RangeMilliMeter/10) < old_dist_4){
    id = 4;
    check_sens();
  }

  old_dist_1 = round(measure1.RangeMilliMeter/10);
  old_dist_2 = round(measure2.RangeMilliMeter/10);
  old_dist_3 = round(measure3.RangeMilliMeter/10);
  old_dist_4 = round(measure4.RangeMilliMeter/10);

}

void setup() {
	///Robojax.com code see video https://youtu.be/0glBk917HPg
  Serial.begin(115200);

  // wait until serial port opens for native USB devices
  while (! Serial) { delay(1); }

  pinMode(SHT_LOX1, OUTPUT);
  pinMode(SHT_LOX2, OUTPUT);
  pinMode(SHT_LOX3, OUTPUT);
  pinMode(SHT_LOX4, OUTPUT);  

  Serial.println("Shutdown pins inited...");

  digitalWrite(SHT_LOX1, LOW);
  digitalWrite(SHT_LOX2, LOW);
  digitalWrite(SHT_LOX3, LOW);
  digitalWrite(SHT_LOX4, LOW);

  Serial.println("All four in reset mode...(pins are low)");
  
  Serial.println("Starting...");
  setID();

}

void check_sens() {
  
 if(temp_bottom == 0){
    if(id == 1 ){
      temp_bottom = id;
    }else if(id == 2 ){
      temp_bottom = id;
    };
    
   time_passed_bottom = millis();

  }else if(temp_bottom == 1){
    if(id == 2 ){
      if(nbr_p == 0){
        itsOn = 1;
        time_passed_on = millis();
        //bas_haut(strip.Color(255, 200, 40)); // Allumer la led de Bas vers le haut
      }
      nbr_p++;
    };
  }else if(temp_bottom == 2){
    if(id == 1 ){
      if(nbr_p == 1){
        itsOn = 0;
        //haut_bas(strip.Color(0, 0, 0)); // Eteindre de Haut vers le bas
      }
      nbr_p--;

      if(nbr_p < 0){
        nbr_p = 0;
      }
    };
  }

  // detecteur haut
  if(temp_top == 0){
    if(id == 3 ){
      temp_top = id;
    }else if(id == 4 ){
      temp_top = id;
    };
    
   time_passed_top = millis();
    
  }else if(temp_top == 4){
    if(id == 3 ){
      if(nbr_p == 0){
        itsOn = 1;        
        time_passed_on = millis();
        //haut_bas(strip.Color(255, 200, 40));// Allumer la led de Haut vers le bas
      }
      nbr_p++;
    };
  }else if(temp_top == 3){
    if(id == 4 ){
      if(nbr_p == 1){
        itsOn = 0;
        //bas_haut(strip.Color(0, 0, 0)); // Eteindre la led de Bas vers le haut
      }
      nbr_p--;
      if(nbr_p < 0){
        nbr_p = 0;
      }
    };
  } 
  Serial.println(nbr_p);
}

void loop() {
   
  read_quad_sensors();

  if(millis()-time_passed_bottom > 1000) {
   time_passed_bottom = millis(); 
   temp_bottom = 0;
  }

  if(millis()-time_passed_top > 1000) {
   time_passed_top = millis();
   temp_top = 0;
  }

  //reset if timer off
  if(itsOn == 1 && (millis()-time_passed_on > itsOnTimer)){
    //timer_off(strip.Color(0, 0, 0)); Eteindre la led
    itsOn = 0;
    nbr_p = 0;
  }
}

Merci de votre aide...

Il faudrait que tu expliques le principe de la détection.

Tu as 4 capteurs VL563L0X (temps de vol) :

Tu en as mis 2 en haut et 2 en bas ? Ils sont orientés comment, et que mesurent-ils ?
Je n'ai jamais fait ce genre de système ni utilisé ce capteur, donc il faut en dire plus pour qu'on puisse t'aider au mieux...

Oui autant pour moi :slightly_smiling_face:

Effectivement deux capteurs en bas et deux capteurs en haut (VL53LXX-v2) afin de déterminer, selon leurs mesures, si ca rentre ou si cela sort de l'escalier. Qui sont intégré dans le mur de l'escalier (et vise le mur opposé)

En gros ma logique étaient de prendre la valeur d'un capteur dans le loop, ensuite au prochain loop vérifier si cette valeur était différente si oui c'est qu'il y a détection.
Et ensuite donc mes 4 capteurs, ID1 le premier capteur en bas ID2 le deuxieme en bas, ID3 le premier en haut et enfin ID4 le deuxieme en haut

Si dans ma boucle j'ai ID1 puis ID2 je sais que quelqu'un rentre donc je rajoute au compteur de personne +1, etc etc.

Je n'ai pas tout lu attentivement, mais mon impression est la suivante :

  • tu vérifies si l'on passe devant le capteur en vérifiant que la valeur est inférieur à la précédente.
  if(round(measure1.RangeMilliMeter/10) < old_dist_1){
  • mais si tu restes devant, ce type de capteurs étant assez sensible de mémoire, les valeurs doivent varier en permanence. Tu dois assez souvent enregistrer du coup des valeurs inférieurs à la précédente (alors que tu penses rester immobile devant). D'ailleurs, ca serait pire si tu marches un peu en diagonal vers le capteur.

  • Il serait peut être plus pertinent de mémoriser la plus grande distance (moins une marge de sécurité) pour :

    • vérifier si tu coupes la zones que tu surveilles
    • mieux détecter la notion d'événement (tant que tu n'as pas rejoint la zone au repos, alors tu es toujours dans le même événement).

Remarque en passant, je n'ai pas la disposition exacte ni l'usage mais cela semble un peu difficile pour obtenir quelque chose de parfaitement fiable. Que se passe-t-il si 2 personnes passe en même temps par exemple. Si l'objectif est de faire des économies de lumières, peut être faut-il aussi prévoir un timer pour être sur que la lumière ne reste pas toujours allumer si quelque chose ne se passe pas comme prévu.

Effectivement les capteurs sont assez sensibles (pour cela que je divise leur valeur par 10 ... mais ce n'est pas encore assez).

Si deux personnes passent PILE en meme temps je pense que ca fera le compte pour 1, car pendant que la leds s'allume (sur 5m30 - +- 3 secondes), et vu que l'arduino n'est pas multi process, il ne fait rien d'autre que d'allumer la led et donc ne comptera qu'une personne et pareil à la sortie...

Quelle distance y a-t-il entre les deux capteurs proches ?
Si deux personnes coupent les faisceaux de deux capteurs extérieurs au même moment (ce qui est déjà très peu probable), il est pratiquement impossible qu'ils coupent aussi le deuxième faisceau au même moment. Donc il doit être possible de reconnaitre deux personnes plutôt qu'une seule.

Les capteurs sont espacés de +- 3cm.
Et meme ADMETTONS que cela compte 1 personnes au lieu de 2 qui monte en même temps, je ne vois pas trop le problème. Mon soucis premier est si on reste devant que le compteur monte. Et ca par contre ca fait un "Bug".

D'où ma demande initiale "Est-ce que mon code de détection est correct". :smiley:

Si ton code ne fait pas ce que tu veux, j'aurais tendance à dire non :slight_smile:
J'avoue que je n'ai pas pris le temps de décortiquer ton code.
Donc je me contenterais de te poser des questions.
Comment ton code détecte que c'est une nouvelle détection pour faire ton +1.
Ou dis autrement pourrais tu plutôt faire ton +1 a l'arrêt de la détection ?

Je suis étonné que @J-M-L n'ai pas sorti sa phrase favorite.
ce type de projet se prête bien à l'utilisation d'une machine à états.

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

:slight_smile:

Effectivement, j'avais été lire ce post :slight_smile:

Quel est le but de mettre deux capteurs à chaque bout de l'escalier ?
J'imagine que c'est pour détecter le sens de déplacement de la personne qui arrive à cet endroit. Mais deux capteurs trop proches l'un de l'autre risquent d'envoyer leur signaux en même temps voire même pas dans l'ordre attendu.

Je n'ai pas d'expérience sur ce genre de projet, mais je pense que tu devrais d'abord espacer tes capteurs (trouver la bonne distance par essais).

Je n'ai pas relu le code non plus car il est très long, n'a pas de commentaire, et les noms des variables n'aident pas à le comprendre (temp_bottom, itsOn, id, etc).

Oui désolé le code est pas bien expliqué.
Donc le but de deux capteurs est pour savoir si quelqu'un rentre ou sort de l'escalier. Avec un seul c'est impossible à savoir.

En gros je me suis inspiré de ceci: https://youtu.be/X8vHWPlUJSw?si=6tRnR2wXuNGQp-V-

Du coup tu n'a pas répondu à mes questions :frowning:

Désolé... je réponds.

J'enregistre en "loop 0" la distance de base de chaques detecteurs, ensuite lorsque la distance est réduite, j'enregistre l'ID du détecteurs. Et ensuite "j'attends" l'ID suivant.

Une fois une j'ai ca, j'ai un "cas". Si c'est par exemple ID1 et ensuite 2, je sais que quelqu'un rentre en bas de l'escalier donc j'incrémente le nombre de personne de 1 et SI je passe de 0 à 1 j'allume la led.

Et donc j'ai 4 cas, sauf que dans mes tests cela fonctionnait assez bien car je simulais des passages, j'avais oubié le cas que quelqu'un peux resté devant le capteur et donc l'incrémentation du nombre de personne augmente non stop...

Du coup tu fais ton +1 la première fois que ID2 est plus petite que la valeur mémoriser à vide?

Si c'est le cas, peut tu par exemple, ne faire un +1 que si ID2 repasse à la valeur à vide ?
en gros tu utilise un booléen pour faire l'incrémentation, qui passe à false quand tu fait +1 et repasse systématiquement à true lorsque ID1 repasse à sa valeur à vide ?

C'est une idée théorique à mettre en relativité avec la pratique.

1 Like

Oui, enfin tes tests ne traitent pas tous les cas.
Tu pourrais très bien avoir ID1 puis ID3 si deux personnes se présentent devant l'escalier l'une en haut et l'autre en bas. Elles vont se faire des politesses "après toi" "non, vas-y". Elles vont reculer, puis avancer et là ta logique de test est perdue.

Pour ton problème de comptage non stop, il ne faut pas travailler avec des états mais sur des changements d'états. Si on a une transition on compte si l'état est stable on ne fait rien.

1 Like

A mon sens tout ceci est une prise de tête inutile.
Deux capteurs, un timer rearmable, et hop, ça roule. En tous cas, c'est ce que j'ai fait chez moi et c'est tout à fait satisfaisant.

Effet comme ceci possible ?

C'est toi qui code, c'est toi qui décide :slight_smile:

A mon sens tout ceci est une prise de tête inutile.
Un interrupteur en haut, un interrupteur en bas et hop, ça roule. En tous cas, c'est ce que j'ai fait chez moi et c'est tout à fait satisfaisant :laughing:

1 Like