The image above exemplifies why you need to debounce your pushbuttons.
When people push a button, they expect one reaction per push. Due to the springy nature that pushes back at you when pressing them, buttons tend to bounce around when pressed and released, which will mess up the signal from them.
For example, let’s say we have a button that we intend to output 0V (logic 0) when pressed, and 5V (logic 1) when unpressed. If we probed the signal coming from the button during the transition from pushing it down to letting go, we would expect an immediate and clean transition from logic 0 to logic 1. What we end up seeing instead is the capture above. Before the signal settles to a flat 5V, it bounces between the two logic states many times.
Imagine if this was the signal your TV received when you pressed a button on your remote. If the signal was taken as is, and a transition from 0 to 1 meant increment the channel, you would probably have an aneurysm trying to navigate to a specific channel. This is why we need to debounce our buttons!
Debouncing attempts to ignore any intermittent jumping between logic states during an actual intended transition from 0 to 1 or 1 to 0. This can be done in hardware, with RC circuits and Schmitt trigger inverters, or in software with just the microcontroller. Let’s focus on software debouncing for now.
In this post we will first consider how to read a pushbutton input and turn on some LEDs in response. Next we will use the same hexadecimal counter circuit used in the previous post, with a pushbutton used to increment the counter, first with an undebounced implementation and then with a software debounced implementation
Often when a microcontroller is being used, we want it to know when certain things occur, and then have something happen in response. A simple example is to have a pushbutton determine when an LED turns on.
One implementation that would satisfy this is called “polling”. Inside of the main while loop we could test the state of an input pin every loop iteration and turn on an LED depending on its state.
The above psuedocode checks the pin state of an input pin connected to a pushbutton and depending on the state turns on or off an LED.
Polling a pin state becomes tricky when you have to do other things in your event loop, especially things that take a lot of time. If for instance you needed to send or interpret some kind of serial data, doing so would take many clock cycles. This would essentially add latency to the response time of the LED to the pushbutton, as checking the pin state would have the same priority as every other sequential task in the while loop.
Hardware interrupts allow for asynchronous handling of system events. If an interrupt is set for a pin, when the pin state changes the code execution in the main loop halts and the code inside an Interrupt Service Routine (ISR) function is executed.
In the previous post we learned how to blink an LED with an ATtiny85 by using a _delay_ms() function to halt the program execution after turning on and off the LED. The downside to this approach is that the _delay_ms() causes our code to hang up while the function spins in a loop up to the specified time. This is a waste of CPU clock cycles, and makes doing anything else in the event loop nearly impossible. Let’s stop the pointless spinning.
In this post I will introduce the two timer/counter hardware peripherals that are inside the ATtiny85 chip, and show how we can offload the job of blinking an LED to one of them with the added benefit of using no clock cycles on the task. This frees the CPU up to do whatever else we wish while our LED reliably blinks away. If you are coming from a typical Arduino upbringing, this sort of flexibility and power is what makes learning how to truly program a microcontroller and its peripherals worth the effort.
The ATtiny85 is a cute little AVR microcontroller that might surprise you with what it can do. We will be considering the 8 pin PDIP version shown above, since we can easily stick it in a breadboard and prototype away. In this project, we will get our toolchain up and running for the first time, and flash some code to blink an LED!