在Arduino上执行多个函数/命令

时间:2014-06-02 02:06:31

标签: c++ ios arduino rgb rfduino

我正在使用RFduino和iOS应用程序来控制某些RGB LED。

这是我向模块发送字符串命令的方式:

- (IBAction)fadeButtonPressed:(id)sender {
    [rfduino send:[@"fade" dataUsingEncoding:NSUTF8StringEncoding]];
}

这些命令在RFduino方面恢复正常:

void RFduinoBLE_onReceive(char *data, int len) {
  if (strncmp(data, "fade", 4) == 0) {
    // begin fading chosen LED colour
  }
}

有没有更好的方法在Arduino上执行多个功能?在我看来,应该有一种更好的方式去做我想做的事情。

最初例如我遇到的问题是"褪色"字符串回来了" fadek"所以我使用strncmp(data, "fade", 4)而不是strcmp(data, "fade")来解决这个问题。

我想我想要一种清理代码的方法,也许可以根据哪些字符串返回来更容易地引入新的功能。

我希望能够做的功能是控制RGB颜色,然后淡化闪烁特定的颜色。

如果我想引入更快的闪烁怎么办?而不是设置另一个命令整数并添加另一个条件是否有更清洁的方法?

通过选择我的iOS应用程序中的色轮来设置颜色的选择。这工作正常。问题是闪烁和淡入淡出不会使所选颜色闪烁/淡化(command 0)。

到目前为止,这是我的整个草图:

#include <RFduinoBLE.h>

// Pin 2 on the RGB LED.
int rgb2_pin = 2; // red
int rgb3_pin = 3; // green
int rgb4_pin = 4; // blue
int brightness = 0;
int fadeAmount = 5;

// Command properties.
int command = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);

  // Setup the LEDs for output.
  pinMode(rgb2_pin, OUTPUT);
  pinMode(rgb3_pin, OUTPUT);
  pinMode(rgb4_pin, OUTPUT);

  // This is the data we want to appear in the advertisement
  // (the deviceName length plus the advertisement length must be <= 18 bytes.
  RFduinoBLE.advertisementData = "rgb";

  // Start the BLE stack.
  RFduinoBLE.begin();
}

void loop() {
  if (command == 1) { // Fade in/out chosen colour.
    analogWrite(rgb2_pin, brightness);
    analogWrite(rgb3_pin, brightness);
    analogWrite(rgb4_pin, brightness);

    // Change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // Reverse the direction of the fading at the ends of the fade:
    if (brightness == 0 || brightness == 255) {
      fadeAmount = -fadeAmount ;
    }

    // Wait for 30 milliseconds to see the dimming effect
    delay(30);
  } else if (command == 2) { // Blink
    digitalWrite(rgb2_pin, HIGH);
    digitalWrite(rgb3_pin, HIGH);
    digitalWrite(rgb4_pin, HIGH);
    delay(200);
    digitalWrite(rgb2_pin, LOW);
    digitalWrite(rgb3_pin, LOW);
    digitalWrite(rgb4_pin, LOW);
    delay(200);
  }
}

void RFduinoBLE_onConnect() {}

void RFduinoBLE_onDisconnect() {}

void RFduinoBLE_onReceive(char *data, int len) {
  Serial.println(data);

  // Each transmission should contain an RGB triple.
  if (strncmp(data, "fade", 4) == 0) {
    command = 1;
  } else if (strncmp(data, "blink", 5) == 0) {
    command = 2;
  } else { // Change colour.
    // Reset other functions.
    command = 0;

    if (len >= 3) {
      // Get the RGB values.
      uint8_t red = data[0];
      uint8_t green = data[1];
      uint8_t blue = data[2];

      // Set PWM for each LED.
      analogWrite(rgb2_pin, red);
      analogWrite(rgb3_pin, green);
      analogWrite(rgb4_pin, blue);
    }
  }

  Serial.println(command);
}

1 个答案:

答案 0 :(得分:1)

我对这种通信的方法是定义一个包含开始和停止字符(比如0x01和0x03)的协议,然后构建一个处理每个传入字节的状态机。

这样做的原因是它有助于纠正无序字节和通信错误。在获得0x01之前,您可以忽略数据,并且命令不会结束,直到您获得0x03。如果你在期望之前得到0x03,那么你可以丢弃无效的数据包。

您当前的方法和此技术存在的一个问题是您正在为RGB命令发送8位数据 - 这可能与您的开始/结束字节冲突。将数据编码为2位十六进制不会产生太大影响,因此您可以使用类似

的协议。
  • 0x01 - 数据包开始
  • 1字节命令b =闪烁,f =淡化,c =设置颜色
  • 6个字节的参数。对于命令c,这将是rgb的三对十六进制字符。对于b&amp; f它可以是2个字符的闪烁/淡入淡出率,其他4个字节对于占位符为0000
  • 0x03 - 数据包结束

然后你可以建立一个状态机 -

  1. 等待0x01。一旦你把它移到州2
  2. 等待有效的命令字节。如果你有一个有效的移动到状态3。 如果你得到0x01,则回到状态2.如果你得到任何其他字节 转到州1
  3. 等待6位十六进制数字。如果你得到0x01 保持状态2.如果你得到0-9以外的任何东西a-f移动 回到状态1
  4. 等待0x03。如果你得到它然后处理 完成命令并返回状态1.如果你得到0x01后退 状态2.如果你得到任何其他东西,请转到州1
  5. 这不会编译,因为我没有在我面前有一个Arduino,但你会使用这样的东西

    int state;   //  Initialise this to 1 
    char command;
    string hexstring;
    
    void RFduinoBLE_onReceive(char *data, int len) {
    
        for (int i=0;i<len;i++) {
            stateMachine(data[i]);
        }
    }
    
    stateMachine(char data) {
    
    
        switch (state) {
           case 1:
              if (data == 1) {
                  state=2;
              }
              break;
           case 2:
              if (data=='b' || data== 'f' || data == 'c') {  // If we received a valid command
                 command=data;                               // store it
                 hexstring="";                               // prepare to receive a hex string
                 state=3;
              } else if (data != 1) {    //Stay in state 2 if we received another 0x01
                 state =1;
              }
              break;
           case 3:
              if ((data >='a' && data <='z') || (data >='0' && data <='9')) {
                  hexstring=hexstring+data;     // if we received a valid hex byte, add it to the end of the string
                  if (length(hexstring) == 6) {  // If we have received 6 characters (24 bits) move to state 4
                      state=4;
                  }
              } else if (data == 1) {            // If we received another 0x01 back to state 2
                 state =2;
              } else {
                 state=1;                        // Anything else is invalid - back to look for 0x01
              }
              break;
         case 4:
             if (data == 3)                      // 0x03=valid terminator
             {
               processCommand(command,hexstring);  // We have a valid command message - process it
               state=1;
             } else if (data==1) {               // 0x01= start of new message, back to state 2
               state=2;
             } else {
               state=1;                          // anything else, back to look for 0x01
             }
             break;
         }
    }