2017-03-17 150 views
0

我有下面的代碼,我需要快速執行,但它花了很多時間來改變值,無論如何,這使得這項任務的方式更快?Arduino readString();代碼運行緩慢

我使用indexOf()substring()來完成這個任務。 這是用於更改條形LED顏色。

// declare LED Series A Pins R-G-B (PWM Pins) 
    int const AledRedPin = 6; 
    int const AledGreenPin = 5; 
    int const AledBluePin = 3; 

// declare LED Series B Pins R-G-B (PWM Pins) 
    int const BledRedPin = 10; 
    int const BledGreenPin = 11; 
    int const BledBluePin = 9; 

// serial input variable & string 
// initialise LED Series A Pins R-G-B (PWN Value: 0 to 255) 
// initial value = 255 
    int AledRed = 255; 
    int AledGreen = 255; 
    int AledBlue = 255; 

// initialise LED Series A Pins R-G-B (PWN Value: 0 to 255) 
// initial value = 255 
    int BledRed = 255; 
    int BledGreen = 255; 
    int BledBlue = 255; 

//serial input 
    String Command = ""; 

//string manipulation 
    int cmdindexval = 0; 
    String CommandType = ""; 
    int CommandValue = 0; 
    String Series = ""; 

void setup() { 
    // put your setup code here, to run once: 
    // start serial 
    Serial.begin(9600); 
     while (!Serial) { 
     ; // wait for serial port to connect. Needed for native USB 
     } 

    // set LED Series A Pins as Output R-G-B 
    pinMode(AledRedPin, OUTPUT); 
    pinMode(AledGreenPin, OUTPUT); 
    pinMode(AledBluePin, OUTPUT); 

    // set LED Series B Pins as Output R-G-B 
    pinMode(BledRedPin, OUTPUT); 
    pinMode(BledGreenPin, OUTPUT); 
    pinMode(BledBluePin, OUTPUT); 
} 

void loop() { 
    // put your main code here, to run repeatedly: 
    // read from serial if it's available 
    if (Serial.available() > 0) { 
     Command = Serial.readString(); //read string from serial monitor 
     cmdindexval = Command.indexOf('='); //read characters until '=' then assign the value 
     CommandType = Command.substring(0, cmdindexval); //assign the value from 0 to cmdindexval 
     //Series = Command.substring(0, 1); //read first character 
     CommandValue = Command.substring(cmdindexval + 1).toInt(); //assign the value after '=' and convert string to Int 
     Serial.println(CommandType + " ,is equal to " + CommandValue + " ,Series: " + Series);  
     //if (Series == "A") { 
     if (CommandType == "ACledRed"){ 
      AledRed = CommandValue; 
     } 
     else if (CommandType == "ACledGreen"){ 
      AledGreen = CommandValue; 
     } 
     else if (CommandType == "ACledRedBlue") { 
      AledBlue = CommandValue; 
     } 
     //} 
     //else if (Series == "B") { 
     if (CommandType == "BCledRed") { 
      BledRed = CommandValue; 
     } 
     else if (CommandType == "BCledGreen") { 
      BledGreen = CommandValue; 
     } 
     else if (CommandType == "BCledBlue") { 
      BledBlue = CommandValue; 
     } 
    //} 
    } //end serial 

    analogWrite(AledRedPin, AledRed); 
    analogWrite(AledGreenPin, AledGreen); 
    analogWrite(AledBluePin, AledBlue); 

    analogWrite(BledRedPin, BledRed); 
    analogWrite(BledGreenPin, BledGreen); 
    analogWrite(BledBluePin, BledBlue); 

} 
+1

你確定'indexOf'很慢,而不是['readString'](https://www.arduino.cc/en/Serial/ReadString),它是基於超時的,默認超時是1秒? –

+0

我不確定。 @gre_gor –

回答

4

從阿爾杜伊諾docs on readString

Serial.readString()讀取來自串行緩衝器的字符爲一個字符串。如果超時(見setTimeout()),該函數終止。

docs on setTimeout

Serial.setTimeout()設置最大毫秒使用Serial.readBytesUntil(),Serial.readBytes(),Serial.parseInt(),或當等待串行數據Serial.parseFloat()。它默認爲1000毫秒。

這意味着readString始終等待1秒以確保發送字符串已完成並具有完整的字符串。
不幸的是,這意味着它的響應速度很慢。你可以通過setTimeout降低超時時間,但是你仍然會有一些延遲,或者如果你設置得太低,你可能會得到不完整的蜇傷。

最好的解決方案是使用readStringUntil,所以你知道你有一個完整的字符串,當你得到一個終結符字符(如換行符)。

更換

Command = Serial.readString(); 

Command = Serial.readStringUntil('\n'); 

,並確保您設置串口監視器,以便發送換行符。

+0

你好,做這項工作還需要1000毫秒。 :( –

+1

如果你發送一個換行符,它不應該。 –

+0

您的問題幫助我很多謝謝:)它的工作! –

3

編輯:看在最後的重要更新。

這可以顯著加快進行,但首先讓我們來看看有在每次循環做與當前代碼的工作:

  • 作爲@gre_gor already explained,你可能會失去一些時間readString()
  • 對於每個值,必須發送15到20個字節,讀取,解析並轉換爲int
  • 對於每個接收到的值(R,G或B),analogWrite()稱爲6次(和analogWrite()是不是真的快)。這意味着爲了改變這兩個系列,analogWrite()被稱爲36次(這可能是大部分時間丟失的地方)。如果沒有串行數據可用,analogWrite()仍被稱爲6次。
  • 以及Serial.println()在每個示例中都會被調用 - 所以最好關閉此功能。

爲了加快速度,RGB值可以發送到一個小緩衝區(假設你也可以控制發送端),並用Serial.readBytesUntil()來讀取。

byte rcvBuffer[7]; 

void loop() { 

    if (Serial.available() > 0) { 

     // message: RGBRGBx - but see update below 
     int numRead = Serial.readBytesUntil(0x78, rcvBuffer, 7); // 0x78 is 'x' 

     if (numRead == 7) { // or 6, see below 

      analogWrite(AledRedPin, rcvBuffer[0]); 
      analogWrite(AledGreenPin, rcvBuffer[1]); 
      analogWrite(AledBluePin, rcvBuffer[2]); 

      analogWrite(BledRedPin, rcvBuffer[3]); 
      analogWrite(BledGreenPin, rcvBuffer[4]); 
      analogWrite(BledBluePin, rcvBuffer[5]); 
     } 
     // else ignore this read - could be a first unaligned read 
    } 
} 

如果只有A或B中的值被髮送在一起:

如果A和B兩者的值被一起發送,所述6個RGB值可以爲6個字節發送

byte rcvBuffer[5]; 

void loop() { 

    // You could probably even remove the Serial.available() check 
    if (Serial.available() > 0) { 

     // message: TRGBx where T is Type ('A' or 'B') 
     int numRead = Serial.readBytesUntil(0x78, rcvBuffer, 5); // 0x78 is 'x' 

     if (numRead == 5) { // or 4, see below 

      switch (rcvBuffer[0]) { 
       case 'A': 
        analogWrite(AledRedPin, rcvBuffer[1]); 
        analogWrite(AledGreenPin, rcvBuffer[2]); 
        analogWrite(AledBluePin, rcvBuffer[3]); 
        break; 
       case 'B': 
        analogWrite(BledRedPin, rcvBuffer[1]); 
        analogWrite(BledGreenPin, rcvBuffer[2]); 
        analogWrite(BledBluePin, rcvBuffer[3]); 
        break; 
       default : 
        // do nothing, or send error message 
      } 
     } 
    } 
} 

我用'x'作爲停止字節使其可見,但您也可以使用零字節。

現在,我不太確定readBytesUntil()是否也會將終止字節讀入緩衝區或跳過它,並且現在無法對此進行測試。但我認爲只有RGB值被讀入緩衝區。在這種情況下,您必須將這些值更改爲我在註釋中輸入的值。

爲了節省更多的時間,你可以檢查每一個值,只能調用analogWrite()如果該值自上次調用(每個R,G和B)沒有變化。


更新:顯然,我們不能只用'x'或零字節作爲停止字節,因爲每個RGB值,也可以是一個'x'或零字節(已經晚了這裏:)。雖然可以使用ReadBytes(),但最好有一個停止字節來保持緩衝區對齊。所以我建議使用0xff(255)作爲停止字節,並確保沒有任何RGB值可以是0xff

以防萬一以後可能會有其他消息類型,每個消息也可以加上一個消息代碼(1或2個字節)。

+0

令人驚歎的解釋這真的很有幫助。 :)但它不能正常工作xD給它一個鏡頭,並知道你是否編輯非常感謝 –