Извлечение значений из входящего последовательного Bluetooth на Arduino - PullRequest
2 голосов
/ 26 июня 2019

В настоящее время я работаю над проектом, который включает в себя приложение для Android, которое управляет светодиодной лентой через Arduino. Это делается через модуль Bluetooth. Проблема, с которой я столкнулся, заключается в том, что приложение включает в себя такие функции, как управление яркостью и оттенком светодиодной ленты. Поэтому, когда вносится изменение в любой из этих компонентов в приложении, значение отправляется в arduino, чтобы он обновил значения. Сообщения отправляются, например, "bt + 50!" где первые две буквы обозначают, какой компонент изменен (bt = яркость), «+» обозначает начало фактического значения и «!» указывая на конец.

Я хотел бы помочь выяснить, как я могу разделить и разделить входящие сообщения, чтобы я мог сначала определить, какой компонент изменен, а затем иметь возможность извлекать целочисленные значения, что-то вроде:

if(message_id == 'bt'){
    brightness = message_value;
}

В настоящее время я просто тестирую вещи на обычном одноцветном светодиодном светильнике. И я реализовал только очень простой код, который работает с однобуквенными сообщениями, поступающими с последовательного порта Bluetooth.

Я пытался использовать встроенные строковые функции C, но так как я новичок в языке C и я из Python, мне было трудно заставить все работать.

// Bluetooth module used - HC-06

#include <SoftwareSerial.h>
SoftwareSerial BlueTooth(5, 6); // (TXD, RXD) of HC-06

char BT_input; // to store input character received via BT.

void setup()  
{
  pinMode(13, OUTPUT);     // Arduino Board LED Pin
  BlueTooth.begin(9600);  
}

void loop() 
{
  if (BlueTooth.available())
  {
    BT_input=(BlueTooth.read());
    if (BT_input=='n')
    {
      digitalWrite(13, HIGH);
      BlueTooth.println("Now LED is ON");
    }
    else if (BT_input=='f')
    {
      digitalWrite(13, LOW);
      BlueTooth.println("Now LED is OFF");
    }
  }
}

Я ожидаю извлечения message_id и message_value из входящих сообщений, чтобы я мог обновить свою светодиодную ленту.

Ответы [ 2 ]

3 голосов
/ 26 июня 2019

Вы можете иметь переменную string, в которой хранятся все значения read, и после считывания ! она начнет ее обрабатывать.

#include <SoftwareSerial.h>
SoftwareSerial BlueTooth(5, 6); // (TXD, RXD) of HC-06

char input; // to store input character received via BT.
String data;

void setup()  
{
  pinMode(13, OUTPUT);     // Arduino Board LED Pin
  BlueTooth.begin(9600);  
}

void loop() 
{
  if (BlueTooth.available())
  {
    input=(BlueTooth.read());

      if (input != '!') {
          data += input;
      }
      else{
          String message_id = String(data.substring(0,2)); //gets only "bt"
          data.remove(0,3); //data becomes "50" since '!' is not added to data

          int message_value = data.toInt();

          if(message_id == "bt"){
               brightness = message_value;
          }
      }
  }
}
0 голосов
/ 26 июня 2019

Вы можете использовать типичный трюк, используемый в случаях, в качестве ваших, кодируя многобайтовые литералы символов в одном unsigned int, что на Arduino uno и Mega 2560 составляет 16 бит в формате с прямым порядком байтов.

Со ссылкой на стандарт C ISO / IEC 9899: 201x § "6.4.4.4 Символьные константы" .

Подпункт 10 объясняет наш случай:

Целочисленная символьная константа имеет тип int. Значение целого числа символьная константа, содержащая один символ, который отображается на однобайтовый символ выполнения - это числовое значение представление сопоставленного символа, интерпретируемого как целое число. значение целочисленной символьной константы, содержащей более одного символ (например, «ab») или содержащий символ или escape-последовательность который не отображается на однобайтовый символ выполнения, от реализации . Если целочисленная символьная константа содержит одиночный символ или escape-последовательность, его значение является тем, которое приводит к когда объект с типом char, значение которого является значением одного символьная или escape-последовательность преобразуется в тип int.

В нашем случае управление «определяется реализацией», как описано ниже.

В этом случае многобайтовая константа 'bt' может быть закодирована как 16-битное целое число 0x6274, где 'b'=0x62 и 't'=0x74.

Компилятор также должен быть достаточно умен, чтобы преобразовывать многобайтовую последовательность символов в значение типа int.

В следующем фрагменте мы считаем, что массив char msg содержит полученное сообщение, и мы используем простую и функциональную инструкцию switch (для которой требуется целочисленное значение), преобразующую переменную msg в целое число без знака. :

char msg[10];
...
switch (*((unsigned int *)msg))
{
    case 'tb':     //Note the reverse order of command characters due to endianess
        int value = atoi(msg+2);    //Convert number to int
        ....     //do something
    break;

    ....    //other cases
}

приведение переменной-указателя msg к указателю на целое число без знака компилятор интерпретирует первые 2 символа как целое число, как описано выше, и действует переключение на основе их значения.

В следующем примере используется ваш код, модифицированный для использования коммутатора. Предполагается, что команда имеет фиксированную длину, равную MAX_MSG_LEN (2 символа для команды, 2 символа для значения и конец сообщения):

// Bluetooth module used - HC-06

#include <SoftwareSerial.h>
SoftwareSerial BlueTooth(5, 6); // (TXD, RXD) of HC-06

#define MAX_MSG_LEN 5       //Max message length
#define OFFSET_TO_VALUE     //Offset in input buffer to value

char BT_input[10];  // to store input characters received via BT.

void setup()
{
    pinMode(13, OUTPUT);    // Arduino Board LED Pin
    BlueTooth.begin(9600);
}

void loop()
{
    if (BlueTooth.available())
    {
        /*
         * Read in the message up to the '!'
         */
        int i=0;
        do
        {
            BT_input[i] = (BlueTooth.read());
        } while (i<MAX_MSG_LEN && BT_input[i++]!='!');

        /*
         * If message length is exactly what we expect
         * we can process the message.
         * Note that because of endianess the command
         * chare are rversed.
         */
        if (i == MAX_MSG_LEN)
        {
            switch (*((unsigned int *)BT_input))
            {
                case 'tb':  // command 'bt'
                    process_brigthness(atoi(BT_input + OFFSET_TO_VALUE));
                    break;

                case 'no':  // command 'on'
                {
                    digitalWrite(13, HIGH);
                    BlueTooth.println("Now LED is ON");
                    break;
                }

                case 'fo':  // command 'of' for off
                {
                    digitalWrite(13, LOW);
                    BlueTooth.println("Now LED is OFF");
                    break;
                }

                default:    // unknown command
                {
                    unknown_command();
                    break;
                }
            }
        }
        else
        {
            /*
             * Process communication error
             */
            communication_error();
        }
    }
}

Или с помощью объединения потока ввода и структуры команды:

// Bluetooth module used - HC-06

#include <SoftwareSerial.h>
SoftwareSerial BlueTooth(5, 6); // (TXD, RXD) of HC-06

#define MAX_MSG_LEN 5       //Max message length
#define OFFSET_TO_VALUE     //Offset in input buffer to value

union tag_BT_input              // to store input characters received via BT.
{
    char   stream[MAX_MSG_LEN];
    struct
    {
        unsigned int cmd;       //Command
        char         val[2];    //value
        char         eom;       //End of message marker '!'
    }msg;
} BT_input;

void setup()
{
    pinMode(13, OUTPUT);    // Arduino Board LED Pin
    BlueTooth.begin(9600);
}

void loop()
{
    if (BlueTooth.available())
    {
        /*
         * Read in the message up to the '!'
         */
        int i=0;
        do
        {
            BT_input.stream[i] = (BlueTooth.read());
        } while (i<MAX_MSG_LEN && BT_input.stream[i++]!='!');

        /*
         * If message length is exactly what we expect
         * we can process the message.
         * Note that because of endianess the command
         * chare are rversed.
         */
        if (i == MAX_MSG_LEN)
        {
            switch (BT_input.msg.cmd)
            {
                case 'tb':  // command 'bt'
                    process_brigthness(atoi(BT_input.msg.val));
                    break;

                case 'no':  // command 'on'
                {
                    digitalWrite(13, HIGH);
                    BlueTooth.println("Now LED is ON");
                    break;
                }

                case 'fo':  // command 'of' for off
                {
                    digitalWrite(13, LOW);
                    BlueTooth.println("Now LED is OFF");
                    break;
                }

                default:    // unknown command
                {
                    unknown_command();
                    break;
                }
            }
        }
        else
        {
            /*
             * Process communication error
             */
            communication_error();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...