首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Arduino Protothread似乎由两个按钮共享

Arduino Protothread似乎由两个按钮共享
EN

Stack Overflow用户
提问于 2015-01-27 17:07:03
回答 1查看 315关注 0票数 0

我遇到了一个关于Arduino中的Protothreading库的问题。我已经创建了一个Button类,它表示一个硬件按钮。现在的想法是,您可以向它附加一个ButtonListener,它监听按钮。如果按下按钮,则调用clicked()函数。

代码语言:javascript
复制
#include <Arduino.h>
#include <pt.h>

class ButtonListener {
    public:
        virtual void clicked() = 0;
        virtual void longClicked() = 0;
        virtual void tapped(int) = 0;
};

class Button {

    static const int RECOIL_TIME = 200;
    static const int LONG_CLICK_LENGTH = 1000;

    private:
        int _pin;
        ButtonListener *_listener;
        struct pt _thread;
        unsigned long _timestamp = 0;

        int listenerHook(struct pt *pt) {
            PT_BEGIN(pt);
            this->_timestamp = 0;
            while (true) {
                PT_WAIT_UNTIL(pt, millis() - _timestamp > 1);
                _timestamp = millis();
                if (&this->_listener != NULL) {
                    this->listenForClick();
                }
            }
            PT_END(pt);
        }

        void listenForClick() {
            boolean longClicked = true;
            int state = digitalRead(this->_pin);
            if (state == HIGH) {
                unsigned long timestamp = millis();
                while (true) {
                    longClicked = millis() - timestamp > LONG_CLICK_LENGTH;
                    state = digitalRead(this->_pin);
                    if (state == LOW) {
                        break;
                    }
                }
                if (&this->_listener != NULL) {
                    if (longClicked) {
                        (*this->_listener).longClicked();
                    }
                    else {
                        (*this->_listener).clicked();
                    }
                }
            }
        }

    public:
        Button(int pin) {
            this->_pin = pin;
        }

        void init() {
            pinMode(this->_pin, OUTPUT);
            PT_INIT(&this->_thread);
        }

        void setListener(ButtonListener *listener) {
            this->_listener = listener;
        }

        void listen() {
            this->listenerHook(&this->_thread);
        }
};

现在,我已经创建了两个ButtonListener实现

代码语言:javascript
复制
class Button12Listener : public ButtonListener {
    public:
        void clicked() {
            Serial.println("Button 12 clicked!");
        }
}

另一个实现是一个Button13Listener,并打印"Button 13 clicked!“

然后让我们运行代码:

代码语言:javascript
复制
// Instantiate the buttons
Button button12(12);
Button button13(13);

void setup() {
    Serial.begin(9600);

    button12.init();
    button13.init();

    // Add listeners to the buttons
    button12.setListener(new Button12Listener());
    button13.setListener(new Button13Listener());
}

void loop() {
    while (true) {
        // Listen for button clicks
        button12.listen();
        button13.listen();
    }
    Serial.println("Loop ended.");
    delay(60000);
}

我期待着"Button 12 clicked!“当我点击引脚12上的按钮时,"Button 13 click!“当我点击引脚13上的按钮时。

但是当我尝试点击任何一个按钮时,它会随机打印出"Button 12 clicked!“或者“点击了13号按钮!”不管我按下什么按钮。

它看起来像是在按钮或其他东西之间共享协议线程。

如果我检查按钮的调用顺序,如下所示:

代码语言:javascript
复制
button12.listen();
Serial.println("listen12");
button13.listen();
Serial.println("listen13");

然后输出以下内容:

代码语言:javascript
复制
12
13
12
13
12
12

Tát看起来还不错

那么问题出在哪里呢?我错过了什么?

EN

回答 1

Stack Overflow用户

发布于 2015-02-21 16:11:29

通过在listenForClick中使用while(true)循环,您完全消除了协议线程的全部要点。我会这样做:

代码语言:javascript
复制
PT_BEGIN(thr); 
while(1){
  // ensure that the pin is low when you start
  PT_WAIT_UNTIL(thr, digitalRead(pin) == LOW); 
  // wait until pin goes high
  PT_WAIT_UNTIL(thr, digitalRead(pin) == HIGH); 
  // insert delay here for minimum time the pin must be high
  this->timeout = millis() + 20; // 20 ms
  // wait until the delay has expired
  PT_WAIT_UNTIL(thr, this->timeout - millis() > 0); 
  // wait until the pin goes low again
  PT_WAIT_UNTIL(thr, digitalRead(pin) == LOW); 
  // call the click callback
  this->clicked(); 
}
PT_END(thr); 

然后重复调用这个线程。

注意:当你连接了按钮时,你通常会在引脚上拉上拉,并将按钮连接在引脚和地之间-因此,当按钮按下时,引脚是低的,而当按钮不被按下时,引脚是高的。在arduino上肯定会出现这种情况。因此,您必须更改上面的代码,以等待负脉冲而不是正脉冲。:)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28166679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档