【发布时间】:2020-02-15 00:12:29
【问题描述】:
我正在努力在我的 Arduino 程序中建立一个状态机,我想我有一个足够简单的程序来学习有限状态机。目前我遇到的问题是每次程序更改状态时,它都会用它的状态或正在记录的数据淹没串行监视器。我创建了一些在非常有限的级别上工作的东西,但我觉得我无法扩展它,因为这段代码只有在我有 3 个状态时才有效。但是如果我想要 4 或 5 个状态呢?
我希望每次在程序继续运行时状态发生变化时,在串行监视器中只提示一次。 例如,
- 如果程序处于空闲状态(状态 0),则串行监视器中不显示任何内容。
- 如果程序是只读的,则提示串行监视器(状态 1)一次,而不是每次执行读取。
- 如果程序正在读取和记录,因为 SPST 开关状态改变,提示串行监视器(状态 2)一次,而不是每次执行读取和记录。
我还想了解如何更好地解决这个问题,因为我觉得这似乎只适用于 3 状态示例。如果我添加更多开关或更多状态会怎样?
快速编程功能:
- 等待 100 毫秒。
- LED1 状态为高
- LED2 状态低
- 如果 SPST 开关为高电平,则读取模拟输入引脚并返回空闲状态。(此时将有一个显示器挂起,无论是否记录数据都会显示值)。
- LED1 状态低
- LED2 状态低
- 如果 SPST 开关为 LOW,则将读取的数据记录到文件中。
- 如果这是第一次,请创建一个具有 unix 名称的文件。
- 如果这不是第一次(文件存在),请将其打开并附加到它。
- 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++