【问题标题】:User input stuck in loop用户输入卡在循环中
【发布时间】:2019-11-22 20:50:29
【问题描述】:

我在 Arduino 上编写了这段代码,目的是让用户在串行监视器中输入延迟时间,然后 LED 应该随着延迟时间闪烁。例如,如果我输入 1000,则 LED 应打开 1 秒,然后关闭 1 秒,然后重复。

我的问题是,当代码运行完一次后,它会等待新的用户输入,而不是继续闪烁。我想我必须将Serial.parseInt 排除在循环之外,但我不确定每次我试图将它放在其他地方时,LED 都会不断亮起。

代码如下:

int ledPin = 13;


void setup() {
  // put your setup code here, to run once:
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);

  Serial.print(" Enter delay time: ");
  while (!Serial.available());

}

void loop() {
  // put your main code here, to run repeatedly
  int delayTime = Serial.parseInt();
  digitalWrite(ledPin, HIGH);
  delay(delayTime);
  digitalWrite(ledPin, LOW);
  delay(delayTime);

}

【问题讨论】:

    标签: input arduino


    【解决方案1】:

    Serial.parseInt 是一个阻塞函数。这意味着它会等待有效的串行输入,直到超时。因此,loop 中的任何其他操作也必须等待。不过,在setup 中读取用户输入只能工作一次,因此它不会再次要求用户输入。

    为避免这种情况,您必须检查串行缓冲区,然后单独读取每个字节,同时在主循环中让 LED 闪烁。

    现在要避免的另一件事是使用delay 函数,因为它还在给定参数时间挂起整个主循环(包括串行读数)。您仍然可以使用时间戳间隔使 LED 闪烁。

    对于非阻塞串行读取的一个很好的例子,我们可以使用this sample from the Arduino docs。此外,对于另一个不使用delay 的 LED 闪烁草图的好例子,我们也可以使用BlinkWithoutDelay sample from the Arduino docs

    String inString = "";
    unsigned long previousMillis = 0;
    int delayTime = 0;
    int ledState = LOW;
    int ledPin = 13;
    
    void nonBlockingSerialReadDelayTime() {
      while (Serial.available() > 0) {
        int inChar = Serial.read();
        if (isDigit(inChar)) {
          // convert the incoming byte to a char and add it to the string
          inString += (char)inChar;
        }
        // if you get a newline (user pressed ENTER on the serial console)
        if (inChar == '\n') {
          // set our new delay time
          delayTime = inString.toInt();
    
          // clear the string for new input
          inString = "";
    
          // ask user again
          Serial.print(" Enter delay time: ");
        }
      }
    }
    
    void blinkLED() {
      unsigned long currentMillis = millis();
    
      if (currentMillis - previousMillis >= delayTime) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
    
        // if the LED is off turn it on and vice-versa
        if (ledState == LOW) {
          ledState = HIGH;
        } else {
          ledState = LOW;
        }
    
        // set the LED with the ledState of the variable
        digitalWrite(ledPin, ledState);
      }
    }
    
    void setup() {
      pinMode(ledPin, OUTPUT);
      Serial.begin(9600);
      while (!Serial.available());
      Serial.print(" Enter delay time: ");
    }
    
    void loop() {
      nonBlockingSerialReadDelayTime();
      blinkLED();
    }
    

    【讨论】:

      【解决方案2】:

      在你输入loop之前,只需阅读你setup中的延迟时间

      int ledPin = 13;
      int delayTime = 0;
      
      void setup() {
        // put your setup code here, to run once:
        pinMode(ledPin, OUTPUT);
        Serial.begin(9600);
      
        Serial.print(" Enter delay time: ");
        while (!Serial.available());
        delayTime = Serial.parseInt();
      
      }
      
      void loop() {
        // put your main code here, to run repeatedly
      
        digitalWrite(ledPin, HIGH);
        delay(delayTime);
        digitalWrite(ledPin, LOW);
        delay(delayTime);
      
      }
      

      【讨论】:

        【解决方案3】:

        当然 Serial.parseInt() 是阻塞的,但你可以将它与 Serial.available() 结合使用

        const int ledPin = 13;
        int delayTime = 1000;
        
        void setup() {
          pinMode(ledPin, OUTPUT);
          Serial.begin(9600);
          Serial.print(" Enter delay time: ");
        }
        
        void loop() {
          digitalWrite(ledPin, HIGH);
          delay(delayTime);
          digitalWrite(ledPin, LOW);
          delay(delayTime);
        
          if (Serial.available()) { 
             int temp = Serial.parseInt();
             if (temp  > 0) delayTime = temp;
             Serial.print(" Enter delay time: ");
          }  
        }
        

        当然,这种方法不允许立即进入一个非常缓慢的眨眼周期,但这是一个不同的问题。

        【讨论】:

          猜你喜欢
          • 2015-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-16
          • 2020-02-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多