如何使用C中的wiringpi确定按钮按下持续时间
How to determine button press duration with wiringpi in C
对于 aspberry pi 项目,我有连接到 GPIO 的按钮,我想根据按下按钮的时间长短采取不同的操作。以下 python 代码(提取)按预期工作:
on_button2(channel):
t1 = time.time()
# Wait for button release
while GPIO.input(channel) == 0:
pass
duration = time.time() - t1
print "duration: %f" % (duration)
if duration > 0.75:
mpd_client.previous()
else:
mpd_client.next()
GPIO.add_event_detect(BUTTON2_PIN, GPIO.FALLING, callback=on_button2, bouncetime=700);
我想把它转换成C程序(别问为什么,我真的不喜欢python而且我对C更熟悉,所以我想做它在 C)
试图用 wiringPi 将其转换为 C,我想出了这个,但它没有按预期工作:
unsigned long btn2_t0;
static void on_button_2_pressed() {
unsigned long duration, t1;
int level;
level = digitalRead(BUTTON_2_PIN);
// Debounce button
t1 = millis();
if (t1 - btn2_t0 < 700) {
return;
}
btn2_t0 = t1;
// Wait for button being released
while (digitalRead(BUTTON_2_PIN) == LOW) {
delay(100);
}
duration = millis() - t1;
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
int main() {
// Setup WiringPi Lib
wiringPiSetupGpio();
pinMode(BUTTON_2_PIN, INPUT);
// Register callbacks on button press
wiringPiISR(BUTTON_2_PIN, INT_EDGE_FALLING, on_button_2_pressed);
for (;;) {
delay(500);
}
return 0;
}
似乎应该等待按钮释放的循环没有被执行,或者 while 条件始终为真,因此持续时间始终为零。
digitalRead(BUTTON_2_PIN)
函数是否等同于 python 代码中的 GPIO.input(channel)
?
如果有人能指出正确的方向,告诉我如何检测按钮按下(软件去抖动)并测量 C 中按钮按下的持续时间。
非常感谢。
编辑:工作解决方案
在 Francesco Boi 的帮助下玩了很多之后,我找到了一个可行的解决方案,虽然我不太明白为什么与 python 代码相比,HIGH / LOW 的比较逻辑被交换了(我认为按下按钮会导致引脚下降到低电平,释放它会使其上升到高电平...)
static void on_button_2_pressed() {
unsigned long duration;
static unsigned long button_pressed_timestamp;
int level = digitalRead(BUTTON_2_PIN);
if (level == HIGH) { // Why HIGH ?!?
button_pressed_timestamp = millis();
}
else {
duration = millis() - button_pressed_timestamp;
button_pressed_timestamp = millis();
if (duration < 100) {
// debounce...
return;
}
else if (duration < 700) {
syslog(LOG_NOTICE, ">> NEXT\n");
}
else if (duration < 3000) {
syslog(LOG_NOTICE, "<< PREV\n");
}
else {
syslog(LOG_NOTICE, "!! REBOOT\n");
}
}
}
int main() {
...
wiringPiISR(BUTTON_2_PIN, INT_EDGE_BOTH, on_button_2_pressed);
...
}
首先,您将引脚的值读入 level
,然后在 while 循环中重新读取它:这是为什么呢?你不能做这样的事情吗:
// Wait for button being released
while (level == LOW) {
delay(100);
}
?
即使时间小于 700 毫秒,您也不想重新分配 btn2_t0 = t1;
吗?喜欢:
t1 = millis();
if (t1 - btn2_t0 < 700) {
btn2_t0 = t1;
return;
}
行为取决于您构建电子电路的方式:按下按钮会使引脚变高还是变低?通过连接 LED 和电阻器或使用电压表,确保行为符合您的预期。
然而,由于你的 Python 代码有效,我假设电子是正确的,你的算法也是正确的。
当然要确保您按下按钮的时间足够长。在您的代码中添加一些打印以了解它正在执行哪些分支,因为当涉及电子时,仅通过代码很难理解。
在等待您的消息时,我认为最好执行以下操作:将回调定义为:INT_EDGE_BOTH
以便在按下底部和释放按钮时调用它。您可以使用静态变量来保持经过的时间。
void yourCallback()
{
unsigned long ela, t;
int level = digitalRead(BUTTON_2_PIN);
static unsigned long button_pressed_timestamp;
//if button pressed:
if(level==LOW)
{
//start counting
button_pressed_timestamp = millis();
}
else //button released
{
duration = millis()-button_pressed_timestamp;
button_pressed_timestamp = millis(); //just to be sure....
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
}
对于 aspberry pi 项目,我有连接到 GPIO 的按钮,我想根据按下按钮的时间长短采取不同的操作。以下 python 代码(提取)按预期工作:
on_button2(channel):
t1 = time.time()
# Wait for button release
while GPIO.input(channel) == 0:
pass
duration = time.time() - t1
print "duration: %f" % (duration)
if duration > 0.75:
mpd_client.previous()
else:
mpd_client.next()
GPIO.add_event_detect(BUTTON2_PIN, GPIO.FALLING, callback=on_button2, bouncetime=700);
我想把它转换成C程序(别问为什么,我真的不喜欢python而且我对C更熟悉,所以我想做它在 C)
试图用 wiringPi 将其转换为 C,我想出了这个,但它没有按预期工作:
unsigned long btn2_t0;
static void on_button_2_pressed() {
unsigned long duration, t1;
int level;
level = digitalRead(BUTTON_2_PIN);
// Debounce button
t1 = millis();
if (t1 - btn2_t0 < 700) {
return;
}
btn2_t0 = t1;
// Wait for button being released
while (digitalRead(BUTTON_2_PIN) == LOW) {
delay(100);
}
duration = millis() - t1;
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
int main() {
// Setup WiringPi Lib
wiringPiSetupGpio();
pinMode(BUTTON_2_PIN, INPUT);
// Register callbacks on button press
wiringPiISR(BUTTON_2_PIN, INT_EDGE_FALLING, on_button_2_pressed);
for (;;) {
delay(500);
}
return 0;
}
似乎应该等待按钮释放的循环没有被执行,或者 while 条件始终为真,因此持续时间始终为零。
digitalRead(BUTTON_2_PIN)
函数是否等同于 python 代码中的 GPIO.input(channel)
?
如果有人能指出正确的方向,告诉我如何检测按钮按下(软件去抖动)并测量 C 中按钮按下的持续时间。
非常感谢。
编辑:工作解决方案
在 Francesco Boi 的帮助下玩了很多之后,我找到了一个可行的解决方案,虽然我不太明白为什么与 python 代码相比,HIGH / LOW 的比较逻辑被交换了(我认为按下按钮会导致引脚下降到低电平,释放它会使其上升到高电平...)
static void on_button_2_pressed() {
unsigned long duration;
static unsigned long button_pressed_timestamp;
int level = digitalRead(BUTTON_2_PIN);
if (level == HIGH) { // Why HIGH ?!?
button_pressed_timestamp = millis();
}
else {
duration = millis() - button_pressed_timestamp;
button_pressed_timestamp = millis();
if (duration < 100) {
// debounce...
return;
}
else if (duration < 700) {
syslog(LOG_NOTICE, ">> NEXT\n");
}
else if (duration < 3000) {
syslog(LOG_NOTICE, "<< PREV\n");
}
else {
syslog(LOG_NOTICE, "!! REBOOT\n");
}
}
}
int main() {
...
wiringPiISR(BUTTON_2_PIN, INT_EDGE_BOTH, on_button_2_pressed);
...
}
首先,您将引脚的值读入 level
,然后在 while 循环中重新读取它:这是为什么呢?你不能做这样的事情吗:
// Wait for button being released
while (level == LOW) {
delay(100);
}
?
即使时间小于 700 毫秒,您也不想重新分配 btn2_t0 = t1;
吗?喜欢:
t1 = millis();
if (t1 - btn2_t0 < 700) {
btn2_t0 = t1;
return;
}
行为取决于您构建电子电路的方式:按下按钮会使引脚变高还是变低?通过连接 LED 和电阻器或使用电压表,确保行为符合您的预期。
然而,由于你的 Python 代码有效,我假设电子是正确的,你的算法也是正确的。
当然要确保您按下按钮的时间足够长。在您的代码中添加一些打印以了解它正在执行哪些分支,因为当涉及电子时,仅通过代码很难理解。
在等待您的消息时,我认为最好执行以下操作:将回调定义为:INT_EDGE_BOTH
以便在按下底部和释放按钮时调用它。您可以使用静态变量来保持经过的时间。
void yourCallback()
{
unsigned long ela, t;
int level = digitalRead(BUTTON_2_PIN);
static unsigned long button_pressed_timestamp;
//if button pressed:
if(level==LOW)
{
//start counting
button_pressed_timestamp = millis();
}
else //button released
{
duration = millis()-button_pressed_timestamp;
button_pressed_timestamp = millis(); //just to be sure....
if (duration > 5000) {
printf("Self destruction sequence initiated!\n");
}
else if (duration > 700) {
player_previous();
}
else {
player_next();
}
}
}