Robin2:
A common problem that arises in the Forum is switch bounce - I have to say I can't think how I would write a test to prove that my program could deal with that.
It's really not difficult.
Consider the example debouncing code provided by Arduino's website; I've delegated that code to a function called onLoop()
, as you might find in a library implementation.
[size=0.8em]Code: [url=https://arduinogetstarted.com/tools/arduino-code-highlighter]see how to post code[/url] [/size]
---
|
``` [size=0.8em][nobbc]// pretend that the "debounce" sketch is a library function that is run on every loop[/nobbc] |
[nobbc]// e.g.[/nobbc] |
[nobbc]// void loop() { onLoop(); }[/nobbc] |
[nobbc]//[/nobbc] |
const int[nobbc] buttonPin = 2; [/nobbc][nobbc]// the number of the pushbutton pin[/nobbc] |
const int[nobbc] ledPin = 13; [/nobbc][nobbc]// the number of the LED pin[/nobbc] |
const long[nobbc] debounceDelay = 50; [/nobbc][nobbc]// debounce time; increase if the output flickers[/nobbc] |
int[nobbc] ledState; [/nobbc][nobbc]// current state of the output pin[/nobbc] |
int[nobbc] buttonState; [/nobbc][nobbc]// current reading from the input pin[/nobbc] |
int[nobbc] lastButtonState; [/nobbc][nobbc]// previous reading from the input pin[/nobbc] |
unsigned long[nobbc] lastDebounceTime; [/nobbc][nobbc]// last time the output pin was toggled[/nobbc] |
void[nobbc] onLoop() {[/nobbc]
[nobbc]// read state, record time if the input flipped[/nobbc]
int[nobbc] reading = [/nobbc]digitalReadnobbc;[/nobbc]
if[nobbc] (reading != lastButtonState) lastDebounceTime = [/nobbc]millisnobbc;[/nobbc]
if[nobbc] (([/nobbc]millisnobbc - lastDebounceTime) > debounceDelay) {[/nobbc]
if[nobbc] (reading != buttonState) {[/nobbc]
buttonState = reading;
if[nobbc] (buttonState == [/nobbc]HIGH[nobbc]) ledState = !ledState;[/nobbc]
digitalWrite[nobbc](ledPin, ledState);[/nobbc]
}
}
lastButtonState = reading;
}[/size]
```
|
Here is one unit test that corresponding to one possible bounce case: a single bounce on the button pin (starts low, bounces from high to low, settles on high):
[size=0.8em]Code: [url=https://arduinogetstarted.com/tools/arduino-code-highlighter]see how to post code[/url] [/size]
---
|
``` [size=0.8em]unittest(bounce_low_to_high) { |
[nobbc] ledState = [/nobbc]LOW; |
[nobbc] buttonState = [/nobbc]LOW; |
[nobbc] lastButtonState = [/nobbc]LOW; |
lastDebounceTime = 0; |
[nobbc] assertEqual(1, state->digitalPin[ledPin].historySize()); [/nobbc][nobbc]// pin history contains only the initial LOW state[/nobbc]
[nobbc] state->[/nobbc]micros[nobbc] = 25000;[/nobbc]
[nobbc] state->digitalPin[buttonPin] = [/nobbc]HIGH[nobbc]; [/nobbc][nobbc]// set initial button entry to HIGH[/nobbc]
onLoop();
[nobbc] assertEqual(25, lastDebounceTime); [/nobbc][nobbc]// debounce time has reset[/nobbc]
[nobbc] assertEqual([/nobbc]LOW[nobbc], state->digitalPin[ledPin]); [/nobbc][nobbc]// no change in output[/nobbc]
[nobbc] assertEqual([/nobbc]HIGH[nobbc], lastButtonState);[/nobbc]
[nobbc] state->[/nobbc]micros[nobbc] = 50000;[/nobbc]
[nobbc] state->digitalPin[buttonPin] = [/nobbc]LOW[nobbc]; [/nobbc][nobbc]// bounce button LOW[/nobbc]
onLoop();
[nobbc] assertEqual(50, lastDebounceTime); [/nobbc][nobbc]// debounce time has reset[/nobbc]
[nobbc] assertEqual([/nobbc]LOW[nobbc], state->digitalPin[ledPin]); [/nobbc][nobbc]// no change in LED output[/nobbc]
[nobbc] assertEqual([/nobbc]LOW[nobbc], lastButtonState);[/nobbc]
[nobbc] state->[/nobbc]micros[nobbc] = 75000;[/nobbc]
[nobbc] state->digitalPin[buttonPin] = [/nobbc]HIGH[nobbc]; [/nobbc][nobbc]// bounce button HIGH[/nobbc]
onLoop();
[nobbc] assertEqual(75, lastDebounceTime); [/nobbc][nobbc]// debounce time is again reset[/nobbc]
[nobbc] assertEqual([/nobbc]LOW[nobbc], state->digitalPin[ledPin]); [/nobbc][nobbc]// still no change in LED output[/nobbc]
[nobbc] assertEqual([/nobbc]HIGH[nobbc], lastButtonState);[/nobbc]
[nobbc] state->[/nobbc]micros[nobbc] = 126000; [/nobbc][nobbc]// actual boundary case, time elapsed[/nobbc]
[nobbc] state->digitalPin[buttonPin] = [/nobbc]HIGH;
onLoop();
[nobbc] assertEqual(75, lastDebounceTime); [/nobbc][nobbc]// no additional bounce happened[/nobbc]
[nobbc] assertEqual([/nobbc]HIGH[nobbc], state->digitalPin[ledPin]); [/nobbc][nobbc]// therefore the LED turns on[/nobbc]
[nobbc] assertEqual(2, state->digitalPin[ledPin].historySize()); [/nobbc][nobbc]// digital output was written only once[/nobbc]
}[/size]
```
|
There is absolute control over "when" the pins are read and what values they have, so you are free to implement however many use cases you can conceive of.
The entire working example (the function under test followed by its unit tests) that I wrote can be found at arduino_ci/SampleProjects/TestSomething/test/debounce.cpp at master · Arduino-CI/arduino_ci · GitHub
An example of the CI running it can be found at https://github.com/Arduino-CI/arduino_ci/runs/1650531936?check_suite_focus=true#step:4:573
Does this answer your question of proof? What bounce behaviors would you want to see simulated, or which ones don't you believe to be possible?