On door open - Logic problem

I got a LED indicator to toggle two LEDs when you open the door (ultrasonic sensor measure a lower distance). The problem to solve is that sometimes people leave the door open (distance < 30), and in that case the LEDs should become green after 5 seconds, and after the door is closed (distance >30) the LEDs should be RED and the indicator should work normally. Now if the door is leaved open, the LEDs toggle from red to green at every 4 seconds.

How do I solve this?
Many thanks.

#define echoPin 8
#define trigPin 7

long duration;
int distance;
int red_LED = 5;
int green_LED = 6;
int red_LED_int = 9;
int green_LED_int = 10;
int toggle = 0;

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(red_LED, OUTPUT);
  pinMode(green_LED, OUTPUT);
  pinMode(red_LED_int, OUTPUT);
  pinMode(green_LED_int, OUTPUT);
  analogWrite(green_LED, 255);
  analogWrite(green_LED_int, 10);
  Serial.begin(9600);
}
void loop() {
  //==============================================================
  // ULTRASONIC SENSOR TO CALCULATE DISTANCE
  //==============================================================
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration * 0.034 / 2;

  //==============================================================
  // LIGHT TOGGLE
  //==============================================================
  if (distance <  30)  {
    analogWrite(red_LED, toggle * 255);
    analogWrite(red_LED_int, toggle * 30);
    if (toggle == 1) toggle = 0; else toggle = 1;
    analogWrite(green_LED, toggle * 25);
    analogWrite(green_LED_int, toggle * 10);
    delay (5000);
  }
}

See the StateChangeDetection example.

Have you considered what would happen if the door is left ajar? What if the distance is exactly 30 cm? What if the draught makes it oscillate just around the 30-cm mark?

HINT: use a reed switch instead of ultrasounds.

int toggle = 0;

    if (toggle == 1)
      toggle = 0;
    else
      toggle = 10;

The first time through, since 0 is not 1, toggle gets set to 10.
Every time after that, since 10 is not 1, toggle gets set to 10.

It never happened, It's sliding, without hinges.
I just have to find a way to make it work in as much as possible situations without adding an PIR sensor or any other extra sensors. The most often situation is when you left door open. Maybe if I make the LED switch when you close the door, and not when you open it could help a little.

Sorry, it was a typo on post writing when I copied the code, it’s 1 in my code, the toggle function works, but I don’t know how to make it show green when door is open for more than 10 seconds and then work normally again when you close the door, starting with Red.

You should always copy the code that you post, not retype it.

Can you fully explain the behaviour you're looking for? So two LEDs, red and green. What are the various states/behaviours and at what distances do they occur?

It was copied, I touched the keyboard by mistake.

Two RGB leds that have to show the same color in the same time (for 2 different rooms).
When distance from sensor is < the leds toggle, from red to green and viceversa, but when you leave the door open, I want the leds to be green. And then red when you close it and so on.

So:
when distance < 30 door is open (green LED after 5 seconds)
when distance > 30 door is close (red LED)
?

Yes, that's right. And the toggle code should still work after the red LED is lit.

So something like:

#define ECHO_PIN 8
#define TRIG_PIN 7
int RED_LED_PIN = 5;
int GREEN_LED_PIN = 6;

float readDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  int duration = pulseIn(ECHO_PIN, HIGH);
  return duration * 0.034 / 2;
}

void setup() {
  pinMode(ECHO_PIN, INPUT);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  static unsigned long timeCapture;

  if (!timeCapture && readDistance() <= 31) {
    timeCapture = millis();
  }

  if (readDistance() >= 30) {
    digitalWrite(RED_LED_PIN, HIGH);
    digitalWrite(GREEN_LED_PIN, LOW);
    timeCapture = 0;
  }
  
  if(timeCapture && (millis() - timeCapture) >= 4000) {
    digitalWrite(GREEN_LED_PIN, HIGH);
    digitalWrite(RED_LED_PIN, LOW);
    timeCapture = 1;
  }
}

?

With this code the Red LED is always lit when you close the door,so if you leave with the door closed, it will show busy (RED). The green LED is on when door is open for longer than 4 seconds, but the toggle between lights when you close and open the door does not work anymore.

I think it follows what you've said, distance above 30 is led red on, distance below 30 waits 4 secs then turns green

At least that's the behaviour you confirmed in my last question.

Yes, but the toggle code should still be there. I think the logic is this, but I don't know how to do it:

The actual code is some kind of "normalMode", when the toggle LED code works.
Setup -> bool normalMode = true;

And when the door is open for more then, let's say 10 seconds,
the LEDs should turn green, like the room is free, in case you leave the sliding door open,
for ex. if distance < 30 && more then 10 seconds elapsed, normalMode = false.
if Normal mode = false {
analogWrite(green_LED, 225);

and then when you close the door (distance > 30), it should get back to the "normalMode" starting with LEDs being RED (room is busy).

Any ideas how this can be done?

I'd bet @st3v3n92 has something for you, but the wokwi.com link in his #16 is broken, at least here.

a7

I still don't think you've fully explained the problem you're trying to solve here and all of the scenarios inside. I think you're (understandably) trying to explain it using limited programming knowledge.

Can you try explaining the problem your project is trying to solve and your proposed solution, in as great detail as possible using little to no programming terms?

I've tried to read and amalgamate all of your previous hints at what you would like here. Because the more I pry the more info we're getting.

It seems to me like the setup is like an 'occupied' notifier for something like a meeting room, is that right?

So if the door is closed (meeting in session), you want the red LED to come on, to tell people that the room is busy and not to disturb.

If the door is open, you want the red LED to go off.

If the door has been left open for more than 5 seconds you want the green LED to come on so that people can see that the room is free to be used again?

Like this? sketch.ino - Wokwi Arduino Simulator

#define ECHO_PIN 8
#define TRIG_PIN 7
#define RED_LED_PIN 5
#define GREEN_LED_PIN 6
#define TIMEOUT 5000

float readDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  int duration = pulseIn(ECHO_PIN, HIGH);
  return duration * 0.034 / 2;
}

void setup() {
  Serial.begin(9600);
  pinMode(ECHO_PIN, INPUT);
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(GREEN_LED_PIN, OUTPUT);
}

void loop() {
  static unsigned long timeCapture;

  if (!timeCapture && readDistance() <= 31) {  // Door is Open - Waiting for Timeout...
    timeCapture = millis();
    digitalWrite(RED_LED_PIN, LOW);
  }

   if (readDistance() >= 30) { // Door is Closed - Room Occupied
    digitalWrite(RED_LED_PIN, HIGH);
    digitalWrite(GREEN_LED_PIN, LOW);
    timeCapture = 0;
  }

  
  if(timeCapture && (millis() - timeCapture) >= TIMEOUT) { // Open Timeout expired - Room Available
    digitalWrite(GREEN_LED_PIN, HIGH);
    timeCapture = 1;
  }
}