【问题标题】:How to use serial.available() inside a void loop() during delay in an Arduino?如何在 Arduino 延迟期间在 void loop() 中使用 serial.available()?
【发布时间】:2018-06-06 01:22:17
【问题描述】:

每当我通过串行监视器发送值时,但当 void loop() 执行串行延迟函数时,我想执行一个函数。 available() 函数不起作用,所以如果我在延迟函数期间在串行监视器中发送任何值,serial.available 将不起作用

#define red 9
#define yellow 8
void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
    pinMode(red, OUTPUT);
    pinMode(yellow, OUTPUT);
}
void LightON() {
    digitalWrite(red, HIGH);
    delay(1000);
    digitalWrite(yellow, HIGH);
    delay(1000);
    digitalWrite(red, LOW);
    delay(1000);
}
void LightOff() {
    digitalWrite(red, LOW);
    digitalWrite(yellow, LOW);
}
void loop() {
    // put your main code here, to run repeatedly:
    LightON();
    if (Serial.available())
    {
        LightOff();
    }
}

如果我在函数 Lighton() 的延迟期间在串行监视器中输入一个值以便执行 Lightoff() 时,我该如何解决这个问题?

【问题讨论】:

  • 即使可以,拨打LightOff 也不会停止LightON。从根本上说,您使用的架构无法支持您想要的。您需要LightON 在暂停期间监控Serial,而不是使用长delays。或许用millis来监控时间的流逝。
  • 好的,如果我在 LightON 中监视串行,如果 LightON 延迟,那么 serial.monitor() 将无法延迟工作

标签: c++ arduino serial-port delay arduino-uno


【解决方案1】:

LightON 总是需要 3 秒。为了避免这种情况,事情变得更加复杂。您可以使用状态机在任何给定时间跟踪闪烁序列的位置。这还具有允许您的代码执行其他操作而不是忙于循环或等待delay() 的好处。

// This class represents the led state machine
class blinker {
    public:
    // Possible states
    enum {START, RED_ON, YELLOW_ON, RED_OFF, INACTIVE};

    // Constructor
    blinker(byte red_pin, byte yellow_pin, long timeout=1000) :
            red(red_pin), yellow(yellow_pin), timeout(timeout), state(INACTIVE) {
        pinMode(red, OUTPUT);
        pinMode(yellow, OUTPUT);
    }

    // Start the loop from the beginning
    void start() {
        stop();
        state = START;
    }
    // Stop the loop
    void stop() {
        digitalWrite(red, LOW);
        digitalWrite(yellow, LOW);
        state = INACTIVE;
    }

    // Update
    void loop() {
        // Only change if started and time is up
        if (state != INACTIVE && timer_expired()) {
            switch (state) {
                // Starting over?
                case START:
                    state = RED_ON;
                    digitalWrite(red,HIGH);
                    break;
                // Red is on, turn yellow on
                case RED_ON:
                    state = YELLOW_ON;
                    digitalWrite(yellow,HIGH);
                    break;
                // Yellow is on, turn red off
                case YELLOW_ON:
                    state = RED_OFF;
                    digitalWrite(red,LOW);
                    break;
                // Red is off, start over
                case RED_OFF:
                    state = START;
            }
        }
    }    

    protected:
    byte red, yellow;
    long timeout;

    // Returns true when time is up. 
    // Also resets the timer    
    bool timer_expired() {
        if ((millis() - last_time) >= timeout) {
            last_time = millis();
            return true;
        }
        return false;
    }
};

// Create the state machine
blinker blinky(9, 8);
void setup() {
    Serial.begin(9600);
    // Start loop
    blinky.start();
}

void loop() {
    // Call this everytime
    blinky.loop();

    // Stop?
    if (Serial.available()) {  
        blinky.stop();
    }

    // Can do other stuff here
}

我只是把它放在一起。你可以改进它。

【讨论】:

    【解决方案2】:

    像这样使用自定义延迟函数:

    bool LedOn;
    
    void MyDelay(int ms) {
       for(int i=0;i<ms;i++){
          if (Serial.available())
          {
            LightOff();
            LedOn = false;
            break;
          }
          delay(1);
       }
    }
    
    void LightON() {
        digitalWrite(red, HIGH);
        MyDelay(1000);
        if(! LedOn) return;
        digitalWrite(yellow, HIGH);
        MyDelay(1000);
        if(! LedOn) return;
        digitalWrite(red, LOW);
        MyDelay(1000);
    }
    void loop() {
      LedOn = true;
      LightON();
      if (Serial.available())
      {
        LightOff();
        LedOn = false;
      }
    }
    

    【讨论】:

    • 当我在串行监视器中输入一个值时,它会不断重复相同的功能
    • 编辑break
    • 不,我用break检查过;但同样的事情发生
    • 它不断重复 Lightoff()
    • 让我们尝试使用一个全局变量 LedOn,见已编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2016-07-08
    • 2021-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多