[英]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
将数据编码为两位数的十六进制不会有多大影响,因此您可以使用看起来像
Then you can build a state machine - 然后,您可以构建状态机-
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.