Skip to content

The combined button LED pin

jbaumann edited this page Oct 19, 2020 · 4 revisions

The Idea

We use an LED to communicate with the user. But to reduce power consumption as much as possible, we turn it on only for very short amounts of time (only 100ms for the actual blinking). To do that, we normally leave the pin floating (by changing it to an input state with a pull-up) and pull it to low to light the LED.

The effect depends on the LED, with most LEDs it is quite visible, I had one that was just barely visible at all, and another one that was so bright it was annoying. If the LED is not visible enough for your taste, either exchange it for another, brighter one or change the value of its resistor.

If our pin blinks the LED only 100ms, then it is unused for 90% of the time. And since our ATTiny is a wee bit short on pins, the logical conclusion is to use it for something else as well. And a button is the most obvious choice.

The Implementation

The LED is connected to the ATTiny and to Vcc (using a resistor). By pulling the pin to GND the LED lights up. If we now connect a button that is normally open to the pin and to GND, then as long as the button is not pressed the LED can be turned on and off without problems (see schematic).

If we press the button, then the pin is pulled to GND and the LED lights up. This could lead to problems if we would, at the same time, try to actively pull the pin high as an output, but as long as we don‘t do that (and why should we?) we are safe. Even better, we have a very nice direct user feedback.

On the software side we normally set the pin to input with pull-up and turn on the interrupt signalling a change on this input pin. This allows us to continue our sleep (to conserve energy) while waiting for a user interaction.

If we want to turn on the LED, we first stop the interrupts, then turn the pin to low output and wait for the 100ms. During this time, a button press is not recognized but most button presses are longer anyway. And by giving an additional feedback when the button press has been detected (by blinking the LED a number of times) the user knows when a button press was successful.

Normally, we would have to debounce the button. But since we have an idempotent operation that simply sets the bit value SL_BUTTON in the variable should_shutdown, this shouldn‘t be a problem in most cases. There is one exception: If the button value is read and reset by the Raspberry while the button is still in its bouncing phase, then this could lead to the value being set a second time with only one user interaction. Though even that would not be a problem, because the only result would be that the ATTiny tries to signal a Raspberry to shut down that is currently in the process of doing so. But still, we check for that condition in the interrupt routine simply to be on the safe side.

Clone this wiki locally