Pausing program until new sensor input received.

[code]
int trigPin=12;
int echoPin=11;
int pingTravelTime;
float pingTravelDistance;
float distanceToTarget;
int LEDpin=2;
int ledState = LOW; //used to set the LED
unsigned long previousMillis=0; //Stores the last time the LED was updated
const long blinkTime = 3000; //interval light stays on after distanceToTarget is <=2"


void setup() {
  // put your setup code here, to run once:
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(LEDpin, OUTPUT);
Serial.begin(9600);
}

void loop() {
  
  // time LED remains on after triggered because distanceToTarget reaches ,+2.
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
pingTravelTime=pulseIn(echoPin,HIGH);
pingTravelDistance=(pingTravelTime*765.*5280.*12.)/(3600.*1000000);
distanceToTarget=pingTravelDistance/2;
Serial.print("Your Distance to Target in inches is: ");
Serial.println(distanceToTarget);
unsigned long currentMillis=millis();

if(distanceToTarget<=2.){
long time_since_last_reset = millis(); //code from this point found on philo mech website
while((millis()-time_since_last_reset)<=blinkTime){
  digitalWrite (LEDpin, HIGH);

if ((millis()-time_since_last_reset)>blinkTime){
  digitalWrite (LEDpin, LOW);
delay (blinkTime);  //could also use the for loop for(;;){ but this permentantl stops the loop.

}
}
if(distanceToTarget<=2.){
long time_since_last_reset = millis(); //code from this point found on philo mech website
while((millis()-time_since_last_reset)<=blinkTime){
  digitalWrite (LEDpin, HIGH);

if ((millis()-time_since_last_reset)>blinkTime){
  digitalWrite (LEDpin, LOW);
delay (blinkTime);  
}
}
}
}
}

[/code]
I'm new, so apologies if this post is not well formatted. I'm using an UNO R3 and HCSRO4 ultrasonic sensor and an LED.
I want the LED to turn on when when within 2" of an object, then turn off after 3 seconds, which the above code accomplishes. I then want the LED to stay off until the object is more than 2" away, at which point I want the LED to turn on, then turn off after 3 seconds. I then want the LED to stay off until the object is within 2", etc. I have tried to make interrupts, delays, and change states work. I'm either doing them wrong or have not selected the correct method for achieving this. Can anyone head me in the right direction? Thanks.

Check out my tutorial on Writing Timers and Delays in Arduino
It includes an example of Delay execution until condition has been true for X secs which is the sort of thing you are looking for

A bit of information taken from: https://www.instructables.com/Improve-Ultrasonic-Range-Sensor-Accuracy/ This instructable will teach you how to improve the accuracy of an ultrasonic range sensor. It is based on the principle that sound will move through air at different speeds depending on the temperature. Since ultrasonic range sensors use the time it takes for the triggered sound to echo off an object and return to the sensor, the ambient temperature can play a role in the calculated distance. This answers your question with much more information then I can give you.

Thanks for the input. I'll check out both suggestions as soon as I can.

I read through Delay execution until.... about700 times (I'm new, and I'm an old man). It seems this will block a subsequent action based on setting a time. What I need is to block an action until new sensor data is available.

So let's say an object comes within 2" of the sensor. The LED turns on for 3 seconds, then turns off and stays off until the object moves to over 2" away, at which point the LED turns on for 3 seconds then turns off and stays off until the object comes within 2" of the sensor. The object might be within the 2 inches for 30 seconds, or 15 seconds, or 60 seconds, and the same applies to the time the object is beyond 2". In any case, the LED cannot turn on again until the distance criteria is met.

If I'm mistaken please accept my apologies.

My mistake. In that case, just a simple timer see Single Shot Delay example where the led/delay is triggered by the sensor distance and the led is turned off when the delay has justFinished(). Post your code if you have problems with the logic.

Again, thanks. That looks like it should work. I'll let you know if I can make it work or, more likely, if I screw it up.

Referring to the code in the Original Post...

If you use the AutoFormat tool to indent the code consistently it will be much easier to read it and to spot mistakes. Like this

int trigPin=12;
int echoPin=11;
int pingTravelTime;
float pingTravelDistance;
float distanceToTarget;
int LEDpin=2;
int ledState = LOW; //used to set the LED
unsigned long previousMillis=0; //Stores the last time the LED was updated
const long blinkTime = 3000; //interval light stays on after distanceToTarget is <=2"


void setup() {
        // put your setup code here, to run once:
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(LEDpin, OUTPUT);
    Serial.begin(9600);
}

void loop() {
  
        // time LED remains on after triggered because distanceToTarget reaches ,+2.
    digitalWrite(trigPin, LOW);
    delayMicroseconds(10);
    digitalWrite(trigPin,HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    pingTravelTime=pulseIn(echoPin,HIGH);
    pingTravelDistance=(pingTravelTime*765.*5280.*12.)/(3600.*1000000);
    distanceToTarget=pingTravelDistance/2;
    Serial.print("Your Distance to Target in inches is: ");
    Serial.println(distanceToTarget);
    unsigned long currentMillis=millis();

    if(distanceToTarget<=2.){
        long time_since_last_reset = millis(); //code from this point found on philo mech website
        while((millis() - time_since_last_reset) <= blinkTime){
            digitalWrite (LEDpin, HIGH);

            if ((millis() - time_since_last_reset) > blinkTime){
                digitalWrite (LEDpin, LOW);
                delay (blinkTime);  //could also use the for loop for(;;){ but this permentantl stops the loop.
            }
        }
        
        if(distanceToTarget<=2.){
            long time_since_last_reset = millis(); //code from this point found on philo mech website
            while((millis()-time_since_last_reset)<=blinkTime){
                digitalWrite (LEDpin, HIGH);

                if ((millis()-time_since_last_reset)>blinkTime){
                    digitalWrite (LEDpin, LOW);
                    delay (blinkTime);  
                }
            }
        }
    }
}

I see a couple (at least) of strange things.

{A} Inside the first if(distanceToTarget<=2.){ you have a second if(distanceToTarget<=2.){ which just duplicates the code of the first part

{B} In this code

        while((millis() - time_since_last_reset) <= blinkTime){
            digitalWrite (LEDpin, HIGH);

            if ((millis() - time_since_last_reset) > blinkTime){
                digitalWrite (LEDpin, LOW);
                delay (blinkTime);  //could also use the for loop for(;;){ but this permentantl stops the loop.
            }
        }

the IF clause can never be true because it contradicts the WHILE clause.

Your code for the sensor needs to take account of when the distance BECOMES <=2 rather than when it IS <= 2. That way it will only trigger the LED once. Something like this

previousDistanceToTarget = distanceToTarget;
distanceToTarget=pingTravelDistance/2;

if (distanceToTarget <= 2 and previousDistanceToTraget > 2) {
   ledMayBlink = true;
   blinkStartTime = millis();
}

Then, separately you can have an ledBlink() function that works something like this

void ledBlink() {
  if (ledMayBlink == true) {
     if (millis() - blinkStartTime >= 3000) {
        ledMayBlink = false;
        return;
     }
     if (millis() - prevBlinkTime >= blinkInterval) {
         digitalWrite(ledPin, ! digitalRead(ledPin)); // toggle LED
         prevBlinkTime  millis();
     }
  }
}

...R

Thanks. Didn't know about autoformat. VERY helpful. Digesting your other input - slow but steady progress.

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