Master a Button - AVR MCU Code
In this video, I am going to demonstrate that a simple button can actually be so complicated that 99 percent of the people would not know how to code it properly, yet this simplest component is so useful that we simply can not afford not to master it.
The complexity depends on the application. For example, a flashlight normally has 1 button, the on or off switch, but a flashlight also is more ideal if it can be dimmable, therefore most flashlights on the market today use a power on cycle to switch between various modes. This means to stay on one mode, you need to press that button many times, and this is absolutely tedious and not fun.
Ideally, the power on button should turn the flashlight on or off, then mode can be switched using double click. This is actually a very advanced problem. It concerns low power mode and watchdog, of which both are hard to code properly and prone to unforeseeable bugs. My prototype light guard has solved this problem flawlessly, so much so that it uses negligible amount of power when the flashlight is in the off state, and when it's on, the MCU is still under low power mode and all the juice from the battery goes to powering the LED. This may not seem like a very advanced problem, but it really is, but as far as buttons goes, a much harder problem exists, and this after all is a simple flashlight.
Let's talk about button de-bounce. The concept is well-known, but it's less known that button de-bounce can be used to avoid accidental button presses that turn the device On. A longer 500 milliseconds button de-bounce can eliminate most of the accidental power on. As demonstrated on this another LED stripe prototype board that actually uses a touch sensing based button. I don't want the light to switch on by accident, so I added a longer de-bounce timing to it that the light only gets to turn on if the touching pad is held for 500 milliseconds. The button de-bounce timing here is actually using power down mode and watchdog extensively, so this type of seemingly simple project is actually more demanding and requires the timing of various power down modes. The MCU for a majority of the time is in deep sleep mode, and it wakes it up by the button event. Adding to the complexity is multiple amounts of triggering states. The aforementioned code is challenging enough, but adding double click, hold, or triple clicks into it would almost make it a mission impossible for most people to code, and doing so using one watchdog timer is a multidimensional brain twister practice.
The thing is, it's actually relatively straightforward to forward implement a watchdog as a de-bounce timer. Watchdog itself is a timeout based timer with a timing interval from 16 milliseconds to 8 seconds. This is almost ideal for timing various tasks for a button, but the timer setting needs to be modified under various conditions, and the fact that doing that itself can be tricky as a watchdog is an important core circuit for the MCU. A simple watchdog button de-bounce is easy: enabling watchdog interrupt when a button edge has occurred, and disable watchdog interrupt inside the watchdog routine. Other button triggering required the watchdog routine to track the previous status and to change its setting accordingly. In other words, a watchdog button is a state machine spanning the timing and powering up and down cycle of the MCU, triggered by both button events and its own time out periods.
I talk about low power a lot here because it's not a challenge to code the button under normal power up scenarios. I actually have a decent enough button library for that, but unfortunately it's not possible at all to write a library for a watchdog button. It's application dependent and it's low power, in the nano amp range. That is pretty much it. See you later, annihilator.