2017-03-17 419 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给它一个镜头,并知道你是否编辑非常感谢 –