Blink button presses consistently missed


#1

In testing out a program, I found that button presses are being consistently missed if the button down portion is within a window under a second in duration. I’ve submitted an issue in github along with the program that can reproduce it, and accompanying output. In short, button releases are detected but not the preceding button push. Let me know if you need any further information or want help in diagnosing it. I’ll be traveling on vacation shortly so will be out of pocket (so to speak). Best, Ken


#2

Here’s an updated program that shows the buttonPress but no button clicks are ever registered. I believe the issue is in the button debounce handling (timing issue between that and the click window countdown) within the updateButtonState() in blinklib.cpp. The result of the test showing the problem is at the end of this comment.
------------- UPDATED BUTTON DETECTION ----------
#include “blinklib.h”
#include “blinkstate.h”
#include “Serial.h”

ServicePortSerial sp;

void setup() {
// put your setup code here, to run once:
sp.begin(500000);
}

void loop() {
// put your main code here, to run repeatedly:
bool buttonClickDetected = false;

if (buttonReleased()) {
if(buttonSingleClicked()) {
buttonClickDetected = true;
sp.print(millis());
sp.println(": buttonSingleClicked");
}
if (buttonDoubleClicked()) {
buttonClickDetected = true;
sp.print(millis());
sp.println(": buttonDoubleClicked");
}
if (buttonLongPressed()) {
buttonClickDetected = true;
sp.print(millis());
sp.println(": buttonLongPressed");
}
if (buttonMultiClicked()) {
buttonClickDetected = true;
sp.print(millis());
sp.println(": buttonMultiClicked");
}
if(buttonPressed()) {
sp.print(millis());
sp.println(": buttonPressed");
}
sp.print(millis());
sp.print(" buttonReleased “);
if(!buttonClickDetected)
sp.print(” MISSED CLICK: “);
sp.print(”: buttonClickCount=");
sp.println(buttonClickCount());
}
}
---------- PROGRAM END ------------
--------- TEST RESULTS -----------
12364 buttonReleased MISSED CLICK: : buttonClickCount=0
17187: buttonSingleClicked
17187: buttonPressed
17187 buttonReleased : buttonClickCount=1
21672: buttonSingleClicked
21672: buttonPressed
21672 buttonReleased : buttonClickCount=1
23347: buttonSingleClicked
23347: buttonPressed
23347 buttonReleased : buttonClickCount=1
24954: buttonPressed
24954 buttonReleased MISSED CLICK: : buttonClickCount=0
26244: buttonPressed
26244 buttonReleased MISSED CLICK: : buttonClickCount=0
27463: buttonPressed
27463 buttonReleased MISSED CLICK: : buttonClickCount=0
28677: buttonPressed
28677 buttonReleased MISSED CLICK: : buttonClickCount=0


#3

The problem shows up consistently if the delta between button press and button release is roughly 400ms (it ranged from 384 to 430ms in the tests).

In blinklib.cpp, the buttonClick count registers are only set true after the button is released and the clickWindowCountdown is zero, I placed them similarly in the Arduino test program so I could see more accurate time values.

If you press-release-press the button in roughly <1 second such that the 2nd press duration is within the clickWindowCountdown reaching 0 than (a) the clickPendingcount is reset to 0, (b) the pending clicks are lost, and © none of the clicked flags are set true (singleClickedFlag, doubleClickedFlag, multiClickedFlag). Which leads to the case where the buttonPressedFlag is true, the buttonReleasedFlag is true, and all of the xxxxClickedFlag’s are false.

I believe the reason for the missed click count is on line 370 of blinklib.cpp (and factoring in the debounce timing on the 2nd press):

clickPendingcount=0;        // Start next cycle (aborts any pending clicks if button was still down

The time delta’s I referenced above (copy/paste from Serial Monitor window):

17319: buttonPressed
17750 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 431
18247: buttonPressed
18631 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 384
19123: buttonPressed
19522 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 399
20014: buttonPressed
20428 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 414
20944: buttonPressed
21374 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 430
21903: buttonPressed
22318 buttonReleased MISSED CLICK: : buttonClickCount=0
DELTA(ms): 415


#4

This all boils down to what is the desired behavior?

I expected that if the button is pressed and released (at all) that a click count value (other than 0) would be registered somewhere. The current implementation does not guarantee that, which means that a false value returned from the buttonSingleClicked function does not mean that the button was not pressed. It only means that it wasn’t registered within the appropriate clickWindowCountdown window.

If the desired behavior is to have a click registered if the button is pressed than one possible temporary fix (until a more formal one is found) is that buttonSingleClicked returns true IFF buttonPressedFlag is true AND buttonReleasedFlag is true AND none of the xxxxClickFlags are true.

Thoughts?

ps: I’ll be traveling 9/8-9/16 and may not be able to respond during that time.


#5

Great test application, it exhibits a designed behavior that I can clarify with this diagram. The idea being that holding a click longer than the click window is a sign or indecision (kind of like clicking down and then dragging out of the button and releasing… This window is a way of giving the user an out from a click, as a click should be somewhat snappy…

The window also determines the latency at which clicks are detected. If we want to use buttonSingleClicked(), the action with be a full 330ms after our release, if we want it to be on the release, simply use butttonReleased(). This avoids firing a single click event on a double click or any multi click event. If the window grows, it increases the latency for the click flag to be set. 330ms felt responsive and quick to learn.

Here are diagrams of when/how the button flags are set (of course let me know if any of these are not accurately representing the implementation).






diagrams illustrated by @Vanilla :stuck_out_tongue:


#6

I understand what you’re saying but it leaves windows in which legitimate button presses are missed. Regardless, there should be a way to detect that the button was pressed at least once since the last time it was checked. I am evaluating if my suggestion on the button release flag will suffice here too. [Button release flag reflects stale data]


#7

Unfortunately, since Blinks is not reliably detecting button presses, it makes the game I created unreliable as well, which makes game players frustrated as they were hitting the button in time but Blinks was not seeing it. I will wait for Josh update to see if it fixes the problem.


#8

Checkout the Move38 dev branch, I believe it fixes this issue and will make it into master soon. Some additional wonderful updates to Dev, faster IR communication with a more robust signal through the silicone. More testing to be done here, but has seemed to make our games more playable with the silicone on in standard fluorescent office lighting.