12. Arduino for Production!! How to Receive Stable GPIO Push Button Input on the ARM Microcontroller - Software Debouncing Part 1
Share
Arduino has moved their chipset to powerful advanced chips like the ARM microcontroller architecture, so following these tutorials will you greatly is you are a follower of Arduino, especially if you are on the track to become a serious developer for production. Learning the bare chip method as shown in my videos and content will prepart you for more cost effective and efficient production rather than starting with Arduino which is geared towards one off projects.
In this video, we're going to make an LED toggle on and off every time we fully depress and release a push button. We will add a bit of complexity to our simple GPIO input for push buttons. Because the push button is a mechanical component, we are going to have some problems because, mechanically, the signal is going to bounce up and down. So, we need to take the bouncing out and only consider the pure high and low values that would be created from the push button when connected to a pin on the STM32 ARM Microcontroller.
Push button switches are mechanical components. Within this push button switch, you have leads that have contacts on the leads, and then there is a conductive area on the plunger of the push button that, when depressed, makes contact with the two leads and creates a circuit flowing between the two leads. This action causes problems electrically because mechanical actions happen much slower than electrical current flow.
You can have a scenario where a high signal (or a 1 in code) will become a low signal when the push button is depressed (of the push button is connected to ground, or the low signal when the two leads are connected). Of course, than can happen in reverse where the signal starts off low and then goes high when pressed (which is how we have our circuit connected.
What is happening; however, when you are pressing a push button, it starts low and when the push button is pressed, the voltage may bounce high and low several times before it stabilizes on the high signal. In software, while the pin is being read, this will be apparent and the pin will show many highs and lows.
Our intention is to eliminate the portion that will be bouncing high and low (1 and 0). Since we have an LED that is being toggled when the push button is pressed, we don't want the LED to toggle more than one time on a single push button press. This will happen if the microcontroller reads the bouncing portion. Imagine how frustrating it would be to press the power button on your TV remote and your TV turns on then off again unpredictably.
To eliminate the bouncing, we will use a counter when the push button is pressed and there is a stable high or low signal (many 1s or 0s in a row). We want to know if the push button is being pressed with a stable high signal and if the push button is not being pressed with a stable low signal. We don't want to count the unstable stuff and that stuff will have low counts.
If you look at code online, you will notice other programmers will implement a delay from the point in time that the push button is pressed. The delay is to theoretically pass the bouncing. There are a couple of reasons why I don't like this approach. First, code cannot be executed in a delay since a delay is just a loop of empty cycles from the microcontroller. And second, the time delay is only testing two points in time. The two points could still be some erroneous bouncing samples.
Alternatively, I would like the program test if the input pin is a one or a zero. If it is a one, it will test it again in the next cycle if it is a one again. If it is a zero, then the button pressed state is eliminated as not pressed. This process is done over and over until there is enough samples that the program can say, I am confident that the button is pressed. This works also vice versa for the state if the button is not pressed where it tests for a number of zero samples. The number of samples will be a variable that is called the confidence threshold. This idea is very similar to a state machine where the program cycles through operations and collects data as it goes and responds to that data.
So, specifically, how do we do this? We're measuring a zero on the pin and then we'll have some bouncing going on, then we'll end up on a high signal level (a one). We are going to have e a few variables we will be working with. the first variable is the most obvious, ButtonPressed. This variable will be equal to either a zero or a one telling me that if the button is pressed or not. The ButtonPressed variable will be a one if there are sufficient samples of ones. If there are sufficient low signal level samples (zeros), then the ButtonPressed Variable will be zero.
For this, we will need to introduce another variable, ButtonPressedConfidenceLevel and ButtonReleasedConfidenceLevel. What we will be doing is counting up the ButtonPressedConfidenceLevel when it matches a high level or a one and keep doing this until it reaches a confidence threshold, at which point the ButtonPressed variable can be changed to a one. There is an important consideration we need to implement. We need to be counting up the confidence level variables on when the opposite button state is present. For instance, the ButtonPressedConfidenceLevel will only be counting up if the ButtonPressed varaible is zero. It doesn't make sense to count up the ButtonPressedConfidenceLevel when the ButtonPressed is already equal to one. This is also true for the other state when counting up the ButtonReleasedConfidenceLevel. When this ButtonPressed is equal to one, then we can toggle the output pin (toggle the LED).