在 Arduino 上执行多个功能/命令 [英] Executing multiple functions/commands on Arduino

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

问题描述

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

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

这些命令在 RFduino 端返回得很好:

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

是否有更好的方法在 Arduino 上执行多个功能?在我看来,应该有更好的方法来做我想做的事情.

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.

最初例如我遇到了一个问题,其中fade"字符串作为fadek"返回,所以我使用了 strncmp(data, "fade", 4) 而不是 strcmp(数据,淡出"),这解决了这个问题.

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.

我希望能够执行的功能是控制 RGB 颜色,然后淡化闪烁该特定选择的颜色.

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?

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

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

推荐答案

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

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 之前命令不会结束.如果您在预期之前得到 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. If you get a 0x03 before you expect it then you can discard the invalid packet.

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

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 - 数据包开始
  • 1 字节命令 b=Blink, f=Fade, c=set color
  • 6 字节参数.对于命令 c,这将是 rgb 的三对十六进制字符.对于 b &f 可以是 2 个字符的闪烁/淡入淡出率,其他 4 个字节为占位符 0000
  • 0x03 - 数据包结束

然后就可以构建状态机了-

Then you can build a state machine -

  1. 等待 0x01.一旦你得到它移动到状态 2
  2. 正在等待有效的命令字节.如果你得到一个有效的移动到状态 3.如果你得到 0x01 回到状态 2.如果你得到任何其他字节移动到状态 1
  3. 等待 6 个十六进制数字.如果你得到 0x01保持状态 2.如果你得到除 0-9 a-f 以外的任何动作回到状态 1
  4. 等待 0x03.如果你得到它然后处理完成命令并返回状态 1.如果你得到 0x01 移回到状态 2.如果你得到任何其他东西,请转到状态 1

这不会编译,因为我面前没有 Arduino,但你会使用这样的东西

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天全站免登陆