执行对Arduino的多种功能/命令 [英] Executing multiple functions/commands on Arduino

查看:270
本文介绍了执行对Arduino的多种功能/命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 RFduino 以及iOS应用程序来控制一些RGB LED的。

这是我如何发送一个字符串命令到模块:

   - (IBAction为)fadeButton pressed:(ID)发送{
    [rfduino发送:[@变脸dataUsingEncoding:NSUTF8StringEncoding]];
}

这些命令(S)都回来了就好在RFduino端:

 无效RFduinoBLE_onReceive(字符*数据,INT LEN){
  如果(STRNCMP(数据褪色,4)== 0){
    //开始褪色选择LED彩
  }
}

是否有Arduino的执行多种功能的更好的办法?在我看来,应该有做我想要做的更好的方法。

最初比如我得到了一个问题,即变脸串回来了作为fadek所以我用 STRNCMP(数据,变脸,4)而不是 STRCMP(数据,变脸)这个固定的问题。

我想我想清理我的code的一种方式,或许更容易根据介绍的功能的新位上的字符串回来了。

我希望能够做到将控制RGB颜色,然后该功能的衰落闪烁的特定选择的颜色。

如果我想更快地介绍闪烁?而不是设置另一个命令整数,并添加另一个条件是有一个更清洁的方式?

的颜色的选择是由一个色轮的选择我的iPhone应用程序内。这是工作的罚款。问题是,闪烁和衰落不闪烁/淡出选中的颜色( 0命令)。

下面是我的整个草图至今:

 的#include< RFduinoBLE.h>//引脚2的RGB LED。
INT rgb2_pin = 2; //红
INT rgb3_pin = 3; // 绿色
INT rgb4_pin = 4; // 蓝色
INT亮度= 0;
INT fadeAmount = 5;//命令属性。
INT命令= 0;无效设置(){
  // 9600波特调试输出
  Serial.begin(9600);  //设置输出的LED。
  pinMode(rgb2_pin,OUTPUT);
  pinMode(rgb3_pin,OUTPUT);
  pinMode(rgb4_pin,OUTPUT);  //这是我们希望出现在广告中的数据
  //(该设备名称长度加上广告的长度必须与LT = 18个字节。
  RFduinoBLE.advertisementData =RGB;  //开始BLE堆栈。
  RFduinoBLE.begin();
}空隙环(){
  如果(命令== 1){//淡入/淡出选择的颜色。
    analogWrite(rgb2_pin,亮度);
    analogWrite(rgb3_pin,亮度);
    analogWrite(rgb4_pin,亮度);    //更改通过循环下一次的亮度:
    亮度=亮度+ fadeAmount;    //反转在淡出末端的衰落的方向:
    如果(亮度== 0 ||亮度== 255){
      fadeAmount = -fadeAmount;
    }    //等待30毫秒看到照明效果
    延迟(30);
  }否则如果(命令== 2){//闪烁
    digitalWrite(rgb2_pin,HIGH);
    digitalWrite(rgb3_pin,HIGH);
    digitalWrite(rgb4_pin,HIGH);
    延迟(200);
    digitalWrite(rgb2_pin,LOW);
    digitalWrite(rgb3_pin,LOW);
    digitalWrite(rgb4_pin,LOW);
    延迟(200);
  }
}空隙RFduinoBLE_onConnect(){}空隙RFduinoBLE_onDisconnect(){}无效RFduinoBLE_onReceive(字符*数据,INT LEN){
  Serial.println(数据);  //每个传输应该包含RGB三倍。
  如果(STRNCMP(数据褪色,4)== 0){
    命令= 1;
  }否则如果(STRNCMP(数据,闪烁,5)== 0){
    命令= 2;
  }其他{//改变颜色。
    //重置等功能。
    命令= 0;    如果(LEN> = 3){
      //获取RGB值。
      uint8_t有红色=数据[0];
      uint8_t有绿色=数据[1];
      uint8_t有蓝色=数据[2];      //为每个LED设置PWM。
      analogWrite(rgb2_pin,红色);
      analogWrite(rgb3_pin,绿色);
      analogWrite(rgb4_pin,蓝);
    }
  }  Serial.println(命令);
}


解决方案

我的方法对这些种类的通信是定义包括启动和停止字符的协议(比如0×01和×03),然后建立一个状态机,处理每个输入字节。

这样做的原因是它有助于为乱序字节,通信错误是正确的。直到你得到一个0×01和命令不会结束,直到你得到一个0×03,你可以忽略的数据。如果你希望它之前得到一个0×03,那么你可以放弃无效的数据包。

一个问题你与你目前的做法,这技术是您要发送的RGB命令8位数据 - 这可以与您的开始/结束字节冲突。它不会有C的数据,2位十六进制为en $ C $太大的影响,所以你可以有一个协议,它看起来像


  • 0×01 - 启动包

  • 1字节命令B =闪烁,F =淡入淡出,C =色彩设置

  • 6个字节的参数。对于指令C,这将是3对十六进制字符RGB。对于B和; F IT可能会眨眼/褪色率2个字符与其他4个字节是0000占位符

  • ×03 - 包结束

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


  1. 等待为0x01。一旦你将它移动到状态2

  2. 等待一个有效的命令字节。如果你得到一个有效的一招状态3。
    如果你得到0X01迁回状态2.如果您得到任何其它字节
    移动状态1

  3. 等待6个十六进制数字。如果你为0x01
    保持状态。如果你得到比0-9-F的举动之外的任何
    回到状态1

  4. 等待×03。如果你得到它,然后过​​程
    完整的命令,并返回到状态1如果你得到0X01回迁
    国家2.如果你得到任何东西搬到状态1

这将无法编译,因为我没有在我面前一个Arduino,但你会使用这样的

  INT状态; //初始化这1
字符的命令;
字符串十六进制串;无效RFduinoBLE_onReceive(字符*数据,INT LEN){    的for(int i = 0; I< LEN,我++){
        的statemachine(数据由[i]);
    }
}的statemachine(char数据){
    开关(州){
       情况1:
          如果(数据== 1){
              状态= 2;
          }
          打破;
       案例2:
          如果(数据=='B'||数据=='F'||数据=='C'){//如果我们收到了有效的命令
             命令=数据; //存放
             十六进制串=; // prepare接收十六进制字符串
             状态= 3;
          }否则如果(数据!= 1){//留在状态2,如果我们收到另一个为0x01
             状态= 1;
          }
          打破;
       案例3:
          如果((数据> ='一'和;&放大器;数据&下; ='Z')||(数据&GT ='0'和;&放大器;数据&下; ='9')){
              十六进制串=十六进制串+数据; //如果我们收到了有效的十六进制字节,将它添加到字符串的结尾
              如果(长度(十六进制串)== 6){//如果我们收到了6个字符(24位),移动到状态4
                  状态= 4;
              }
          }否则如果(数据== 1){//如果我们收到另一个为0x01回到状态2
             状态= 2;
          }其他{
             状态= 1; //还有什么是无效的 - 回到寻找为0x01
          }
          打破;
     情况4:
         如果(数据== 3)//×03 =有效终止
         {
           processCommand(命令,十六进制串); //我们有一个有效的命令消息 - 它的过程
           状态= 1;
         }否则如果(数据== 1){// 0×01 =开始新的消息,回到状态2
           状态= 2;
         }其他{
           状态= 1; //别的,回来找为0x01
         }
         打破;
     }
}

I am using an RFduino and an iOS application to control some RGB LEDs.

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:

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? 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.

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.

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. This is working fine. The problem is that the Blinking and Fading does not blink/fade the selected colour (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.

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. If you get a 0x03 before you expect it then you can discard the invalid packet.

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. 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
  • 1 byte command b=Blink, f=Fade, c=set color
  • 6 bytes arguments. For command c this would be three pairs of hex characters for rgb. For b & f it could be 2 characters of blink/fade rate with the other 4 bytes being 0000 for placeholder
  • 0x03 - End of packet

Then you can build a state machine -

  1. Waiting for 0x01. Once you get it move to state 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. Waiting for 6 hex digits. If you get 0x01 stay in state 2. If you get anything other than 0-9 a-f move back to state 1
  4. Waiting for 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

This won't compile as I don't have an Arduino in front of me, but you would use something like this

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

这篇关于执行对Arduino的多种功能/命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆