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?

maxschlepzig
  • 531
  • 1
  • 4
  • 14

3 Answers3

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.

Majenko
  • 105,851
  • 5
  • 82
  • 139
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".

VE7JRO
  • 2,515
  • 19
  • 27
  • 29
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: