คำสั่งสตริงสำหรับ Arduino แบบร่างทำงานได้แต่ไม่ได้จริงๆ

ดังนั้นฉันจึงมีร่าง Arduino ที่อ่านคำสั่งอนุกรม (สตริงตัวอักษร) จากนั้นให้ร่างทำอะไรบางอย่างตามคำสั่งที่ได้รับ ณ ตอนนี้ฉันมีสองคำสั่ง

  • {เปิด_วาล์ว}
  • {ปิด_วาล์ว}

เมื่อฉันส่งคำสั่ง {open_valve} ไปยัง Arduino วาล์วจะเปิดได้ดี แต่วาล์วไม่ปิดเมื่อฉันส่งคำสั่ง {close_valve} ไปยัง Arduino ร่างมีลักษณะดังต่อไปนี้

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

person ipatch    schedule 08.07.2013    source แหล่งที่มา


คำตอบ (3)


โค้ดของคุณไม่ควรคอมไพล์ตามที่วางไว้ที่นี่ ฟังก์ชัน 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;
  } 
person jdr5ca    schedule 09.07.2013
comment
ขอบคุณสำหรับคำแนะนำ ฉันจะลองดูในภายหลังวันนี้ - person ipatch; 09.07.2013
comment
jdr5ca เมื่อฉันใส่คำสั่ง else ลงไป วาล์วก็ไม่เปิดหรือปิด ฉันเอาคำสั่ง else ออกแล้ว และตอนนี้อย่างน้อยฉันก็สามารถเปิดวาล์วได้แล้ว - person ipatch; 10.07.2013
comment
เดี๋ยวก่อนคุณบอกว่าไม่มีอย่างอื่นในรหัสดั้งเดิมของคุณเหรอ? ฉันคิดว่ามันเป็นเพียงข้อผิดพลาดในการวางโค้ด checkForCorrectCommand() ไม่มีโอกาสทำงานตามที่เขียนไว้ - person jdr5ca; 10.07.2013

ดังนั้นฉันจึงแก้ไขร่างของฉันด้วยโค้ดต่อไปนี้ และตอนนี้ดูเหมือนว่าจะประมวลผลคำสั่งอนุกรมตามที่ฉันต้องการเช่นกัน

 // 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());
  }
}
person ipatch    schedule 16.07.2013

บันทึกจาก jdr5ca ค่อนข้างถูกต้อง รูทีน checkForCorrectCommand จำเป็นต้องมีส่วนคำสั่ง else พร้อมด้วยคำสั่ง return ที่แยกต่างหาก วิธีแก้ปัญหาที่คริสคิดไว้นั้นดี เห็นได้ชัดว่าดีกว่าที่จะประมวลผลเนื้อหาของ 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;
    }
  }
} 
person Peter Schaeffer    schedule 10.11.2013