Go Down

Topic: internal pullup resistors & digitalWrite (Read 17571 times) previous topic - next topic


Mar 28, 2010, 11:10 am Last Edit: Mar 28, 2010, 11:11 am by mem Reason: 1
It kind of mirrors pin 13 with the flashing LED - you can just plug an LED in without worrying about resistors.

Yes you can do that to make things simpler for beginners, but its not good practice.  The current Arduino boards do not have a resistor in series with pin 13 (its only in series with the internal LED) so the typical red LED plugged in directly will exceed the Atmel recommended pin current.

That, and starting off with external pull-downs are the way many people have been introduced to Arduino, but they are not necessarily the best way to learn.


So far, this all this discussion about pinMode parameters, code readability and maintaining vs breaking backwards compatibility has missed what is by far the largest novice user problem with the pullup resistors.

The problem is inside digitalWrite().  It activates and deactivates the pullup resistor when the pin is in input mode.

Novice users (and even experts) sometimes forget to use pinMode() to put the pin in OUTPUT mode.  This wouldn't be so bad, except that turning the pullup resistor on and off give the appearance the pin is working as an output.

Some time ago, at a local dorkbot meetup, a fairly new user was trying to build a simple tachometer for her bicycle, using a hall sensor hooked up to a pin and a bunch of LEDs to show if the code had detected changes.  She was mostly using parts she'd found for free, and believed something was wrong with the LEDs, because they were working but only very dim.   Several people looked at her board and tried different resistors, but nothing would work.  I tried a 100 ohm resistor, no luck.  Later, it occurred to me the pullup resistor was probably driving the LED, and indeed her code lacked pinMode()s to set the LED pins to output mode.

The primary problem is digitalWrite.

If the conceptual model being taught is the pin can be an INPUT or OUTPUT, when digitalWrite does something that appears to be working as an output, it is not following the user's understanding.  The fundamental problem is the user's conceptual model of digitalWrite differs from its actual behavior.

Unfortunately, changing digitalWrite() to not touch pins when they're in input mode will break lots of code.  The alternative is improving the user's model, but teaching input pullup resistors so early substantially raises the learning bar.

As another example, on a mail list a user was having a lot of trouble interfacing with a tiny motor.  He had reason to believe 40 mA should be enough.  Much discussion followed, about using transistors, about the actual needs of the motor, lots of back and forth about how to use a voltmeter, speculation if his multimeter's current mode was dead due to a blow fuse (all attempts read virtually no current).  No matter what he tried, the pin would output only a fraction of a volt with the motor connected, but produced the full 5 volts without it.  digitalWrite() struck again!

The huge problem is that unintentionally controlling the pullup resistor appears as if the pin is function as an output using digitalWrite(), leading the novice user and experts alike to pursue hardware troubleshooting, when in fact the problem is purely software.

Having said all that, I should mention that Teensyduino has disabled the pullup when pinMode(pin, INPUT) is used, and enabled it with pinMode(pin, INPUT_PULLUP).  Over the last year, Teensy has been used with most Arduino libraries and lots of existing code, and this has caused zero problems (and believe me, I am well aware of pretty much every detail that has caused compatibility issues).  Virtually all existing code that intentionally enables the pullup resistors does so by first called pinMode(pin, INPUT), and then the pullup is activated using digitalWrite(pin, HIGH).  I am not aware of any existing code which first uses digitalWrite, even though that would also work, with the caveat of driving the pin as an output for a brief time.

However, to truly fix digitialWrite() so it fits the conceptual model taught, it really needs to not touch the pin when input mode is configured.  That WILL BREAK ALL EXISTING CODE which uses pullup resistors.

Is the pain of reworking so much existing code worth it?


I'm not sure I see this as a big problem with digitalWrite().  "Your pin is working right as an output because you didn't set it as an output" is fairly understandable.  Yes, it's weird that the pins sort of works even when set as an input, but I'm not sure that's a problem that requires changing the behavior of digitalWrite().

Go Up