Is time taken by a digitalRead(pin) constant?

Hi

I am new to arduino and electronics in general and back to some coding after a hiatus of 20 years :slight_smile:

Reading a pin with digitalRead() in a tight loop, is it correct to assume that each call to digitalRead() for a specific pin takes the same time?

Doing some empirical testing on an UNO R3 I am getting constant values reading from the same pin even across power cycles although slightly different per pin.

I am just 'toying about' without a specific task at hand but the idea is to keep a rough track of the wall clock while polling for a pin state change without introducing added latency of time functions.

Thanks all

B

I presume checking a particular pin would be constant, except for variations introduced by the timer interrupt firing.

Why not use a pin-change interrupt?

I wouldn't want to assume that the elapsed time was consistent per pin or between pins, even if your empirical testing suggests it is. Is there some hard real time requirement which precludes the use of micros() or millis() to control time-based activities?

The timing does seem to be constant per pin but varies slightly across pins.

Nick - I tried to look up information about the timer interrupt but failed to land on anything that seems relevant. Is there a timer interrupt that fires to keep a clock updated and possibly other tasks?

Peter - On my uno r3 a digitalRead() takes > 4us. A micros() takes > 3us. So having both calls in a tight loop introduces about 8us per iteration.

The emphasis so far has been on 'toying about' as I ease myself back into some coding and acquaint myself to this joyous world of arduino + hobbyist electronics. In this specific case I was listening in to a device, a dht11 on pin 2, and wanted to visualise the change in signal which i did by storing in memory and then exporting and graphing.

synerr:
On my uno r3 a digitalRead() takes > 4us. A micros() takes > 3us. So having both calls in a tight loop introduces about 8us per iteration.

Are you trying to solve a problem which requires you to do more than one digital read per 8us and also know when the read occurred?

If you use PINB (or whatever) it only takes 1 clock cycle as far as I know, and could read 8 pins at the same time.

...R

synerr:
Nick - I tried to look up information about the timer interrupt but failed to land on anything that seems relevant. Is there a timer interrupt that fires to keep a clock updated and possibly other tasks?

Every 1024 ยตS an interrupt fires controlled by Timer 0, this is used to update the counter used by millis() and micros() function calls. It would take a few clock cycles to do this, hence this would introduce jitter into any tight loops.

just from the code from the core lib

int digitalRead(uint8_t pin)
{
	uint8_t timer = digitalPinToTimer(pin);
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);

	if (port == NOT_A_PIN) return LOW;

	// If the pin that support PWM output, we need to turn it off
	// before getting a digital reading.
	if (timer != NOT_ON_TIMER) turnOffPWM(timer);

	if (*portInputRegister(port) & bit) return HIGH;
	return LOW;
}

one can see that there are different code paths

  • the first return LOW is way faster than the second one
  • If turnOffPWM needs to be called makes a diff in timing.!!!
  • the last 2 paths I think are equal in time (compiler can optimize this I expect)

in short expect different timing

I said earlier "checking a particular pin would be constant".

Wouldn't that still be true? A certain pin is either on a timer or not, or valid or not. So for a particular pin (eg. 13) the path would be constant?

Thanks all for kind help. Mission now accomplished.

PeterH - As a learning exercise I wanted to write an interface to a DTH11 from which the arduino receives a digital transmission with pulses in the order of microseconds without looking at any reference implementation. To see what I was doing my first self imposed task was to visualise the incoming signal at the highest resolution possible. I achieved that by iterating tightly over a digitalRead() saving the state change and iteration number to an array, exporting the results, and graphing them

NickG - Thanks. From that code it does seem that at least for a pin not on a timer the read time should be the same while accounting for interrupt jitter. Found some reading points on interrupts. Now I know what I'm going to be doing next weekend.

Next time I'd recommend using interrupts to capture the edges, or (or you have some specific reason to poll them) use the fast digital pin library - a performance-optimised I/O library with a similar API to the standard Arduino digitalRead()/digitalWrite() functions. Using interrupts would be a better way to capture a high speed digital signal though, IMO.