1

所以我有一个 Arduino 草图,它读取串行命令(一串字符),然后让草图根据它收到的命令做一些事情。截至目前,我有两个命令,

  • {open_valve}
  • {关闭阀门}

当我向 Arduino 发送命令 {open_valve} 时,阀门打开正常,但是当我向 Arduino 发送命令 {close_valve} 时阀门没有关闭。草图如下所示,

 // flow_A LED
 int led = 4;

 // relay_A
 const int RELAY_A = A0;

 // variables from sketch example
 String inputString = ""; // a string to hold incoming data
 boolean stringComplete = false; // whether the string is complete

 // variables from SO thread
 boolean LED_state = false;
 boolean vavle_open = false;

// flowmeter shit
unsigned long totalCount = 0;
unsigned long previousCount = 0;
int pin = 2;
unsigned long duration;

// storage variable for the timer
unsigned long previousMillis=0;
int interval=1000; //in milliseconds

// counters for each flowmeter
unsigned long countA = 0;

 void setup() {

   Serial.begin(115200); // open serial port, sets data rate to 115200bps
   Serial.println("Power on test");
   inputString.reserve(200);

   pinMode(RELAY_A, OUTPUT);

   // flowmeter shit
   pinMode(pin, INPUT);

}

void open_valve() {

  digitalWrite(RELAY_A, HIGH); // turn RELAY_A on

  // set the boolean value for "vavle_open" to true
  //valve_open = true;
  Serial.println("Valve Open");

}

void close_valve() {
  Serial.println("2");
  digitalWrite(RELAY_A, LOW); // turn RELAY_A off
  //valve_open = false;
  Serial.println("3");
  Serial.println("Vavle Closed");
}

void controlValve(bool open)
{

}

void flow_A_blink() {

  digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for one second
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

void flow_A_blink_stop() {

  digitalWrite(led, LOW);
}

void getFlow() {

  duration = pulseIn(pin, HIGH);
  Serial.print(duration);
  Serial.println("");
  delay(200);
}

/*
 * Main program loop, runs over and over repeatedly
 */

void loop() {
  if(checkForCorrectCommand("{open_valve}") == true) {
    open_valve();
    Serial.println("OPENING"); 
    getFlow();   
  }
  else if(checkForCorrectCommand("{close_valve}") == true)
  {
    close_valve();
    Serial.println("CLOSING");
  }
}

bool checkForCorrectCommand(String cmd) {  

    //Serial.println(inputString);
    //Serial.println(cmd);

    if(inputString == cmd) { 
     // reset String variables for serial data commands
     Serial.println("1");
     inputString = "";
     stringComplete = false;
     return true;
      // reset String variables for serial data commands
      inputString = "";
      stringComplete = false;
      return false;
    } 
}

//SerialEvent occurs whenever a new data comes in the
//hardware serial RX.  This routine is run between each
//time loop() runs, so using delay inside loop can delay
//response.  Multiple bytes of data may be available.

void serialEvent() {
  while(Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}
4

3 回答 3

0

您的代码不应按照此处粘贴的方式编译。checkForCorrectCommand 函数没有匹配和不匹配的返回值。您的代码显示您打算为匹配和不匹配的情况清空 inputString 缓冲区。如果字符串匹配不正确,您希望输入缓冲区保持不变,以便可以运行以下测试用例。

bool checkForCorrectCommand(String cmd) {  

  if(inputString == cmd) { 
    // for match case, the string is consumed from the buffer
    inputString = "";
    stringComplete = false;
    return true;
  } 
  else {
    // for the non-match case, leave the buffer for further Rx or further tests
    return false;
  } 
于 2013-07-09T01:06:23.497 回答
0

jdr5ca 的注释非常正确。checkForCorrectCommand 例程需要一个带有单独返回语句的 else 子句。克里斯设计的解决方案很好。显然最好只处理完整的 inputString 的内容,并在检查有效命令后丢弃它(inputString 的内容)。我想对serialEvent 做一个小改动。

serialEvent 例程不应继续向已完成的字符串添加字符。相反,它应该将它们留在缓冲区中以帮助形成下一个命令。请参阅下面的代码。

void serialEvent() {
  if (stringComplete)
    return;
  while(Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
} 
于 2013-11-10T15:37:33.310 回答
0

所以我用下面的代码修改了我的草图,现在它似乎也以我想要的方式处理串行命令。

 // flow_A LED
 int led = 4;

 // relay_A
 const int RELAY_A = A0;

 // variables from sketch example
 String inputString = ""; // a string to hold incoming data
 boolean stringComplete = false; // whether the string is complete

 // variables from SO thread
 boolean LED_state = false;
 boolean vavle_open = false;

// flowmeter shit
unsigned long totalCount = 0;
unsigned long previousCount = 0;
int pin = 2;
unsigned long duration;

// storage variable for the timer
unsigned long previousMillis=0;
int interval=1000; //in milliseconds

// counters for each flowmeter
unsigned long countA = 0;

void setup() {
   // initialize serial
   Serial.begin(9600); // open serial port, sets data rate to 115200bps
   // Serial.println("Power on test - println");
   // line below is for iPhone testing
   // Serial.write("Power on test - write");
   inputString.reserve(200);

   pinMode(RELAY_A, OUTPUT);

   // flowmeter shit
   pinMode(pin, INPUT);

}

void open_valve() {

  digitalWrite(RELAY_A, HIGH); // turn RELAY_A on
  // Serial.println("Valve Open");
  Serial.write("{valve_open}");
}

void close_valve() {
  digitalWrite(RELAY_A, LOW); // turn RELAY_A off
  // Serial.println("Vavle Closed");
  Serial.write("{valve_close}");
}

void flow_A_blink() {

  digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for one second
  digitalWrite(led, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

void flow_A_blink_stop() {

  digitalWrite(led, LOW);
}

void getFlow() {

  duration = pulseIn(pin, HIGH);
  Serial.print(duration);
  Serial.println("");
  delay(200);
}

/*
 * Main program loop, runs over and over repeatedly
 */

void loop() {

 //print the string when a newline arrives:
 if(stringComplete) {
//    Serial.println(inputString);

    if(inputString.equals("{open_valve}\n")) {
//       Serial.println("opening valve.");
       open_valve();
    }

    if(inputString.equals("{open_valve}")) {
//       Serial.println("opening valve.");
       open_valve();
    }

    if(inputString.equals("{close_valve}\n")) {
//      Serial.println("close vavle.");
      close_valve();
    }

    if(inputString.equals("{close_valve}")) {
//      Serial.println("close vavle.");
      close_valve();
    }

  // clear the string:
  inputString = "";
  stringComplete = false;
  }
}

/*
 SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
*/

void serialEvent() {
  while(Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
    // Serial.println(inputString.length());
  }
}
于 2013-07-16T19:51:24.480 回答