Combine while loop with digitalRead - Simple code that does not run

//Light led when KL15 input goes high, keep it lit for ~3000ms or until the input goes low (check digital status every 100ms)
const int led = 12;
const int KL15Pin = 2;
int OnTime = 0;
int OnTimeMax = 3000;
boolean start = true;

void setup() {                
  
  pinMode(led, OUTPUT);  // initiate ledpin as output
  pinMode(KL15Pin, INPUT);   // initiate KL15pin as input
//  attachInterrupt(0, blink, LOW);
}

// main loop
void loop() {
       
      if((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)){     //Initial 
          digitalWrite(led, HIGH);                                      // Light the led
          while((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)) {  //While loop that SHOULD end if the input goes low
            delay(100);                                                // wait 100 ms
            OnTime = OnTime + 100;                                     // increase the counter
          }
          digitalWrite(led, LOW);                                      //led off
          OnTime = OnTimeMax;                                          //to ensure that the ontime is set to max, case where the while loop was ended.
      }
        
      else if(digitalRead(KL15Pin == LOW)){                            //Wait until the input is low until we allow the led to go on again.
        OnTime = 0;
      }
}

This is a simple code which should turn on a led (and keep it on for approximately 3000ms) when the input goes HIGH. This part works. However I would also like to turn off the led in case the input goes low during that 3000ms. This part does NOT work. I check if the input is low every 100ms, and this is “fast enough” for my application. No interrupts needed.

It seems like that the "digitalRead(KL15Pin) == HIGH) " part in the while loop is always true, even though I connect this pin to LOW, the while is not ended.

Reading if the digitalpin is LOW works in other parts of the code, which makes me confused.

What did I do wrong? Seems so simple, but yet I can not get it to work.

Thanks,

while((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)) {  //While loop that SHOULD end if the input goes low
            delay(100);                                                // wait 100 ms
            OnTime = OnTime + 100;

Only the delay is part of the while loop.
Is that what you intended? Your indentation suggests otherwise.

AWOL:

while((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)) {  //While loop that SHOULD end if the input goes low

delay(100);                                                // wait 100 ms
            OnTime = OnTime + 100;



Only the delay is part of the while loop.
Is that what you intended? Your indentation suggests otherwise.

No this is not what I intended, why does not the while loop include everything between the "{" "}"?

Oops, sorry - couldn't see the brace on my phone.

Do you have a pulldown resistor connected between the input pin and ground?

WebWolf:
Reading if the digitalpin is LOW works in other parts of the code, which makes me confused.

What did I do wrong? Seems so simple, but yet I can not get it to work.

Thanks,

posting the whole code and a schematics could be a good idea :slight_smile:

how do you put the pin to LOW ? do you maintain it LOW for several seconds ?

alnath:

WebWolf:
Reading if the digitalpin is LOW works in other parts of the code, which makes me confused.

What did I do wrong? Seems so simple, but yet I can not get it to work.

Thanks,

posting the whole code and a schematics could be a good idea :slight_smile:

how do you put the pin to LOW ? do you maintain it LOW for several seconds ?

The whole code is posted, what I ment was that the elseif part is working.

dc42:
Do you have a pulldown resistor connected between the input pin and ground?

I read a digital signal in a vehicle, so I can not be sure.

However during my bench tests I have had a 10kOhm resistor to ground. But to be honest, if the pin was floating I would not have got this behavior (pin seems to be always TRUE in the while loop).

I have connected the pin directly to ground during the while loop (when the led is lit for 3 seconds) I can not get it to leave the while.

WebWolf:

dc42:
Do you have a pulldown resistor connected between the input pin and ground?

I read a digital signal in a vehicle, so I can not be sure.

However during my bench tests I have had a 10kOhm resistor to ground. But to be honest, if the pin was floating I would not have got this behavior (pin seems to be always TRUE in the while loop).

I have connected the pin directly to ground during the while loop (when the led is lit for 3 seconds) I can not get it to leave the while.

why ?

Did it work during these tests ?

Where ? In the vehicle ? Was it the same GND as the arduino's GND ?

What happens if you try it outside the vehicle, using a switch instead of "KL15" ? You could try with the internal pull-up resistor, making the input HIGH as soon as it is not actually connected to GND , or with a pull-down resistor if you prefer :wink:
If it works there and it doesn't work in the vehicle, then you'll have to find out where the problem is (interferences, digital signal not really 'LOW' ....etc... )

alnath:

WebWolf:

dc42:
Do you have a pulldown resistor connected between the input pin and ground?

I read a digital signal in a vehicle, so I can not be sure.

However during my bench tests I have had a 10kOhm resistor to ground. But to be honest, if the pin was floating I would not have got this behavior (pin seems to be always TRUE in the while loop).

I have connected the pin directly to ground during the while loop (when the led is lit for 3 seconds) I can not get it to leave the while.

why ?

Did it work during these tests ?

Where ? In the vehicle ? Was it the same GND as the arduino's GND ?

What happens if you try it outside the vehicle, using a switch instead of "KL15" ? You could try with the internal pull-up resistor, making the input HIGH as soon as it is not actually connected to GND , or with a pull-down resistor if you prefer :wink:
If it works there and it doesn't work in the vehicle, then you'll have to find out where the problem is (interferences, digital signal not really 'LOW' ....etc... )

I see the same behavior, in the vehicle as on bench tests, with or without pulldown resistor. This is why I suspect something to be erroneous in my code.

I also tried this:

if(digitalRead(KL15Pin) == HIGH)
           delay(100);

if(digitalRead(KL15Pin) == HIGH)
           delay(100);

if(digitalRead(KL15Pin) == HIGH)
           delay(100);

if(digitalRead(KL15Pin) == HIGH)
           delay(100);

//and so on....until the sum of all delays was ~3000ms

digitalWrite(led, LOW);

But even though I connected the pin directly to ground after triggering the first IF-sentence all of them where executed leaving the led on for ~3s.

But in general what you are saying is that the code "should" work and that it is something electrical?

remember the arduino does nothing during "delay()" . The reading only occurs between these delay() calls, and arduino runs fast.
are you sure you maintained the input LOW more than 1/10s ?
maybe you could try with the "blink without delay" approach : you turn led ON and start a timer when the input gets HIGH, and you turn the led off if the timer is over or the input gets LOW (whichever happens first)

alnath:
remember the arduino does nothing during “delay()” . The reading only occurs between these delay() calls, and arduino runs fast.
are you sure you maintained the input LOW more than 1/10s ?
maybe you could try with the “blink without delay” approach : you turn led ON and start a timer when the input gets HIGH, and you turn the led off if the timer is over or the input gets LOW (whichever happens first)

remember the arduino does nothing during “delay()” . The reading only occurs between these delay() calls, and arduino runs fast.
are you sure you maintained the input LOW more than 1/10s ?

Yes, I expect the arduino to be in a dumb loop when I call delay(). I am also sure that I kept the input low more than 1/10th of a second. I mean, I did tests with a lot of these if-statements, where it added up to 3s. I grounded the pin 2 with ground on the arduino board itself, but it was no different from having the pin connected to +5v.

However, I need to empathize that that in general reading the pin state works! I am currently running in the vehicle that waits for “KL15” to go high before proceeding.

Another question, how do I debug in the arduino environment? Can I simulate the code and set brake points?

OK, I've just tried it, with 2 changes (nothing important : LED on pin 13 and Serial output to see messages ) :

//Light led when KL15 input goes high, keep it lit for ~3000ms or until the input goes low (check digital status every 100ms)
const int led = 13;  // so that I don't need an external LED to see the result
const int KL15Pin = 2;
int OnTime = 0;
int OnTimeMax = 3000;
boolean start = true;

void setup() {                
  Serial.begin(38400);  // I'll send messages when needed
  pinMode(led, OUTPUT);  // initiate ledpin as output
  pinMode(KL15Pin, INPUT_PULLUP);   // initiate KL15pin as input + pull-up resistor
//  attachInterrupt(0, blink, LOW);
}

// main loop
void loop() {
       
      if((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)){     //Initial 
          digitalWrite(led, HIGH);                                      // Light the led
          while((digitalRead(KL15Pin) == HIGH) && (OnTime < OnTimeMax)) {  //While loop that SHOULD end if the input goes low
            delay(100);                                                // wait 100 ms
            OnTime = OnTime + 100;                                     // increase the counter
          }
          Serial.println("OFF");
          digitalWrite(led, LOW);                                      //led off
          OnTime = OnTimeMax;                                          //to ensure that the ontime is set to max, case where the while loop was ended.
      }
        
      else if(digitalRead(KL15Pin == LOW)){                            //Wait until the input is low until we allow the led to go on again.
        OnTime = 0;
      }
}

and it works as expected :
(remember I use the internal pull-up resistor)
While the input is not grounded, it is HIGH , and the LED is ON. Actually, it turns OFF every 3s, but the OFF state doesn't last enough to be seen :wink: , I see it happens because it sends "OFF" to the monitor .
When I connect pin 2 to GND, the LED turns OFF. This time, I can see it OFF (and the monitor sends the "OFF" message too ) .

Debugging Arduino is not very easy, but you can use the serial monitor and some Leds to tell you what happens.
Instead of writing "OFF" each time the while loop ends, I could have tested the Input state and written "GND" each time the Input is LOW.