What happens when I digitalRead() a pin that is in PWM output mode?

Hi there, I'm wondering what value would I get when I digitalRead() from a pin that is currently set to output in PWM mode (analogWrite)? Would I expect to read whatever value that is being driven by the PWM output, or would I get a fixed value?

Thanks much,

  • K.
1 Like

You will turn that output pin into an input pin, and your reading depends on what is connected to the pin.

@liudr,
have you a reference to confirm that?

I was thinking it would return the last value written to it... so it can return either a 1 or a 0 just depends....
NB digitalRead() does not call inputMode(...) ?

Note: there is some blinking led code like: digitalWrite(LED, !digitalRead(LED));

just wondering...

I would tend to agree with Rob. I certainly don't think that the data direction register would be changed (making the pin an input pin) since there are perfectly legitimate reasons to read from an output port and to write to an input port.

Don

I vaguely recall that the PWM module has its own pin driver. If that's true, then digitalRead returns the last value written to the pin before PWM was enabled.

You will turn that output pin into an input pin, and your reading depends on what is connected to the pin.

Not as I understand it.

Where a pin was last used with a PWM comman, a digital read of the pin without first performing a mode change statement will just read the last value written to the pin's data register. The voltage at the pin will remain to be the last value written by the pwm command, and the pin remains as a output pin because the pin's DDRx register bit was not changed, because of the lack of a mode change command prior to performing the digitRead command.

retrolefty:
Where a pin was last used with a PWM comman[d], a digital read of the pin without first performing a mode change statement will just read the last value written to the pin's data register. The voltage at the pin will remain to be the last value written by the pwm command

So far so good.

And here's the thing:

The PWM timer mode and prescale values for all timers are set up in the Arduino init() function (in wiring.c).
A call to analogWrite() for a PWM pin sets the duty cycle and makes the PWM signal connection to that pin. (See Footnote.)

The PWM signal itself is generated by the timer circuitry and does not go through the pin's output register.

If the value is zero the analogWrite() function writes a zero to the PWM pin's bit in that port's output register. (The timer signal is disconnected from the pin at this point.)

If the value is 255, the analogWrite() function writes a one to the PWM pin's bit in that port's output register. (The timer signal is disconnected from the pin at this point.)

Otherwise, the analogWrite() function connects the timer signal to the PWM pin and does not write anything to that pin's bit in the output register.

Bottom line: The output register bit values for all I/O pins are initialized to zero. If you have executed an analogWrite() function for a particular PWM pin and you have not subsequently executed a pinMode() function for that that pin to make it an input, digitalRead() will read a value of zero for that pin unless and until you have executed either a digitalWrite() with a value of one to that pin or an analogWrite() value of 255.

Post-bottom-line note: The digitalRead() function disconnects the timer from the pin, so PWM is no longer applied to the output. It definitely does not automatically set the pin mode to input, and the result is that the pin's bit value in the output register is applied to the pin. Subsequent analogWrite() function calls can be used to connect the timer signal to the PWM pin again.

Regards,

Dave

Footnote:
The analogWrite() function sets a pin to output mode. If the pin is a PWM pin it applies a signal from a timer. If you later perform a digitalWrite() to that pin, it disconnects the timer signal and makes the pin act as a normal output pin. Of course you can call the pinMode() function if you want to use the pin as a digital input. (After changing to input mode, executing digitalRead() for that pin turns off the timer.)

Finally, note that if you execute an analogWrite() function to a pin that is not one of the PWM pins, the function writes a zero if the byte value is less than 128, and writes a one if the byte value is greater than or equal to 128.

Thanks Dave, as allways excellent explanation!

Sorry. I thought I knew this but apparently I didn't. Thanks for correcting me.

davekw7x:
Post-bottom-line note: The digitalRead() function disconnects the timer from the pin, so PWM is no longer applied to the output. It definitely does not automatically set the pin mode to input, and the result is that the pin's bit value in the output register is applied to the pin. Subsequent analogWrite() function calls can be used to connect the timer signal to the PWM pin again.

Finally, note that if you execute an analogWrite() function to a pin that is not one of the PWM pins, the function writes a zero if the byte value is less than 128, and writes a one if the byte value is greater than or equal to 128.

Wow, thanks everyone, especially Dave. Some very interesting tidbits!!

So if I am resding this correctly, it seems like if a pin is sending PWM output and an attempt to digitalRead() from that pin will cause the PWM output to stop. Does the pin output revert to the last value that was set for this output pin, or just back to 0? I'm assuming the former.

It's also interesting to see the behavior of analogWrite() to a non-PWM pin - definitely not what I expected!

Thanks and kudos,

  • K.

It's also interesting to see the behavior of analogWrite() to a non-PWM pin - definitely not what I expected!

What did you expect?

I'd expect it to output 1 if the write value is anything but zero, like the digitalWrite() behavior.

I'd expect it to output 1 if the write value is anything but zero, like the digitalWrite() behavior.

You could make it do that, if that's what you'd like.