簡體   English   中英

用於Arduino草圖的字符串命令可以正常工作

[英]String commands for Arduino sketch kind of working but not really

所以我有一個Arduino草圖,可以讀取串行命令(一串字符),然后讓該草圖根據接收到的命令做一些事情。 截至目前,我有兩個命令,

  • {open_valve}
  • {close_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;
    }
  }
}

您的代碼不應按此處粘貼的方式進行編譯。 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;
  } 

因此,我用以下代碼修改了我的草圖,現在看來也可以按照我想要的方式處理串行命令。

 // 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());
  }
}

來自jdr5ca的注釋非常正確。 checkForCorrectCommand例程需要帶有單獨的return語句的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;
    }
  }
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM