diloxus
December 21, 2021, 2:12pm
1
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
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();
}
J-M-L
December 21, 2021, 2:20pm
2
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.
diloxus
December 21, 2021, 2:34pm
4
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.
diloxus:
if (distance_mm > 50)
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)'
blh64
December 21, 2021, 3:00pm
7
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;
}
}
diloxus
December 21, 2021, 3:30pm
8
sorry I don't have my project next to me at the moment, I send a few pics as soon as possible !
system
Closed
June 19, 2022, 3:31pm
9
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.