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

0

Я использую 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") и это strcmp(data, "fade") проблему.

Думаю, мне нужен способ очистки моего кода и, возможно, упростить введение новых бит функциональности в зависимости от того, какие строки возвращаются.

Функции, которые я хотел бы сделать, будут контролировать цвета RGB, а затем Fading или Blinking, что выбранный вами цвет.

Что делать, если я хотел бы ввести более быстрое мигание? Вместо того, чтобы устанавливать другое целое число и добавлять другое условие, существует ли более чистый подход?

Выбор цветов задается выбором цветового круга в приложении 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
    Я полагаю, что RFduinoBLE_onReceive не всегда доставляет полные данные за один вызов. RFduinoBLE_onReceive ли вы свой последовательный журнал, чтобы увидеть, отображаются ли правильные данные в одной строке?
  • 0
    @Paulw11: Paulw11: Да, я уже это проверил. Правильные данные появляются в одной строке для каждого нажатия кнопки.
Теги:
rgb
arduino

1 ответ

1
Лучший ответ

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

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

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

  • 0x01 - начало пакета
  • 1 байтовая команда b = Мигает, f = Fade, c = установить цвет
  • 6 байтов. Для команды c это будет три пары шестнадцатеричных символов для rgb. Для b & f это может быть 2 символа скорости blink/fade, а остальные 4 байта - 0000 для заполнителя
  • 0x03 - Конец пакета

Тогда вы можете построить конечный автомат -

  1. Ожидание 0x01. Как только вы его перейдете в состояние 2
  2. Ожидание действительного байта команды. Если вы получите действительный один переход в состояние 3. Если вы получите 0x01, вернитесь в состояние 2. Если вы получите какой-либо другой байт, перейдите в состояние 1
  3. Ожидание 6 шестнадцатеричных цифр. Если вы получаете 0x01 пребывания в состоянии 2. Если вы получаете что-либо кроме 0-9 af, возвращайтесь в состояние 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;
     }
}
  • 0
    Спасибо за ответ, это высоко ценится. Я буду читать на конечных автоматах. Я хотел бы простой пример кода, если вы чувствуете себя обязанным.
  • 0
    Ваш код очень сильно смутил меня. Я постараюсь понять, что вы предоставили. Мне, возможно, придется открыть новый вопрос и попросить кого-нибудь прояснить мне все это.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню