1

By default, all Arduino (ATmega328P) pins are configured for input without the internal pull-up enabled. This default seems to come from the AVR microcontroller itself.

When it comes to saving power - is this an optimal configuration for unused (and thus unconnected) pins?

Section 14.2.6 Unconnected Pins of the ATmega328P datasheet (page 88) recommends to configure pull-ups in order to save power:

If some pins are unused, it is recommended to ensure that these pins have a defined level. Even though most of the digital inputs are disabled in the deep sleep modes as described above, floating inputs should be avoided to reduce current consumption in all other modes where the digital inputs are enabled (Reset, Active mode and Idle mode).

The simplest method to ensure a defined level of an unused pin, is to enable the internal pull-up. In this case, the pull-up will be disabled during reset. If low power consumption during reset is important, it is recommended to use an external pull-up or pull-down.

So I'm tempted to call something like

for (uint8_t i = first_unused_pin; i < 20; ++i)
    pinMode(i, INPUT_PULLUP);

during setup.

Although, I don't understand where an increased power-consumption would come from when the INPUT pin is unconnected and no pull-up is active. I mean, since the pull-up is connected to VCC, there definitely is some current flowing, whereas without the pull-up I don't see where current would flow, since the pin is unconnected ...

However, Nick Gammon reports in his extensive article on power saving techniques (Section Configuring pins as inputs/outputs, Sketch D) an increased power consumption when 6 unused pins are configured as inputs with internal pull-ups attached:

All pins as inputs, and LOW (in other words, internal pull-ups disabled): 0.35 µA (same as before).

All pins as inputs, and HIGH (in other words, internal pull-ups enabled): 1.25 µA.

So the datasheet's statements seem to conflict with these results.

Is this an error in the datasheet are am I missing something?

4

3 Answers 3

3

Current is consumed when an input pin switches from HIGH to LOW or from LOW to HIGH. An unconnected "floating" input pin can change randomly depending on the local environment (EMI, noise, etc). That is unpredictable. The "it will consume more" is erroneous - it should be "it could consume more". The could is important, as I mentioned, it is unpredictable. By pulling up or down it is no longer unpredictable, as you have a defined steady state, and the input pin will not switch randomly.

Yes, you will get some leakage current through the pullup and the low-side MOSFET, but it is a defined predictable amount which you can incorporate into your design. If you want to reduce it then use larger external pullups (or pulldowns) to reduce the leakage current (note: using too large will start to encroach on the "floating" teritory again).

But when you're dealing with such small currents you're usually below the self-discharge equivalent current of your battery anyway, so saving a few nA isn't going to actually make the slightest bit of difference.

4
  • ok, yes, these are small amounts - re: '[..] so saving a few nA isn't going to actually make the slightest bit of difference'. Perhaps I'm missing something here, but isn't such leakage additive? I mean the self-discharge of a battery I have in any case - and on top of that I have to account for any additional leakage current, right? Also, what would be the worst-case that could happen when no pull-up is configured/attached to an unconnected input pin in terms of power usage (or something else)? Commented Jan 9, 2022 at 16:05
  • @maxschlepzig It's not quite as simple as that, since self discharge isn't a current per se, it's an effect of the chemistry of the battery. For example an NiMH can lose 30% of its charge in a month (NiMH is one of the worst for self discharge). But of course what current you draw is drawn from what is left in the battery, which is constantly depleting, and the less you draw the longer it will last, but when you've got (as in the NiMH example) about 3 months of potential runtime anyway trying to save enough power to last 6 months just isn't going to happen.
    – Majenko
    Commented Jan 9, 2022 at 16:18
  • You could try feeding a high frequency (few MHz) signal into all the unconnected pins when set as INPUT and measure the sleep current to see how (if) it increases.
    – Majenko
    Commented Jan 9, 2022 at 16:19
  • That's a great idea Majenko!
    – Nick Gammon
    Commented Jan 10, 2022 at 6:59
1

Although, I don't understand where an increased power-consumption would come from when the INPUT pin is unconnected and no pull-up is active.

This part of your question already has 2 answers, so I'll just answer the "power saving part".

The data sheet says "If some pins are unused, it is recommended to ensure that these pins have a defined level.". Configuring them with pinMode() to OUTPUT, then driving them LOW using digitalWrite() is perfectly acceptable, and MAY offer the greatest power saving / noise immunity of all.

If you look at "14.3 Alternate Port Functions" on page 89, you get a glimpse of the internal digital logic circuitry. When set to OUTPUT, the internal circuits provides a low impedance path to ground to sink current. What ever part of the internal circuitry that was "oscillating due to a floating input pin", causing the extra power consumption, is now connected to ground, or it's input is ignored, or how ever Microchip did it.

When you follow the I/O pin on Figure 14-2, it shows the INPUT_PULLUP circuitry at the top of the diagram, followed by the tri-state control lower down, then the SLEEP circuitry comprised of an analogue switch OR transmission gate if you prefer, inverter gate and N channel FET. When the Arduino is in some sleep modes, it "disconnects" the pin with the analog switch, and also grounds the Schmitt trigger input at the same time. What would be cool is if you could write "Arduino code" in the IDE to toggle this ON/OFF programmatically.

Figure 14-2

From the data sheet:

14.2.5 Digital Input Enable and Sleep Modes

As shown in Figure 14-2, the digital input signal can be clamped to ground at the input of the Schmitt Trigger. The signal denoted SLEEP in the figure, is set by the MCU Sleep Controller in Power-down mode, Power-save mode, and Standby mode to avoid high power consumption if some input signals are left floating, or have an analog signal level close to VCC/2.

The bottom line is, you don't want unused pins set as INPUT (Tri-state (Hi-Z) mode). See "Table 14-1. Port Pin Configurations".

8
  • My earlier testing would seem to confirm that setting the pins to OUTPUT and LOW probably has the lowest power consumption. In my tests setting them to INPUT also had low consumption, but that would probably vary depending on what is going on around the pins.
    – Nick Gammon
    Commented Jan 10, 2022 at 6:57
  • Ok - one issue with that approach (setting an unconnected pin to OUTPUT+low) is perhaps the behavior during reset, i.e. where the pin is set to INPUT for a short time. So, connecting external pull-ups to unused pins (and keeping them as INPUT) would help with that. However, I guess if you don't reset much, the savings (of OUTPUT+low vs. INPUT+pull-up) offset the potential 'waste' during reset by a large margin. I don't know, connecting all unused pins to external pull-ups feels a bit excessive. Commented Jan 10, 2022 at 21:39
  • @maxschlepzig - I don't recommend connecting the unused pins to anything. Are you commenting on something I've written in my answer, or on the comment above yours made by Nick Gammon?
    – VE7JRO
    Commented Jan 10, 2022 at 22:23
  • @maxschlepzig - Page 619 of the data sheet may shed some light on how much current is used during the re-set process. See: 35.12 Current Consumption in Reset and Reset Pulsewidth
    – VE7JRO
    Commented Jan 10, 2022 at 23:25
  • @VE7JRO I didn't say that you did. In my comment I just wanted to discuss the trade-offs of the method described in your answer (i.e. OUTPUT+low). So reset-behavior is - arguably - its only drawback, AFAICS - so, I just mentioned INPUT+external pull-up since it's the only alternative that yields a defined level also during reset. What I mean with reset behavior is this: during reset an unconnected pin (previously set to OUTPUT+low) is reset to INPUT until setup() runs. During that time-window of 1 s or so the level isn't defined, yet. 35.12 doesn't deal with that scenario, right? Commented Jan 11, 2022 at 21:08
0

The theory here is that an pin without a pull-up will probably float somewhere around the switching voltage. A bit of noise from the surroundings or whatever might push the pin up or down slightly, which will cause the internal circuitry to "flip" from high to low (or vice versa). All that flipping consumes quite a lot of power. The little tiny trickle from a pull-up resistor is so much smaller than the "flip cost" that it's worth using them.

I should also mention that it's very hard to test for a floating pin's consumption of power. Whenever you test it, you'll find it behaving very nicely, but as soon as you put it into a proper application it'll go crazy and won't work anywhere near your expectation. Putting in pull ups avoids this uncertainty, and lets you work with whatever the power consumption is when they're present.

I don't have the results any longer, but a while back I tried measuring the power consumption of the Arduino in various "idle" modes. The theory and practice did't match up terribly well.

It's possibly worth doing some tests, but IIRC, the lowest power setup was to set all pins as inputs and pull them low. In practice that's a lot of work to arrange, so setting them as inputs and using the internal pull-ups works nearly as well.

What you'll also find is that almost anything else will save far more power than the little trickle in the internal pull-ups. Here are some guides which might help:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.