Как отправить большие данные (длинную строку) с ПК на 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 секунды.
@Artiom, 👍1
Обсуждение1 ответ
Вы прекращаете чтение при первом разрыве между байтами. Для простого случая вы можете использовать data = BT.ReadString()
. Он будет ждать следующего символа. Так что в конце он подождет секунду. Если это слишком долго, используйте BT.setTimeout(100)
в setup()
.
Примечание. Использование строки в небольшой памяти Uno приведет к фрагментации памяти и сбою
- Можно ли измерить скорость акселерометром? Насколько точно?
- Модуль Bluetooth HC-05 мигает красным светом - Arduino Uno
- Модуль Bluetooth HC-05 возвращает закодированные данные
- Мой модуль Bluetooth HC-05 не работает
- Модуль AT-команд HM10 BLE — не работает
- Программные обновления FOTA (микропрограммы по беспроводной сети) с Uno R3
- Создание Bluetooth-мыши с помощью Arduino
- Чтение характеристического значения BLE в Arduino Uno
почему вы используете 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