简体   繁体   English

在Arduino上执行多种功能/命令

[英]Executing multiple functions/commands on Arduino

I am using an RFduino and an iOS application to control some RGB LEDs. 我正在使用RFduino和iOS应用程序来控制某些RGB LED。

This is how I'm sending a string command to the module: 这就是我向模块发送字符串命令的方式:

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

These command(s) are coming back just fine on the RFduino side: 这些命令在RFduino方面很好地返回了:

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

Is there a better way of executing multiple functions on Arduino? 有没有在Arduino上执行多种功能的更好方法? It seems to me that there should be a better way of doing what I'm trying to do. 在我看来,应该有一种更好的方法来做我想做的事情。

Originally for example I was getting an issue where the "fade" string was coming back as "fadek" so I used strncmp(data, "fade", 4) instead of strcmp(data, "fade") and this fixed the issue. 例如,最初,我遇到了一个问题,其中“ fade”字符串以“ fadek”的形式返回,因此我使用了strncmp(data, "fade", 4)而不是strcmp(data, "fade")并解决了该问题。

I guess I'd like a way of cleaning up my code and perhaps make it easier to introduce new bits of functionality depending on which strings are coming back. 我想我想要一种清理代码的方法,也许更容易根据返回的字符串来引入新的功能。

The functions I would like to be able to do would be controlling of the RGB colours and then Fading or Blinking that particular chosen colour. 我想做的功能是控制RGB颜色,然后淡入闪烁该特定选择的颜色。

What if I wanted to introduce faster blinking? 如果我想引入更快的闪烁怎么办? Rather than setting another command integer and adding another condition is there a cleaner approach? 除了设置另一个命令整数并添加另一个条件之外,还有没有更干净的方法?

The selection of the colours is set by selection of a color wheel within my iOS application. 颜色的选择是通过在我的iOS应用程序中选择一个色轮来设置的。 This is working fine. 一切正常。 The problem is that the Blinking and Fading does not blink/fade the selected colour ( command 0 ). 问题是闪烁和渐变不会闪烁/淡入所选颜色( command 0 )。

Here is my entire sketch so far: 到目前为止,这是我的整个草图:

#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);
}

My approach to these sort of communications is to define a protocol that includes start and stop characters (say 0x01 and 0x03) and then build a state machine that processes each incoming byte. 我进行这类通信的方法是定义一个包含开始和结束字符(例如0x01和0x03)的协议,然后构建一个状态机来处理每个传入的字节。

The reason for this is it helps correct for out-of-sequence bytes and communication errors. 这样做的原因是它有助于纠正乱序字节和通信错误。 You can ignore data until you get a 0x01 and the command doesn't end until you get a 0x03. 您可以忽略数据,直到得到0x01,并且命令直到得到0x03才结束。 If you get a 0x03 before you expect it then you can discard the invalid packet. 如果在期望之前得到0x03,则可以丢弃无效的数据包。

One issue you have with your current approach and this technique is that you are sending 8 bit data for the RGB command - this can conflict with your start/end bytes. 当前方法和此技术存在的一个问题是,您正在为RGB命令发送8位数据-这可能与您的开始/结束字节冲突。 It won't have much impact to encode your data as 2 digit hex, so you can have a protocol which looks something like 将数据编码为两位数的十六进制不会有多大影响,因此您可以使用看起来像

  • 0x01 - Start of packet 0x01-封包开始
  • 1 byte command b=Blink, f=Fade, c=set color 1字节命令b =闪烁,f =淡入淡出,c =设置颜色
  • 6 bytes arguments. 6个字节的参数。 For command c this would be three pairs of hex characters for rgb. 对于命令c,这将是rgb的三对十六进制字符。 For b & f it could be 2 characters of blink/fade rate with the other 4 bytes being 0000 for placeholder 对于b&f,它可能是2个字符的闪烁/淡入速率,而其他4个字节则是0000(占位符)
  • 0x03 - End of packet 0x03-封包结束

Then you can build a state machine - 然后,您可以构建状态机-

  1. Waiting for 0x01. 等待0x01。 Once you get it move to state 2 一旦获得,便进入状态2
  2. Waiting for a valid command byte. 等待有效的命令字节。 If you get a valid one move to state 3. If you get 0x01 move back to state 2. If you get any other byte move to state 1 如果得到有效的一则转移到状态3。如果得到0x01,则返回到状态2。如果得到任何其他字节,则转移到状态1。
  3. Waiting for 6 hex digits. 等待6个十六进制数字。 If you get 0x01 stay in state 2. If you get anything other than 0-9 af move back to state 1 如果得到0x01,则保持状态2。如果得到0-9 af以外的值,则返回状态1
  4. Waiting for 0x03. 等待0x03。 If you get it then process complete command and return to state 1. If you get 0x01 move back to state 2. If you get anything else move to state 1 如果得到它,则处理完整命令并返回到状态1。如果得到0x01,则返回到状态2。

This won't compile as I don't have an Arduino in front of me, but you would use something like this 由于我面前没有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;
     }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM