Как отправить большие данные (длинную строку) с ПК на Arduino с помощью Bluetooth

Одним из требований моих проектов является отправка данных из моего приложения в Arduino robot.

У меня есть Windows 10, и мой робот Arduino Uno. Bluetooth, который я использую на своем роботе,-это HC-06.

Сторона приложения:

  • Я пишу какой-то сценарий (С форматом, который я создал)
  • Затем преобразование его в jsonString
  • Открытие порта и отправка стартового сигнала связи.
  • Отправляя jsonString, каждый представляет другую команду, и они разделены специальным символом, который не может быть записан в сценарии. Вот в чем проблема, я попытался отправить строку длиной 256 байт (не jsonString) просто для проверки Bluetooth.

Тест, который я сделал в своем роботе

  • Я прочитал данные
  • Включил светодиод
  • Ожидание (data.length() / 10) секунд
  • Выключил светодиод

Для моих данных 256 байт светодиод был включен в течение 12,8 секунд, что составляет 128 байт. И иногда, когда я что-то менял, время составляло 6,4 секунды.

C# (Приложение)

string data = @"0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101";

protocolBT.BTcontroller.OpenPort();                   
protocolBT.BTcontroller.SendChar(ProtocolBT.COM_OpenChar);
protocolBT.BTcontroller.SendBigData(data);
protocolBT.BTcontroller.ClosePort();

Класс Bluetooth

public class BluetoothController
{
    private readonly SerialPort _serialPort;


    public BluetoothController(string portName, BaudRate baudRate)
    {
        _serialPort = new SerialPort(portName, (int)baudRate, Parity.None, 8, StopBits.One);
    }

    public static bool IsBluetoothSupported()
    {
        return BluetoothRadio.IsSupported;
    }

    public static void SetConnection()
    {
        if (IsBluetoothSupported())
        {
            if (BluetoothRadio.PrimaryRadio.Mode == RadioMode.PowerOff)
                BluetoothRadio.PrimaryRadio.Mode = RadioMode.Connectable;
        }
    }


    public void OpenPort()
    {
        try
        {
            _serialPort.Open();
        }
        catch(IOException IOex)
        {
            throw IOex;
        }
    }

    public void ClosePort()
    {
        _serialPort.Close();
    }

    public void SendData(string msg)
    {
        try
        {
            if (_serialPort.IsOpen)
            {
                byte[] data = Encoding.UTF8.GetBytes(msg);
                _serialPort.Write(data, 0, data.Length);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }


    public void SendBigData(string msg)
    {
        try
        {
            if (_serialPort.IsOpen)
            {
                foreach (char ch in msg)
                {
                    SendChar(ch);
                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public void SendChar(char ch)
    {
        try
        {
            if (_serialPort.IsOpen)
            {
                byte[] data = Encoding.UTF8.GetBytes(new char[]{ ch });
                _serialPort.Write(data, 0, data.Length);
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

}

А это мой тестовый код Arduino

#include <SoftwareSerial.h>

#define RX 10
#define TX 11
SoftwareSerial BT = SoftwareSerial(RX, TX);


String startCom = "»";

String MessageStart = "";
bool isListen = false;
String data = "";

int yellow = 12;



void setup() 
{
  // Define LED
  pinMode(yellow, OUTPUT);

  // Test yellow led
  digitalWrite(yellow, HIGH);
  delay(1000);
  digitalWrite(yellow, LOW);

  // Define Bluetooth
  pinMode(RX, INPUT);
  pinMode(TX, OUTPUT);
  BT.begin(9600);
}


void loop() 
{
  if(isListen == false)
  {
    readStartCommand();
  }
  else if(isListen == true)
  {
    readAllData();

    int len = data.length();
    if(len > 0)
    {
      robotLedOn(0); // Turn on the yellow led
      for(int i = 0; i < len; i++) // Wait (len * 0.1) second
      {
        delay(100);
      }
      robotLedOff(0); // Turn off the yelloe led
    }
  }
}


void readStartCommand()
{
  if(BT.available() > 0)
  {
    char ch = BT.read();
    Message += ch;

    if(MessageStart == startCom)
    {
      // Blink the yellow led if the start communication command recieved
      robotLedOn(0);
      delay(1000);
      robotLedOff(0);
      delay(2000);

      MessageStart = "";
      isListen = true;
    }
  }
}

void readAllData()
{

  while(BT.available() > 0)
  {
    data += BT.read();
  }
  isListen = false;
}

Я попытался поместить данные 256 байт вручную в строку в Arduino, и таймер был на 25,6 секунды. Поэтому я думаю, что есть предел для размера данных, которые может обрабатывать Bluetooth.

Примечание:

  • Мне нужен Json, потому что у меня сложные команды, а не только светодиоды. Некоторые команды требуют нескольких параметров из разных типов.
  • Скоро я получу Arduino-Mega, потому что у меня недостаточно контактов в Uno.

Попробовал:

  • Измените тайм-аут, он все равно перестанет получать 128 байт. с read() и setTimeout(100-2000) Результат таймера: 12,8 секунды С ReadString() и setTimeout(100-2000) Результат таймера: 6,4 секунды

  • Мой WriteBufferSize в PC Bluetooth составляет 2048 байт. Так что я почти уверен, что все данные отправлены.

  • Различные скорости передачи данных и использование библиотеки вместо Единственное изменение в том, что теперь таймер останавливается на 15,5 секунд...

  • Используйте BT.flush() и все мои данные отправляются 100% наверняка, проблема в получении в моем Arduino. Я думаю, что есть предел буфера для данных...

  • При использовании другого устройства Bluetooth результат по-прежнему составляет 15,5 секунды вместо 25,6 секунды.

, 👍1

Обсуждение

почему вы используете JSON? .... почему бы вам просто не использовать однобайтовые команды с однобайтовыми данными, такими как, например, " L10 " или "L:1:0", что может означать "LED 1 off"?, @jsotola

https://majenko.co.uk/blog/reading-serial-arduino, @Majenko

Для любого сообщения вы должны каким-то образом указать конец вашего пакета. Вы можете использовать символ завершения ot фиксированной длины данных. И вы должны считывать данные с последовательного порта на стороне Arduino до тех пор, пока не получите символ завершения ot, достигающий длины пакета., @Mike Petrichenko

тайм-аут не применяется для available() и read (), поэтому ваш код прекращает чтение при разрыве в потоке данных. входите, пока вы не моргнете светодиодом 3 секунды? тогда вы теряете данные там, @Juraj


1 ответ


0

Вы прекращаете чтение при первом разрыве между байтами. Для простого случая вы можете использовать data = BT.ReadString(). Он будет ждать следующего символа. Так что в конце он подождет секунду. Если это слишком долго, используйте BT.setTimeout(100) в setup().

Примечание. Использование строки в небольшой памяти Uno приведет к фрагментации памяти и сбою

,