How long should I wait for the pin to settle after setting the internal pullup on a digital pin, before reading it and being sure to get the correct value? I want to check if a normally vacant pin has been held to ground. The pin has been floating for a few microseconds since reset. So, I'm wondering roughly how many clock cycles to wait before reading. My MCU is running at 8 or 16 MHz.
I was on the fence about whether to post in programming questions or hardware questions sections. I suppose it is half about practice of programming and half about electrical hardware characteristics, so I picked here in the programming section.
You're suggesting no wait time. But then I wonder if there is "built-in" wait time because of the Arduino functions that are happening there, generating lots of instructions in the final compiled code. If I use direct port manipulation, I wonder if I would need to wait for the electrical characteristics of the pulling up to happen, before reading. I'm doing direct port manipulation, sorry for not mentioning that.
DDRD &= ~(1 << 2); PORTD |= (1 << 2);
if (PIND & (1 << 2))
//do stuff here
Perhaps I should have posted in hardware, because I'm realizing the question is really: how fast does pullup of a bare floating pin happen, to arrive at a guaranteed state of the pin is "on?" So it is an electronics question I suppose.
dmjlambert:
You're suggesting no wait time. But then I wonder if there is "built-in" wait time because of the Arduino functions that are happening there, generating lots of instructions in the final compiled code. If I use direct port manipulation, I wonder if I would need to wait for the electrical characteristics of the pulling up to happen, before reading. I'm doing direct port manipulation, sorry for not mentioning that.
DDRD &= ~(1 << 2); PORTD |= (1 << 2);
if (PIND & (1 << 2))
//do stuff here
This has 'never' caused problems with reading an input with my sketches.
You could trigger an oscilloscope with PINB while looking at the input pin.
You should see an image similar to the charging curve in the image below.
Use the scope to examine/measure the timing.
larryd:
If you think there is a problem, throw in 1 or 2 NOOPs between the pull-up and read instructions.
if (PIND & (1 << 2)) // Note the 'if' line would be sllloooowwww
Further more, are you turning pull-ups ON and OFF?
If not, just turn on pull-ups in setup() and leave them on, no problem.
I am turning on the pull-up in the bootloader, right after a reset or power on of the MCU. And then I read the pin and turn off the pull-up to get ready for the user program (sketch) to run and do whatever it's going to do with the pins.
I am no expert but if() must add some code prior to the PIND & (1 << 2) code, this would add delay after the turning on of your pull-up and the actual reading of your pin.
During this time, any reactance effects would surely settle out.
Ah, yes, I see what you mean. If the "if" and pin read take a dozen or so instructions, that would take less that a microsecond to execute. I will see if I can situate the pull up instruction and the pin read test in different parts of the bootloader, to give a few microseconds of time for the voltage on the pin to come up. I was reading the data sheet to see if there was any electrical characteristics of the pull up, such as a chart showing voltage vs. time, and didn't find anything. If I had that information I could be more scientific about this. It seems testing will need to suffice.
So the question is, how long does it take for the "1" bit in the port output register to propagate to the port input register? My guess is that it happens during the bit set instruction, otherwise the bit test and skip would fail.
You might be able to check with an LED on PD2, or with a scope.
jremington:
So the question is, how long does it take for the "1" bit in the port output register to propagate to the port input register? My guess is that it happens during the bit set instruction, otherwise the bit test and skip would fail.
That was not my intended question, but it's interesting. I expect the 1 in the port output register to be populated immediately during the instruction execution. The 1 does not propagate to the input register. The transistor that turns on the internal pull-up resistor will turn on (which will take some time), and voltage on the pin will begin to rise and continue rising until it is at approximately VCC. During the time that voltage is rising, when I read the input register I may or may not get a 1. After the voltage has arrived close enough to VCC level I will then read a 1 from the input register. By "close enough" I mean when it exceeds the threshold level necessary for the pin to read as a 1, and it's described in the data sheet as about 2.6V if VCC is 5.0V in the "I/O Pin Input Threshold Voltage vs. VCC" chart. Since the pin was floating at reset time, it could have been floating above or below this threshold, and I'm thinking the rise of the voltage due to the pullup may not be instantaneous because it is subject to electrical characteristics of the presumed bare pin and internals of the MCU that I don't fully understand. So, I'm just wondering if I need to wait a few clock cycles.
You may want to rethink this claim. Note that IN and OUT instructions are not involved in the code posted in reply #9.
The following program generates a pulse train on PD2 that is high for ~550 ns, and low for ~230 ns, according to my old, beat up, uncalibrated 100 MHz Tek 2235A scope. If I take out the "if" the pulse train is high for ~100 ns and low for ~240 ns
My only basis for this claim is that I know the programming and the electrical part of the project work together. So, here is my admittedly weak argument. It is logical to me that if the pin voltage is floating, and then when I turn on the pull-up, it will take some time for the pull-up to turn on, and after it turns on it will take time for the voltage to rise to a point above the threshold voltage necessary for reading a 1 on the input register (if it happens that it wasn't already floating above that threshold). If the pin is being held low such as shorted to ground, the voltage won't rise at all and the input register will not show me a 1. Based on that, I propose the 1 does not propagate from the port output register, which is being used to store the preference for the pull-up state, to the input register, which reads the voltage and decides whether to give me a 1 or 0.
Regarding how long these steps take, I assume the whole process happens pretty darned fast, but I don't know how fast compared to 16MHz clock cycles, and I prefer not to assume.
Turning to your original question about the input pullup, it is of course very weak and can't drive low impedance loads, nor even significant capacitive loads.
Using the following program, I find that "delay(1)" is required to see LOW on the port pin, but the rise time is too fast for me to measure.
With the only load on the output pin being the 10Meg/12 pF probe input impedance, the decay time for the output is surprisingly large, about 400 usec.
If you are using digitalRead() to read the pin, don't worry about a delay, the time it takes to translate the pin number to the PIN register and bit within that register is far longer than you'd ever need to wait.
@jremington, By decay time do you mean how long it takes after you turn off the pull-up for the voltage to go down below 2.6V or some other low voltage? The rise time too fast to measure with a 100MHz scope matches my assumption the pull-up of the actual voltage happens pretty darned fast. Could you run out and buy a brand new fancy fast scope to fully research this matter?
Thanks for looking into this with me, interesting and educating thread.
Thanks for input from DrAzzy and larryd, too. I'm not using digitalRead(), instead I'm doing direct port manipulation. Considering all I've read about NOOP in C++ and whether or not it really exists by the time it is or is not optimized out by the compiler, then considering do I need to insert some assembler code, all this is too much trouble, considering I could just put in an extra actual harmless instruction such as read a register, and have that burn some clock cycles.