Problem with loops of my program

Hi !
I have a problem concerning the programmation.
My project consist of measuring the time like a chronometer with an ultrasonic sensor and print it on a LCD module. A hand will go around a dial and I want to measure the time taken by the hand to make one turn.

When the hand moves more than 5mm away from the sensor the chrono starts, and when it comes back to its starting position (less than 5mm) the chrono stops before resetting because the hand is moving and does not stop at the end of the lap.

I would like to be able to display on the LCD module the value of the first lap only and this even if the hand passes the sensor again at the end of the lap.

I am sure there is a problem in the construction of my loops but i can't seem to fix it :frowning:

const byte TRIGGER = 6; 
const byte ECHO = 7; 
const unsigned long MEASURE_TIMEOUT = 25000UL; 
const float SOUND_SPEED = 340.0 / 1000;
float TempsAffiche;
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  
  lcd.begin(16, 2);
  
  
  Serial.begin(9600);
  pinMode(8, OUTPUT); // LED ROUGE 
  digitalWrite(8, LOW);
  pinMode(9, OUTPUT); // LED VERTE
  digitalWrite(9, HIGH);
  pinMode(TRIGGER, OUTPUT);
  digitalWrite(TRIGGER, LOW);
  pinMode(ECHO, INPUT);
}

void loop() {
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER, LOW);
  
  long measure = pulseIn(ECHO, HIGH, MEASURE_TIMEOUT);
  
  float distance_mm = measure / 2.0 * SOUND_SPEED;
  
  lcd.display();
  
  if (distance_mm > 50)
  {
    TempsDepart = millis ();
  }
  else if (distance_mm < 50)
  {
    TempsAffiche = (millis()- TempsDepart)/1000.0;
  }
  lcd.print(TempsAffiche,3);
  delay(50);
  lcd.clear();
}

this will be true always when your hand is away, so you keep reseting TempsDepart

read about state change detection (and state machines)

no sure the typical ultrasonic detectors like HC-SR04 range well at 5mm. Also their precision is within this range too... so your results may vary

The ultrasonic sensor has a minimum range of detection.

With a minimum range of 2cm and an error rate of +/-3mm/cm, and coupled with the other inherent issues with the SR04 module, 5mm may fall in the sr04 can't see well range.

Oops sorry, I didn't meant 5mm but 50mm !
So when the hand is away "TempsDepart" will keep reseting, but is there any way to make it stop reseting, so it will be true for ONLY 1 lap ?

What does that mean? A few pics of your working project, show where it works correctly and where it fails, please.

Comparing floats to ints does not always work as intended.

Comparing floats to floats works much better but will use more RAM.
if (distance_mm > 50.0f)

Here millis() an unsigned long does not math well with 2 floats. I'd use millis() as a float like so.
'(float(millis())/1000.0f)'

You need to keep track of what state your sketch is in, hence the term "state machine" as referenced in relply #2.

Your states could be WAITING_TO_START, RUNNING, and DONE. If you use enumerations, it even makes them human readable. Something like this

const byte TRIGGER = 6;
const byte ECHO = 7;
const unsigned long MEASURE_TIMEOUT = 25000UL;
const float SOUND_SPEED = 340.0 / 1000;
const float threshhold = 50.0;
float TempsAffiche;

unsigned long TempsDepart;

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

enum { WAITING_TO_START, RUNNING, DONE };
int state = WAITING_TO_START;

void setup() {

  Serial.begin(115200);
  lcd.begin(16, 2);
  pinMode(8, OUTPUT); // LED ROUGE
  digitalWrite(8, LOW);
  pinMode(9, OUTPUT); // LED VERTE
  digitalWrite(9, HIGH);
  pinMode(TRIGGER, OUTPUT);
  digitalWrite(TRIGGER, LOW);
  pinMode(ECHO, INPUT);
}

void loop() {
  digitalWrite(TRIGGER, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIGGER, LOW);

  long measure = pulseIn(ECHO, HIGH, MEASURE_TIMEOUT);

  float distance_mm = measure / 2.0 * SOUND_SPEED;

  switch (state) {
    case WAITING_TO_START:
      // if we are far away, begin timing
      if (distance_mm > threshhold) {
        TempsDepart = millis();
        state = RUNNING;
      }
      break;

    case RUNNING:
      // waiting for hand to come close again
      if (distance_mm < threshhold) {
        TempsAffiche = (millis() - TempsDepart) / 1000.0;
        lcd.setCursor(0, 0);
        lcd.print(TempsAffiche, 3);
        state = DONE;
      }
      break;

    case DONE:
      // all done, delay a bit, then start again
      delay(2000);
      lcd.clear();
      state = WAITING_TO_START;
      break;
  }
}

sorry I don't have my project next to me at the moment, I send a few pics as soon as possible !

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