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.
Reaction time is the duration of time it takes for the brain to interpret a stimulus and do something in reaction to it. The stimulus may be something visual such as a light turning on, something auditory such as a beep, or a touch cue such as a poke. The time it takes for the brain to interpret a stimulus and respond to it can be used as a basic benchmark to measure and compare mental acuity.
We will be implementing a reaction timer on an FPGA that turns on an LED after a psuedorandom period of time, and uses a pushbutton as a reaction input. There will be 3 input buttons: clear, start, and stop. The system will begin in an idle state waiting for the user to press the start button. When the start button is pressed, a random time interval will elapse before the LED turns on. When the LED turns on a reaction timer will begin counting the number of milliseconds until the user presses the stop button. When the stop button is pressed, the reaction time will be shown on a 4 digit 7-segment display in the format “0.000” seconds, up to a value of 9.999 seconds. The user can then press the clear button to reset the time display and go back to the idle state.
For this project we will be using the Basys 2 FPGA development board to implement the design, as it has the 4 digit display, pushbuttons, and LED that we need onboard.
Binary Coded Decimal format is a binary encoding of decimal numbers that represents each decimal digit by a fixed binary number. For example, 42 is represented in BCD format by the binary representations of 4 and 2, as shown above. The BCD format is common in electronic systems where numeric digits are displayed, as well as in systems where the rounding and conversion errors introduced by binary floating point representation and arithmetic are undesirable.
We will focus on designing a conversion circuit that converts a BCD formatted number to to a binary formatted number. I chose to detail this direction of conversion as binary to BCD conversion circuits are easily be found by a quick web search.
We will consider two algorithms to perform the conversion, the first being a direct arithmetic approach, and the second an iterative algorithm using a finite state machine with data path (FSMD).
We will be designing for the Basys 2 FPGA board which has 8 input switches. We can use the 8 input switches to encode 2 BCD numbers of 4 bits each. We will therefore concern ourselves with designing a circuit to convert a 2 digit BCD number to a 7 bit binary representation (27 = 128 > 99, the largest 2 digit BCD number we can input).