【问题标题】:How to Refine and Expand Arduino Finite State Machine如何完善和扩展 Arduino 有限状态机
【发布时间】:2020-02-15 00:12:29
【问题描述】:

我正在努力在我的 Arduino 程序中建立一个状态机,我想我有一个足够简单的程序来学习有限状态机。目前我遇到的问题是每次程序更改状态时,它都会用它的状态或正在记录的数据淹没串行监视器。我创建了一些在非常有限的级别上工作的东西,但我觉得我无法扩展它,因为这段代码只有在我有 3 个状态时才有效。但是如果我想要 4 或 5 个状态呢?

我希望每次在程序继续运行时状态发生变化时,在串行监视器中只提示一次。 例如,

  1. 如果程序处于空闲状态(状态 0),则串行监视器中不显示任何内容。
  2. 如果程序是只读的,则提示串行监视器(状态 1)一次,而不是每次执行读取。
  3. 如果程序正在读取和记录,因为 SPST 开关状态改变,提示串行监视器(状态 2)一次,而不是每次执行读取和记录。

我还想了解如何更好地解决这个问题,因为我觉得这似乎只适用于 3 状态示例。如果我添加更多开关或更多状态会怎样?

快速编程功能:

  1. 等待 100 毫秒。
    • LED1 状态为高
    • LED2 状态低
  2. 如果 SPST 开关为高电平,则读取模拟输入引脚并返回空闲状态。(此时将有一个显示器挂起,无论是否记录数据都会显示值)。
    • LED1 状态低
    • LED2 状态低
  3. 如果 SPST 开关为 LOW,则将读取的数据记录到文件中。
    1. 如果这是第一次,请创建一个具有 unix 名称的文件。
    2. 如果这不是第一次(文件存在),请将其打开并附加到它。
      • LED1 状态低
      • LED2 状态为高

我有这样的工作,但觉得它效率低下,我只是幸运地来到这里。我一直在努力执行有限状态机。

void setup() {
  Serial.begin(57600);   // Initiate serial
  delay(100);
  // Set pinmodes
  // Start and adjust RTC
  // Begin RTC
  delay(100);
  // Initialize SD Card
}

void loop() {
  // Read to see if the switch has changed states
  PIN_STATE = digitalRead(PIN_SWITCH);
  currentMillis = millis();

  // State 0 - Idle
  if (currentMillis - previousMillis < interval) {
    STATE = STATE;   // State flag set
    led_status(HIGH, LOW);
    digitalWrite(PIN_READ, LED_READ);
  }

  // State 1 - Read Only
  if ((PIN_STATE == HIGH) && (currentMillis - previousMillis >= interval)) {
    if (CHANGE_STATE) {
      STATE = 1;   // State flag set
      Serial.println("Changed state: Read");
    }
    previousMillis = currentMillis;  // Remember the time
    led_status(LOW, LOW);  // Update LEDs
    read();  // Read the pins
    CHANGE_STATE = false;
  }

  //State 2 - Read and Record
  else if ((PIN_STATE == LOW) && (currentMillis - previousMillis >= interval)) {
    if (!CHANGE_STATE) {
      Serial.println("Changed state: Read and Record");
    }
    previousMillis = currentMillis;  // Remember the time
    led_status(LOW, HIGH);  // Update LEDs
    read();   // Read the pins

    if (STATE < 2) {  // Was a file already created?
      // Create new file
    }
    filename = filename;
    open();   // Open the file
    write();  // Write to the file
    close();  // Close the file
    STATE = 2;   // State flag set
    CHANGE_STATE = true;
  }
}

void read() {
  //Read Values

  //Calculate Values
}

void open() {
  // Open the file
}


void write() {
  // Write to file
}

void close() {
  // Close the file
}

void led_status(int led_one, int led_two) {
  // Change the status of LEDS

更新,解决了。 从下面由 Arcadien 提供的文章中,我能够重新思考程序流程并将其重写为 switch case 状态机。

// Declare the states
enum state {
  _readState,
  _displayState,
  _createState,
  _openState,
  _writeState,
  _saveState,
  _errorState
};

void loop() {
  pinState = digitalRead(pinSwitch);
  // Green LED HIGH
  // Yellow LED LOW
  currentMillis = millis();

  if ((currentMillis - previousMillis) >= interval) {
    switch (_currentState) {

      case _readState:
        //Serial.println("Current State: _readState");
        // Green LED LOW
        _currentState = _readState;
        previousMillis = currentMillis;
        //Read Values

      case _displayState:
        //Serial.println("Current State: _displayState");
        _currentState = _displayState;
        previousMillis = currentMillis;
        if (pinState != LOW) {    // If not recording, then break
          filename = "";
          _currentState = _readState;
          break;
        };

      case _createState:
        //Serial.println("Current State: _createState");
        // Yellow LED HIGH
        _currentState = _createState;
        previousMillis = currentMillis;
        if (filename == NULL) {
          //Serial.print("Creating new file... ");
          DateTime now = rtc.now();
          filename = String(now.unixtime(), DEC);
          filename = filename + ".txt";
          //Serial.print(filename);
          //Serial.println(" created!");
          //Serial.print("Writing header to file... ");
          //dataFile = SD.open(filename, FILE_WRITE);
          dataFile = SD.open(filename, O_WRITE | O_CREAT);
          dataFile.println("Time(ms), TPS, AFR");
          //Serial.println("header written!");
          dataFile.close();
        };

      case _openState:
        //Serial.println("Current State: _openState");
        _currentState = _openState;
        dataFile = SD.open(filename, O_CREAT | O_APPEND | O_WRITE);     // Open filename.txt

      case _writeState:
        //Serial.println("Current State: _writeState");
        _currentState = _writeState;
        // if the file is available, write to it:
        if (dataFile) {
          // Create a single line string of data
          dataFile.println(_data);  // Write data
        }
        // if the file didn't open, throw errors
        else {
          Serial.print("error opening ");
          Serial.println(filename);
          _currentState = _errorState;
        }

      case _saveState:
        //Serial.println("Current State: _saveState");
        _currentState = _saveState;
        dataFile.flush();
        dataFile.close();
        _currentState = _readState;
        break;

      case _errorState:
        _currentState = _errorState;
        // Red LED HIGH
    }
  }
  // Return to the begining
}

【问题讨论】:

    标签: arduino arduino-c++


    【解决方案1】:

    您应该在这里查看其他答案,例如 this one。粗略地说,你必须将你的机器和它的状态分开。嵌入式代码通常需要紧凑高效,状态机可以使用转换表来实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      相关资源
      最近更新 更多