Arduino Ultrasonic Parking Sensor

I'm just getting into coding and wrote this simple code to build a parking sensor. It works for the most part but I'm having trouble getting the LED to turn off after certain time of no movement and resetting/looping to the beginning. What am I doing wrong here?
I'd appreciate any feedback.

int distance;
unsigned long startTime = 0;

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);

  Serial.begin(9600);
}

void loop() {
  digitalWrite(2, HIGH);
  delayMicroseconds(10);
  digitalWrite(2, LOW);
  delayMicroseconds(5);
  digitalWrite(2, HIGH);
  int pulseDuration = pulseIn(3, HIGH);
  distance = (pulseDuration * 0.0343) / 2;
  Serial.print("Distance from sensor to object is = ");
  Serial.println(distance);
  delay(5);
  
  controlLEDs(distance);

  if (millis() - startTime > 10000) {
    distance = 0;
    startTime = millis();
    
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
  }
}

void controlLEDs(int distance) {
  if (distance < 0 || distance > 200) {
    // Handle out of range distance
    return;
  }

  if (distance < 10) {
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, HIGH);
  } else if (distance <= 15) {
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(6, LOW);
  } else if (distance <= 20) {
    digitalWrite(4, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
  } else {
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
    digitalWrite(6, LOW);
  }
}

Understanding what your code does would be made easier if you gave the pins names rather than using anonymous pin numbers

Under what circumstances do you want the LEDs to turn off ?

Suppose that the distance is currently 5, then all 3 LEDs will be on. When the LED timeout occurs you turn them all off but the distance is still 5 so all of them come on again immediately

What do you want to happen if the distance is 5 and the timeout occurs ?

Thank you for the suggestion. I made the changes to give proper names to the pins.
I want all the LEDs to turn off after distance is 5 and no movement for 30 seconds. Then turn back on if the sensor detects movement. I tried adding bool movementDetected but still getting same result...

int distance;
unsigned long startTime = 0;
bool movementDetected = false;

const int trig = 3;
const int echo = 2;

const int LED1 = 4;
const int LED2 = 5;
const int LED3 = 6;

void setup()
{
  pinMode(trig , OUTPUT);
  pinMode(echo , INPUT);
  
  pinMode(LED1 , OUTPUT);
  pinMode(LED2 , OUTPUT);
  pinMode(LED3 , OUTPUT);

  Serial.begin(9600);
}

void loop() {
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  delayMicroseconds(LED2);
  digitalWrite(trig, HIGH);
  int pulseDuration = pulseIn(echo, HIGH);
  distance = (pulseDuration * 0.0343) / 2;
  Serial.print("Distance from sensor to object is = ");
  Serial.println(distance);
  delay(LED2);
  
  controlLEDs(distance);

  if (distance > 0) {
    movementDetected = true;
    startTime = millis();
  }
  if (millis() - startTime > 30000) {
    distance = 0;
    startTime = millis();
    
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }
}

void controlLEDs(int distance) {
  if (distance < 0 || distance > 200) {
    // Handle out of range distance
    return;
  }

  if (distance < 10) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED1, HIGH);
  } else if (distance <= 15) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED1, LOW);
  } else if (distance <= 20) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  } else {
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }
}

You need to set movementDetected to true every time the distance changes. To do this you need to compare the current distance with the previous distance

If the distance does not change between readings then set movementDetected to false and save the start time. If 30 seconds elapses since movementDetected became false then turn off the LEDs.

Thank you so much for your feedbacks and patience. Here's the updated code. It's obviously still missing something since I'm getting the same result.

int distance;
int previousDistance = 0;
int lastDistance = -1; // To keep track of the previous distance reading
unsigned long startTime = 0;
unsigned long prevTime = 0; // To store the time when movement was last detected
bool movementDetected = false;

const int trig = 3;
const int echo = 2;

const int LED1 = 4;
const int LED2 = 5;
const int LED3 = 6;

void setup()
{
  pinMode(trig , OUTPUT);
  pinMode(echo , INPUT);
  
  pinMode(LED1 , OUTPUT);
  pinMode(LED2 , OUTPUT);
  pinMode(LED3 , OUTPUT);

  Serial.begin(9600);
}

void loop() {
  digitalWrite(trig, HIGH);
  delayMicroseconds(10);
  digitalWrite(trig, LOW);
  delayMicroseconds(LED2);
  digitalWrite(trig, HIGH);
  int pulseDuration = pulseIn(echo, HIGH);
  distance = (pulseDuration * 0.0343) / 2;
  Serial.print("Distance from sensor to object is = ");
  Serial.println(distance);
  delay(LED2);
  
  if (distance != previousDistance) {
    movementDetected = true;
    previousDistance = distance;
    startTime = millis();
  } else if (millis() - startTime > 30000 && !movementDetected) {
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }

  controlLEDs(distance);

  if (distance != lastDistance) {
    // Distance has changed, set movementDetected to true and update startTime
    movementDetected = true;
    startTime = millis();
    lastDistance = distance;
  } else if (!movementDetected && millis() - prevTime > 30000) {
    // Reset distance and LEDs if no movement detected for 30 seconds
    distance = 0;
    startTime = millis();
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }

  // Save previous time if movementDetected is false
  if (!movementDetected) {
    prevTime = millis();
  }
}

void controlLEDs(int distance) {
  if (distance < 0 || distance > 200) {
    // Handle out of range distance
    return;
  }

  if (distance < 10) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED1, HIGH);
  } else if (distance <= 15) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED1, LOW);
  } else if (distance <= 20) {
    digitalWrite(LED3, HIGH);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  } else {
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }
}

Distance is 5 AND no movement for 30 seconds. Yes, both have to be true. I changed the part you mentioned to the code below. The more updated code is posted just above.

if (distance != lastDistance) {
    // Distance has changed, set movementDetected to true and update startTime
    movementDetected = true;
    startTime = millis();
    lastDistance = distance;
  } else if (!movementDetected && millis() - prevTime > 30000) {
    // Reset distance and LEDs if no movement detected for 30 seconds
    distance = 0;
    startTime = millis();
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);
  }

  // Save previous time if movementDetected is false
  if (!movementDetected) {
    prevTime = millis();
  }

Is it finished or you need any more help

I'm still stuck trying to get the LED to turn off after 30 seconds of no movement and distance 5. Tried to implement the suggestions above but I can't figure out what else I'm missing.

Isn't the code below resetting when there is movement?

 } else if (!movementDetected && millis() - prevTime > 10000) {
    // Reset distance and LEDs if no movement detected for 30 seconds
    distance = 0;
    startTime = millis();
    digitalWrite(LED3, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED1, LOW);

I think you need add a condition where no movement is detected like this

if(distance == lastDistance){
   movementDetected = false;
}

Because in your code only at beggining movement detected is false then after finding movement it changes to true state and does not change back to false state .You haven't provided that part so the condition will never become true.so try add something like that in program

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