首页 > 解决方案 > 如果 x 秒内没有串行数据,则关闭模拟引脚

问题描述

我的计算机上有一个程序,可以将串行数据发送到我的 Arduino,该程序指示 Arduino 上的模拟写入。如何检查 x 秒内是否没有发送新的串行数据以及是否没有执行任何操作。例如:

if (newDataInLastSeconds(10) {
    // Do Something...
}```

标签: arduinoserial-portarduino-c++

解决方案


对于这个问题,您可以使用状态机来跟踪串行链路的状态,并设置在状态转换时触发的操作。如果您还想loop()根据链接的状态设置每次发生的操作,那么设置起来会更容易(未显示)。

您可能已经在检查Serial.available()串行线路上是否收到任何字节,对吗?您需要做的就是创建一个非常简单的两态状态机:

  1. 确定你想要的超时时间
  2. 跟踪数据超时处于什么状态(bool serial_fresh——您最近是否收到过数据)
  3. 记录您上次收到任何数据的时间
  4. 如果串行线是新的,将当前时间与之前的时间进行比较。如果大于您的超时时间,则将 fresh 设置为 false(这是一个状态转换)并执行您想要执行的操作
  5. 如果串行线不是新鲜的,而您刚刚收到数据,则将新鲜设置为 true(另一个状态转换)并在该转换上执行您想要执行的操作
// start in the unfresh state, we won't transition to fresh until
// we receive the first byte - if this doesn't match what you want change to fit
bool g_serial_fresh = false; 
const unsigned long SERIAL_TIMEOUT_MS = 5000; // or however many milliseconds
unsigned long g_last_serial_rx_ms = 0;

void transitionToFresh() {
    g_serial_fresh = true;
    /* do what you want to do when the link comes back up - turn on ADC */
}

void transitionToStale() {
    g_serial_fresh = false;
    /* do what you want to do when the link times out - shutdown ADC */
}

bool serialTimedOut() {
    return (millis() - g_last_serial_rx_ms) > SERIAL_TIMEOUT_MS;
}
void doStateMachine() {
    bool received_data_this_loop = false;

    if (Serial.available() > 0) { // assumes you read all available bytes later
        g_last_serial_rx_ms = millis();
        received_data_this_loop = true;
    }

    if (!g_serial_fresh && received_data_this_loop) {
        transitionToFresh();
    }

    else if (g_serial_fresh && serialTimedOut()) {
        transitionToStale();
    }
}
void loop() {
    doStateMachine();

    /* do regular programmy things here */
}

推荐阅读