Capítulo 1 INTRODUCCIÓN
1.8. Contexto de la Organización
1.8.1. Comprensión de la Organización y su contexto
We have two distinct elements on which we can act: • The circuit itself
The circuit itself can be modified. I could quote some solutions such as adding diodes, capacitors, and some Schmitt trigger inverters. I won't explain that solution in detail because we are going to do that in software, but I can explain the global concept. The capacitor in that case will be charged and discharged while the switch will be bouncing, smoothing those peaks of noise. Of course, some tests are needed in order to find the perfect components fitting your precise needs.
The firmware can also be modified.
Basically, we can use a time-based filter, because the bounce occurs during a particular amount of time.
Following is the code, then will come explanations:
const int switchPin = 2; // pin of the digital input related to the switch
const int ledPin = 13; // pin of the board built-in LED
int switchState = 0; // storage variable for current switch state
int lastSwitchState= LOW;
// variables related to the debouncing system long lastDebounceTime = 0;
long debounceDelay = 50; void setup() {
pinMode(ledPin, OUTPUT); // the led pin is setup as an output pinMode(switchPin, INPUT); // the switch pin is setup as an input }
void loop(){
// read the state of the digital pin int readInput = digitalRead(switchPin);
// if freshly read state is different than the last debounced value if (readInput != lastSwitchState){
// reset the debounce counter by storing the current uptime ms lastDebounceTime = millis();
}
// if the time since the last debounce is greater than the debounce delay
[ 176 ]
// store the value because it is a debounced one and we are safe switchState = readInput;
}
// store the last read state for the next loop comparison purpose lastSwitchState = readInput;
// modify the LED state according to the switch state if (switchState == HIGH)
{ // test if the switch is pushed or not
digitalWrite(ledPin, HIGH); // turn the LED ON if it is currently pushed
} else {
digitalWrite(ledPin, LOW); // turn the LED OFF if it is currently pushed
} }
Following is an example of the debouncing cycle. At the beginning, I defined some variables:
• lastSwitchState: This stores the last read state
• lastDebounceTime: This stores the moment when the last debounce occurred • debounceDelay: This is the value during which nothing is taken as a safe value We are using millis() here in order to measure the time. We already talked about this time function in Chapter 4, Improve Programming with Functions, Math, and Timing. Then, at each loop() cycle, I read the input but basically I don't store it in the switchState variable that is used to the test to turning ON or OFF the LED. Basically, I used to say that switchState is the official variable that I don't want to modify before the debounce process. Using other terms, I can say that I'm storing something in switchState only when I'm sure about the state, not before.
So I read the input at each cycle and I store it in readInput. I compare readInput to the lastSwitchState variable that is the last read value. If both variables are different, what does it mean? It means a change occurs, but it can be a bounce (unwanted event) or a real push. Anyway, in that case, we reset the counter by putting the current time provided by millis() to lastDebounceTime.
Then, we check if the time since the last debounce is greater than our delay. If it is, then we can consider the last readInput in this cycle as the real switch state and we can store it into the corresponding variable. In the other case, we store the last read value into lastSwitchState to keep it for the next cycle comparison.
This method is a general concept used to smooth inputs.
We can find here and there some examples of software debouncing used not only for switches but also for noisy inputs. In everything related to a user-driven event, I would advise using this kind of debouncer. But for everything related to system communication, debounce can be very useless and even a problem, because we can ignore some important messages and data. Why? Because a communication system is much faster than any user, and if we can use 50 ms as the time during which nothing is considered as a real push or a real release with users, we cannot do that for very fast chipset signals and other events that could occurs between systems themselves.
Summary
We have learnt a bit more about digital inputs. Digital inputs can be used directly, as we just did, or also indirectly. I'm using this term because indeed, we can use other peripherals for encoding data before sending them to digital inputs. I used some distance sensors that worked like that, using digital inputs and not analog inputs. They encoded distance and popped it out using the I2C protocol. Some specific operations were required to extract and use the distance. In this way, we are making an indirect use of digital inputs.
Another nice way to sense the world is the use of analog inputs. Indeed, this opens a new world of continuous values. Let's move on.