Electronic – External pull-ups with Atmel microcontrollers: what assumptions can be safely made about the impedance in tri-state mode

atmegapullup

Using an ATmega (the 48/88/168/328 family, if relevant) with a very weak supply, the internal pull-up resistors have proven to draw too much current.

The microcontroller is driven at very low clock speeds, with a supply between 2 and 3 V, with everything non-essential turned off, so that it uses less than 100 µA. This is all fine, but the device needs a few buttons. If I just connect the buttons to the ground, and use the integrated pull-up resistors, a single button, when pressed, can draw more current than the rest of the microcontroller. This would lead to the collapse of the power supply. Therefore I intend to set the pins to "tri-state", and use a much higher external pull-up than the integrated 20-50 k.

However, I have trouble specifying the value of the external pull-up. Obviously, I would like to have it as large as possible, while still being able to reliably detect a high logic level.

My problem is, that I couldn't find in documentation how high the high-Z really is. Searching through several forums the only indication was that it's measured in megaohms. But how high is it really? And what is the lowest value it can take? How can I find it out, besides trying to contact the manufacturer directly?

I wouldn't trust in an empirical method, as the internal pull-ups are specified in the datasheet as 20-50 k, a very generous range, so I guess the impedance in tri-state could also vary significantly.

I tried it with 330 k, and it worked, with a tolerable current draw in the 10 µA range. One method would be to increase the resistor until it no longer works, and then take a value significantly lower than that. However, as I don't know how much the impedance of the pin in tri-state mode can vary between devices, I doubt this would be the best approach.

Does anyone have more information or experience about it?

Best Answer

When tri-stated, the pin is actually considered as an input. So look at the datasheet for the "Input Leakage Current (IIH)" (given in table 30-1, page 314). It is 1µA max. Now, look at the voltage you need for identifying the high level correctly: "Input High Voltage (VIH)", given in the same table. It is 0.6Vcc min = 2.7V (I assume a 4.5V Vcc).

So you have your maximum pull-up value: R = U/I = (Vcc-VIH)/IIH = (4.5-2.7)/1µ = 1.8 MΩ.

Another solution to help in reducing the power consumption in your situation: do not activate the pull-up all the time. Check the button state every 100ms, for example, and just activate the pull-up for a few µS before checking the pin state (you need to activate the pull-up for a small time before checking, to overcome the parasitic capacitance of the track+pin). This way, you can have very low consumption without needing external pull-up. This forces you to check regularily, however. You can't just make the MCU sleep and wait for an interrupt on the button pin. Note: during the time you're not checking (when the pull-up is not activated), you need to set the pin as an output and force it to low level (same level as if the button was pressed), otherwise, if you keep the pin as an input, its level may be undefined (nothing drives it and there is no pull-up/down). This has a dramatic effect on power consumption if the voltage settles between high and low levels (even if the inputs are schmitt-triggered).