Выполнение нескольких функций / команд на Arduino

Я использую RFduino и приложение iOS для управления некоторыми светодиодами RGB.

Вот как я посылаю строковую команду в модуль:

- (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? Мне кажется, что должен быть лучший способ делать то, что я пытаюсь сделать.

Первоначально, например, у меня возникла проблема, когда строка «fade» возвращалась как «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);
}

0

Решение

Мой подход к такого рода коммуникациям состоит в том, чтобы определить протокол, который включает символы начала и окончания (скажем, 0x01 и 0x03), а затем создать конечный автомат, который обрабатывает каждый входящий байт.

Причина этого заключается в том, что он помогает исправить несоответствующие байты и ошибки связи. Вы можете игнорировать данные, пока не получите 0x01, и команда не завершится, пока не получите 0x03. Если вы получили 0x03 до того, как ожидаете его, вы можете отказаться от неверного пакета.

Одна из проблем, с которой вы сталкиваетесь при использовании вашего текущего подхода и этой техники, заключается в том, что вы отправляете 8-битные данные для команды RGB — это может конфликтовать с вашими байтами начала / конца. Кодирование ваших данных в виде двухзначного шестнадцатеричного кода не окажет большого влияния, поэтому вы можете иметь протокол, который выглядит примерно так:

  • 0x01 — начало пакета
  • 1-байтовая команда b = Blink, f = Fade, c = установить цвет
  • 6 байтов аргументов. Для команды c это будет три пары шестнадцатеричных символов для rgb. Для б & 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

Это не скомпилируется, так как у меня нет 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;
}
}
1

Другие решения


По вопросам рекламы [email protected]