Simple sketch with unexpected delay

I have a simple sketch that:
1.) turns a green led on and a red led off.
2.) senses via analogRead a voltage and if the voltage is below 5V, reverse the leds to green off, red on.

I test this by simply disconnected the voltage source going to the analog a0 pin through a L4940V5 voltage regulator and then through a 1k ohm resistor for isolation. Once I pull the wire on the voltage source, it takes about 1 sec before the leds change. I would’ve thought the change would happen nearly instanteously.

Can anyone explain the delay? I can’t believe the Uno would have that kind of cycle time in the main loop.

Thanks in advance for any help.
Here’s the sketch:

int grnled=10;
int redled=9;
int q1base=11;
int sense=0;
float vin= 0.0;
int onetimesw=0;
void setup()
{
pinMode(grnled,OUTPUT);
pinMode(redled,OUTPUT);
pinMode(q1base,OUTPUT);
Serial.begin(9600);
}
void loop()
{
if (onetimesw == 1)
{
//Serial.println(“bypass”);
//delay(500);
return;
}
digitalWrite(grnled,HIGH);
digitalWrite(redled,LOW);
digitalWrite(q1base,LOW);
vin=analogRead(sense);
if ( vin < 5 && onetimesw ==0 )
{
digitalWrite(grnled,LOW);
digitalWrite(redled,HIGH);
digitalWrite(q1base,HIGH);
//Serial.println(“switch on”);
onetimesw = 1;
}
}

I bet if you used Serial.print() to display the value returned from the analog read you would quickly be able to debug your program yourself!!!!

Paul

Just unplugging a pin doesn’t make it go to 0 volts. For that you’d have to connect it to ground. While you leave the pin floating it can read anything. You’re just watching the voltage fade away over the stray capacitance.

2.) senses via analogRead a voltage and if the voltage is below 5V, reverse the leds to green off, red on.

If you feed it anything more than 5V then you fry the Arduino. So it should ALWAYS read less than 5 volts.

  vin=analogRead(sense);
    if ( vin < 5 && onetimesw ==0 )
    {

But you aren’t actually testing for it being over 5V. A reading of 5 from the ADC is about 25 or so millivolts. I think you should probably do some reading on the reference page for analogRead.

Well, firstly, I would presume (and measured) the output of the V reg when I pull the source and it goes to 0 so I’d presume then the A0 pin wouldn’t be floating, rather it would have 0V on it, no?

Secondly, I see my problem in that the values will be from 1023 for max voltage (output of reg is 5V) and I should have been looking for a higher value. I changed my code to check for Vin to be < 900 and now the led’s change nearly instanteously, as I expected.

So, now it works as I expected, I can move forward. It’s actually intended as a backup battery switcher for my radio controlled helicopter. If for some reason the main battery fails, I switch to a smaller backup battery and turn on a buzzer and light a led. When the buzzer is on it means LAND NOW, because the backup battery doesn’t have near the capacity of the main.

Thanks for the inputs and replies. I’m using a IRLB8721 MOSFET as my switcher. I initially used a PN2222, but I couldn’t get that to work; I don’t know if the transistor was bad or it was something else.

Cheers!

Delta_G pretty-much covered it, but I'm going to throw a couple of other things at you...

  • Once you get the voltage measurement & calculation figured-out, be careful about trying to measure 5V (the upper limit of the ADC). Voltage regulators are not perfect (and the ADC can be off by one count). If Vcc (your ADC reference) happens to be a few millivolts higher than the voltage out of your L4940V5, the analog input will always read less than 5V. It's a little "safer" to set the threshold at 4.5V, or maybe 2.5V, or whatever makes sense. (But don't set it at 25mV. :wink: )

If you really need to detect higher-or-lower than 5V you can use a voltage divider (2 resistors) and set your threshold proportionally lower (and adjust your formula). With a voltage divider you can read more than 5V.

  • There are usually capacitors in the voltage regulator circuit and capacitors "store" voltage. If you disconnect the input to the voltage regulator, the 5V output won't instantly drop to zero.

  • Consider using a digital input. Anything greater than 3V (0.6Vcc) is read as digital-high and anything below 1.5V (0.3Vcc) is read as digital low. Anything in-between is undefined and might read high or low. (From the ATmega datasheet.)

If you're going to measure a battery you have to be a bit careful about the input voltage. If the reference is off then the measured voltage is off. If the battery starts to sag then the reference sags and the measured voltage looks like it is OK. The 1V1 internal reference may be off by 10% but it is rock solid. Whenever I do a battery monitor I like to use that and calibrate it with a few known values.

Thanks again folks...I forget about the capacitors at the input and output of the V regulator...my bad. I wasn't thinking clearly about everything as a whole when I wrote my sketch...

What chemistry battery are you using? Lithiums have a very flat discharge curve so they will hold voltage until end of discharge then "crash" so very hard to detect state of charge.

1/ You could use the internal 1.1 ADC reference rather than the +5 with a resistive divider. This is stable, though not very accurate, so you'd have to calibrate.

2/ A Li cell has very little capacity left by the time it falls to 3.7v, so you could choose eg 3.8 or 3.9 volts as your switch point. Overdisharging a Li cell also reduces it's life, so is to be avoided.

Allan

I also see that you declare vin to be a float, and sense to be an integer, zero.

Then your sketch does vin = analogRead(sense).

That doesn't make sense.

johncblacker:
Thanks again folks...I forget about the capacitors at the input and output of the V regulator...my bad. I wasn't thinking clearly about everything as a whole when I wrote my sketch...

No problem at all! Just a quick one though..... if you need help in future... the first part will do just fine.... ie.

"Can anyone explain the delay?" --- is fine.

Also... "the Uno would not have that kind of cycle time, right?" --- also fine.

..... avoid things like " I can't believe the Uno would have that kind of cycle time in the main loop."

That's mainly because most of the things we run into trouble with are not due to the device. It's just due to something we didn't do properly, or didn't do.

Great to hear that you found out the reason behind your observation.

Why is this project using analogRead() when it seems that digitalRead() would be sufficient?

...R