英文:
Button2 Library isPressed() method return inverted?
问题
I am using two buttons on a Teensy 4.1 MCU to control a robot. I want to add debouncing (and further stuff like longpress etc.) and decided on the library Button2
link to Repo, which is apparently quite popular for this type of tasks.
The buttons are wired as shown in the figure below. They use input pulldown resistors. Adding the option INPUT_PULLDOWN
to the begin()
method does not make a difference in the problem I encountered.
I compiled a small program to test the library and ran it on the MCU. However, results are unexpected. The output of the method isPressed() seems to be inverted meaning the default value of an idle button is 1 instead of 0. Everything seems to be wired properly as using the digitalRead() returns the expected states of 1 when pressed and 0 when not pressed.
Adding to the problem is, that longpress and doubleclick work "wrong". In the Serial log you can see what I want to say: The button is pressed the first time and the library interprets this as a long press as it just sees the button was pressed from the start and then released.
Source code:
#include <Arduino.h>
#include <Button2.h>
#include <math.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 26 ///< Pin for status led
#define LED_COUNT 7 ///< Numbers of pins on the status led
#define BRIGHTNESS 10 ///< Brightness of pixels (prevents the LED from being a laserbeam)
#define COLOR_RED ((255 << 16) + (0 << 8) + (0))
#define COLOR_ORANGE ((255 << 16) + (155 << 8) + (0))
#define COLOR_YELLOW ((255 << 16) + (255 << 8) + (0))
#define COLOR_GREEN ((0 << 16) + (255 << 8) + (0))
#define COLOR_CYAN ((0 << 16) + (255 << 8) + (255))
#define COLOR_BLUE ((0 << 16) + (0 << 8) + (255))
#define COLOR_PURPLE ((155 << 16) + (0 << 8) + (255))
#define COLOR_MAGENTA ((255 << 16) + (0 << 8) + (255))
#define COLOR_WHITE ((255 << 16) + (255 << 8) + (255))
#define COLOR_TUM_DARKBLUE ((0 << 16) + (82 << 8) + (147))
#define COLOR_TUM_BLUE ((0 << 16) + (101 << 8) + (189))
#define COLOR_TUM_ORANGE ((227 << 16) + (114 << 8) + (34))
#define COLOR_TUM_GREEN ((162 << 16) + (173 << 8) + (0))
#define COLOR_OFF 0
#define RECORD_BUTTON 5 ///< Pin for record button
#define PLAY_BUTTON 6 ///< Pin for play button
#define DEBOUNCE_TIME_MS 50 ///< Debounce time in ms
Button2 playButton;
Button2 recordButton;
Adafruit_NeoPixel statusLED(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void statusLEDShineFullColorCode(int color) {
statusLED.fill(color);
statusLED.setBrightness(BRIGHTNESS);
statusLED.show();
}
void pressedHandler(Button2 &button){
Serial.println("Button was pressed");
statusLEDShineFullColorCode(COLOR_BLUE);
}
void longPressedHandler(Button2 &button){
Serial.println("Button was pressed long");
statusLEDShineFullColorCode(COLOR_GREEN);
}
void doubleClickedHandler(Button2 &button){
Serial.println("Button clicked twice!");
statusLEDShineFullColorCode(COLOR_RED);
}
void setupButtons(){
playButton.begin(PLAY_BUTTON);
recordButton.begin(RECORD_BUTTON);
playButton.setDebounceTime(50);
recordButton.setDebounceTime(50);
playButton.setDoubleClickTime(500);
recordButton.setDoubleClickTime(500);
playButton.setLongClickTime(1000);
recordButton.setLongClickTime(1000);
playButton.setClickHandler(pressedHandler);
recordButton.setClickHandler(pressedHandler);
playButton.setDoubleClickHandler(doubleClickedHandler);
recordButton.setDoubleClickHandler(doubleClickedHandler);
playButton.setLongClickHandler(longPressedHandler);
recordButton.setLongClickHandler(longPressedHandler);
}
void setup() {
statusLED.begin();
setupButtons();
Serial.begin(115200);
}
void loop() {
playButton.loop();
recordButton.loop();
statusLED.show();
if(millis()%1000 == 0){
Serial.println("Record button isPressed(): " + String(recordButton.isPressed()) + ", Play button isPressed(): " + String(playButton.isPressed()));
Serial.println("Record button digitalRead(): " + String(digitalRead(RECORD_BUTTON)) + ", Play button digitalRead(): " + String(digitalRead(PLAY_BUTTON)));
}
}
Serial Log (comments from me added after the fact indexed with #):
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Button was pressed long # here the record button is pressed the first time, but Button2 thinks this was pressed until now
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed isPressed() = 0, digitalRead() = 1 (WTF?)
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed():
<details>
<summary>英文:</summary>
I am using two buttons on a teensy 4.1 MCU to control a robot. I want to add debouncing (and further stuff like longpress etc.) and decided on the library `Button2` (https://github.com/LennartHennigs/Button2), which is apparently quite popular for this type of tasks.
The buttons are wired as shown in the figure below. They use input pulldown resistors. Adding the option ```INPUT_PULLDOWN``` to the `begin()` method does not make a difference in the problem I encountered. [![Crude Wiring Diagram of MCU](https://i.stack.imgur.com/A9qFv.png)](https://i.stack.imgur.com/A9qFv.png)
I compiled a small program to test the library and ran it on the MCU. However, results are unexpected. The output of the method isPressed() seems to be inverted meaning the default value of an idle button is 1 instead of 0. Everything seems to be wired properly as using the `digitalRead()` returns the expected states of 1 when pressed and 0 when not pressed.
Adding to the problem is, that longpress and doubleclick work "wrong". In the Serial log you can see what I want to say: The button is pressed the first time and the library interprets this as a long press as it just sees the button was pressed from the start and then released.
Source code:
#include <Arduino.h>
#include <Button2.h>
#include <math.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 26 ///< Pin for status led
#define LED_COUNT 7 ///< Numbers of pins on the status led
#define BRIGHTNESS 10 ///< Brightness of pixels (prevents the LED from being a laserbeam)
#define COLOR_RED ((255 << 16) + (0 << 8) + (0))
#define COLOR_ORANGE ((255 << 16) + (155 << 8) + (0))
#define COLOR_YELLOW ((255 << 16) + (255 << 8) + (0))
#define COLOR_GREEN ((0 << 16) + (255 << 8) + (0))
#define COLOR_CYAN ((0 << 16) + (255 << 8) + (255))
#define COLOR_BLUE ((0 << 16) + (0 << 8) + (255))
#define COLOR_PURPLE ((155 << 16) + (0 << 8) + (255))
#define COLOR_MAGENTA ((255 << 16) + (0 << 8) + (255))
#define COLOR_WHITE ((255 << 16) + (255 << 8) + (255))
#define COLOR_TUM_DARKBLUE ((0 << 16) + (82 << 8) + (147))
#define COLOR_TUM_BLUE ((0 << 16) + (101 << 8) + (189))
#define COLOR_TUM_ORANGE ((227 << 16) + (114 << 8) + (34))
#define COLOR_TUM_GREEN ((162 << 16) + (173 << 8) + (0))
#define COLOR_OFF 0
#define RECORD_BUTTON 5 ///< Pin for record button
#define PLAY_BUTTON 6 ///< Pin for play button
#define DEBOUNCE_TIME_MS 50 ///< Debounce time in ms
Button2 playButton;
Button2 recordButton;
Adafruit_NeoPixel statusLED(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void statusLEDShineFullColorCode(int color) {
statusLED.fill(color);
statusLED.setBrightness(BRIGHTNESS);
statusLED.show();
}
void pressedHandler(Button2 &button){
Serial.println("Button was pressed");
statusLEDShineFullColorCode(COLOR_BLUE);
}
void longPressedHandler(Button2 &button){
Serial.println("Button was pressed long");
statusLEDShineFullColorCode(COLOR_GREEN);
}
void doubleClickedHandler(Button2 &button){
Serial.println("Button clicked twice!");
statusLEDShineFullColorCode(COLOR_RED);
}
void setupButtons(){
playButton.begin(PLAY_BUTTON);
recordButton.begin(RECORD_BUTTON);
playButton.setDebounceTime(50);
recordButton.setDebounceTime(50);
playButton.setDoubleClickTime(500);
recordButton.setDoubleClickTime(500);
playButton.setLongClickTime(1000);
recordButton.setLongClickTime(1000);
playButton.setClickHandler(pressedHandler);
recordButton.setClickHandler(pressedHandler);
playButton.setDoubleClickHandler(doubleClickedHandler);
recordButton.setDoubleClickHandler(doubleClickedHandler);
playButton.setLongClickHandler(longPressedHandler);
recordButton.setLongClickHandler(longPressedHandler);
}
void setup() {
statusLED.begin();
setupButtons();
Serial.begin(115200);
}
void loop() {
playButton.loop();
recordButton.loop();
statusLED.show();
if(millis()%1000 == 0){
Serial.println("Record button isPressed(): " + String(recordButton.isPressed()) + ", Play button isPressed(): " + String(playButton.isPressed()));
Serial.println("Record button digitalRead(): " + String(digitalRead(RECORD_BUTTON)) + ", Play button digitalRead(): " + String(digitalRead(PLAY_BUTTON)));
}
}
Serial Log (comments from me added after the fact indexed with #):
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Button was pressed long # here the record button is pressed the first time, but Button2 thinks this was pressed until now
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed isPressed() = 0, digitalRead() = 1 (WTF?)
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1 # record button still pressed
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 0, Play button isPressed(): 1
Record button digitalRead(): 1, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Button was pressed long # here I am pressing the other button
Record button isPressed(): 1, Play button isPressed(): 0
Record button digitalRead(): 0, Play button digitalRead(): 1
Record button isPressed(): 1, Play button isPressed(): 0
Record button digitalRead(): 0, Play button digitalRead(): 1
Record button isPressed(): 1, Play button isPressed(): 0
Record button digitalRead(): 0, Play button digitalRead(): 1
Record button isPressed(): 1, Play button isPressed(): 0
Record button digitalRead(): 0, Play button digitalRead(): 1
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
Record button isPressed(): 1, Play button isPressed(): 1
Record button digitalRead(): 0, Play button digitalRead(): 0
The output I would expect is:
Record button isPressed(): 0, Play button isPressed(): 0
Record button digitalRead(): 0, Play button digitalRead(): 0
for idle and:
Record button isPressed(): 1, Play button isPressed(): 0
Record button digitalRead(): 1, Play button digitalRead(): 0
if the record button is pressed.
</details>
# 答案1
**得分**: 0
感谢Juraj,我发现了“错误”,原因是将activeLow设置为false。我不太明白为什么要这样定义,但现在它可以正常工作了。
更新后的工作代码如下:
```cpp
#include <Arduino.h>
#include <Button2.h>
#include <math.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 26 /// Pin for status led
#define LED_COUNT 7 /// Numbers of pins on the status led
#define BRIGHTNESS 10 /// Brightness of pixels (prevents the LED from being a laserbeam)
#define COLOR_RED ((255 << 16) + (0 << 8) + (0))
#define COLOR_ORANGE ((255 << 16) + (155 << 8) + (0))
#define COLOR_YELLOW ((255 << 16) + (255 << 8) + (0))
#define COLOR_GREEN ((0 << 16) + (255 << 8) + (0))
#define COLOR_CYAN ((0 << 16) + (255 << 8) + (255))
#define COLOR_BLUE ((0 << 16) + (0 << 8) + (255))
#define COLOR_PURPLE ((155 << 16) + (0 << 8) + (255))
#define COLOR_MAGENTA ((255 << 16) + (0 << 8) + (255))
#define COLOR_WHITE ((255 << 16) + (255 << 8) + (255))
#define COLOR_TUM_DARKBLUE ((0 << 16) + (82 << 8) + (147))
#define COLOR_TUM_BLUE ((0 << 16) + (101 << 8) + (189))
#define COLOR_TUM_ORANGE ((227 << 16) + (114 << 8) + (34))
#define COLOR_TUM_GREEN ((162 << 16) + (173 << 8) + (0))
#define COLOR_OFF 0
#define RECORD_BUTTON 5 /// Pin for record button
#define PLAY_BUTTON 6 /// Pin for play button
#define DEBOUNCE_TIME_MS 50 /// Debounce time in ms
Button2 playButton;
Button2 recordButton;
Adafruit_NeoPixel statusLED(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void statusLEDShineFullColorCode(int color) {
statusLED.fill(color);
statusLED.setBrightness(BRIGHTNESS);
statusLED.show();
}
void pressedHandler(Button2 &button){
Serial.println("Button was pressed");
statusLEDShineFullColorCode(COLOR_BLUE);
}
void longPressedHandler(Button2 &button){
Serial.println("Button was pressed long");
statusLEDShineFullColorCode(COLOR_GREEN);
}
void doubleClickedHandler(Button2 &button){
Serial.println("Button clicked twice!");
statusLEDShineFullColorCode(COLOR_RED);
}
void setupButtons(){
playButton.begin(PLAY_BUTTON, INPUT_PULLDOWN, false); // changed this
recordButton.begin(RECORD_BUTTON, INPUT_PULLDOWN, false); // changed this
playButton.setDebounceTime(50);
recordButton.setDebounceTime(50);
playButton.setDoubleClickTime(500);
recordButton.setDoubleClickTime(500);
playButton.setLongClickTime(1000);
recordButton.setLongClickTime(1000);
playButton.setClickHandler(pressedHandler);
recordButton.setClickHandler(pressedHandler);
playButton.setDoubleClickHandler(doubleClickedHandler);
recordButton.setDoubleClickHandler(doubleClickedHandler);
playButton.setLongClickHandler(longPressedHandler);
recordButton.setLongClickHandler(longPressedHandler);
}
void setup() {
statusLED.begin();
setupButtons();
Serial.begin(115200);
}
void loop() {
playButton.loop();
recordButton.loop();
statusLED.show();
if(millis()%1000 == 0){
Serial.println("Record button isPressed(): " + String(recordButton.isPressed()) + ", Play button isPressed(): " + String(playButton.isPressed()));
Serial.println("Record button digitalRead(): " + String(digitalRead(RECORD_BUTTON)) + ", Play button digitalRead(): " + String(digitalRead(PLAY_BUTTON)));
}
}
英文:
Thanks to Juraj, I found the "error" it was to set activeLow to false. I do not really get why it is defined that way but whatever it works now.
The updated working code is:
#include <Arduino.h>
#include <Button2.h>
#include <math.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 26 ///< Pin for status led
#define LED_COUNT 7 ///< Numbers of pins on the status led
#define BRIGHTNESS 10 ///< Brightness of pixels (prevents the LED from being a laserbeam)
#define COLOR_RED ((255 << 16) + (0 << 8) + (0))
#define COLOR_ORANGE ((255 << 16) + (155 << 8) + (0))
#define COLOR_YELLOW ((255 << 16) + (255 << 8) + (0))
#define COLOR_GREEN ((0 << 16) + (255 << 8) + (0))
#define COLOR_CYAN ((0 << 16) + (255 << 8) + (255))
#define COLOR_BLUE ((0 << 16) + (0 << 8) + (255))
#define COLOR_PURPLE ((155 << 16) + (0 << 8) + (255))
#define COLOR_MAGENTA ((255 << 16) + (0 << 8) + (255))
#define COLOR_WHITE ((255 << 16) + (255 << 8) + (255))
#define COLOR_TUM_DARKBLUE ((0 << 16) + (82 << 8) + (147))
#define COLOR_TUM_BLUE ((0 << 16) + (101 << 8) + (189))
#define COLOR_TUM_ORANGE ((227 << 16) + (114 << 8) + (34))
#define COLOR_TUM_GREEN ((162 << 16) + (173 << 8) + (0))
#define COLOR_OFF 0
#define RECORD_BUTTON 5 ///< Pin for record button
#define PLAY_BUTTON 6 ///< Pin for play button
#define DEBOUNCE_TIME_MS 50 ///< Debounce time in ms
Button2 playButton;
Button2 recordButton;
Adafruit_NeoPixel statusLED(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
void statusLEDShineFullColorCode(int color) {
statusLED.fill(color);
statusLED.setBrightness(BRIGHTNESS);
statusLED.show();
}
void pressedHandler(Button2 &button){
Serial.println("Button was pressed");
statusLEDShineFullColorCode(COLOR_BLUE);
}
void longPressedHandler(Button2 &button){
Serial.println("Button was pressed long");
statusLEDShineFullColorCode(COLOR_GREEN);
}
void doubleClickedHandler(Button2 &button){
Serial.println("Button clicked twice!");
statusLEDShineFullColorCode(COLOR_RED);
}
void setupButtons(){
playButton.begin(PLAY_BUTTON, INPUT_PULLDOWN, false); // changed this
recordButton.begin(RECORD_BUTTON, INPUT_PULLDOWN, false); // changed this
playButton.setDebounceTime(50);
recordButton.setDebounceTime(50);
playButton.setDoubleClickTime(500);
recordButton.setDoubleClickTime(500);
playButton.setLongClickTime(1000);
recordButton.setLongClickTime(1000);
playButton.setClickHandler(pressedHandler);
recordButton.setClickHandler(pressedHandler);
playButton.setDoubleClickHandler(doubleClickedHandler);
recordButton.setDoubleClickHandler(doubleClickedHandler);
playButton.setLongClickHandler(longPressedHandler);
recordButton.setLongClickHandler(longPressedHandler);
}
void setup() {
statusLED.begin();
setupButtons();
Serial.begin(115200);
}
void loop() {
playButton.loop();
recordButton.loop();
statusLED.show();
if(millis()%1000 == 0){
Serial.println("Record button isPressed(): " + String(recordButton.isPressed()) + ", Play button isPressed(): " + String(playButton.isPressed()));
Serial.println("Record button digitalRead(): " + String(digitalRead(RECORD_BUTTON)) + ", Play button digitalRead(): " + String(digitalRead(PLAY_BUTTON)));
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论