Связь Arduino с Arduino через HM-10
Примечание
Перевод статьи Arduino to Arduino Communication Using HM-10s с сайта Martyn Currey.
Подключить два Arduino с помощью двух HM-10 довольно просто. Установить соединение несложно, и после его установления UART-уровень HM-10 выполняет всю работу за вас. Однако UART-уровень означает, что у вас нет контроля над фактическими деталями BLE.
Для установления соединения нужно лишь перевести основной модуль в ручной режим подключения, установить режим Central и использовать команду подключения AT+CON.
После подключения HM-10 передаёт данные, устанавливая значение пользовательской характеристики в передаваемые данные. Принимающее устройство затем считывает значение.
В этом примере у меня 2 Arduino, каждый подключён к HM-10. Оба подключены одинаково.
Если вы задаётесь вопросом, откуда второй HM-10 получает питание — соединения на обратной стороне.
Я использую 2 разных Arduino IDE. Версию 1.82 как основную и версию 1.63 как дополнительную (портативная IDE). Это даёт мне 2 монитора порта. Arduino на COM6 — это #1, Arduino на COM9 — это #2.
Ручное подключение HM-10 к HM-10
Для установления соединения:
Установите второй модуль в режим Peripheral (настройка по умолчанию).
Установите основной модуль в ручной режим запуска с помощью «AT+IMME1».
Установите основной модуль в режим Central с помощью «AT+ROLE1».
Используйте «AT+CON» для подключения. Конечно, вам нужно знать адрес второго модуля, который можно найти с помощью «AT+DISC?».
Теперь, когда у нас есть адрес второго HM-10, мы можем подключиться, используя адрес или индекс из списка найденных устройств.
Я использую адрес, поэтому команда: «AT+CONA81B6AAE5221». Вам нужно изменить адрес в соответствии с вашими модулями.
Если соединение успешно, мы получаем «OK+CONNA», и светодиоды на HM-10 перестают мигать и горят постоянно.
Теперь всё, что введено в одном мониторе порта, передаётся в другой.
Автоматическое подключение HM-10 к HM-10
HM-10 можно настроить на автоматическое подключение при запуске. Вмешательство пользователя не требуется.
Когда есть 2 или более модуля и один из них в режиме Central, он будет искать и подключаться к другому HM-10. Это полностью автоматический процесс, и вы не контролируете, к какому модулю он подключится, хотя обычно выбирается модуль с самым сильным сигналом. Конечно, если модулей только 2, это не имеет значения. Когда у вас только 2 модуля, установите один в режим Peripheral, а другой в режим Central. Они должны подключиться автоматически. Ничего другого не требуется.
Если было предыдущее соединение, последнее подключённое устройство будет иметь приоритет над другими модулями.
После ручного подключения разорвите соединение (выключите/включите питание) и, когда будете готовы, введите «AT+IMME0» (включает автоподключение). Затем перезагрузите модуль, выключив/включив питание или используя команду «AT+RESET». Модули теперь должны автоматически подключаться, даже если в зоне действия есть дополнительные HM-10.
Команда «AT+IMME1» останавливает автоподключение. Помните, что вы не можете использовать AT-команды при активном соединении (команды воспринимаются как данные), за исключением «AT», которая разрывает соединение. Поэтому для ввода AT-команд нужно выключить удалённый модуль и перезагрузить Central-модуль.
HM-10 к HM-10: Включение и выключение светодиода
Теперь попробуем дистанционное управление светодиодом. Это очень простой пример: при нажатии кнопки удалённый светодиод загорается. При отпускании кнопки светодиод гаснет.
На Arduino #1 добавляем кнопку к D2, а на Arduino #2 — светодиод к D4.
Кнопка на Arduino #1 подтянута к земле резистором 10 кОм. Это означает, что нажатие кнопки переводит вывод Arduino из LOW в HIGH.
Светодиод на Arduino #2 подключён последовательно с резистором 220 Ом (330 Ом тоже подойдёт).
Скетч на ведущем Arduino использует 3 AT-команды для настройки Central HM-10 и запуска соединения. Это те же команды, которые мы использовали в примере ручного подключения выше.
BTserial.print("AT+IMME1" );
delay(1000);
BTserial.print("AT+ROLE1" );
delay(1000);
BTserial.print("AT+CONA81B6AAE5221" );
delay(1000);
Это не самое лучшее решение, но оно работает и сохраняет пример простым для понимания. Конечно, если HM-10 уже в режиме Central и в ручном режиме запуска, первые 2 команды не нужны. Задержки дают время для получения ответов. При желании можно проверять правильный ответ перед переходом к следующей команде. Измените адрес в соответствии с вашими модулями.
Если вы используете старую прошивку, вам потребуется добавить команду «AT+RESET» после «AT+ROLE1».
Можно обойтись без этих команд, используя режим автоподключения.
После этого скетч проверяет состояние вывода, подключённого к кнопке, и если оно изменилось, отправляет одну из 2 команд:
LOW -> HIGH. Кнопка нажата — включаем светодиод, отправляя «1» на удалённый модуль.
HIGH -> LOW. Кнопка отпущена — выключаем светодиод, отправляя «0» на удалённый модуль.
Обратите внимание, что мы отправляем ASCII «1» и ASCII «0», а не значения 1 и 0.
// Very simple debouce.
boolean state1 = digitalRead(switchPin); delay(1);
boolean state2 = digitalRead(switchPin); delay(1);
boolean state3 = digitalRead(switchPin); delay(1);
if ((state1 == state2) && (state1==state3))
{
switch_State = state1;
if (switch_State != oldswitch_State)
{
if ( switch_State == HIGH) { BTserial.print("1" ); Serial.println("1"); }
else { BTserial.print("0" ); Serial.println("0"); }
oldswitch_State = switch_State;
}
}
Второй Arduino просто проверяет наличие «1» или «0» и в зависимости от этого включает или выключает светодиод.
void loop()
{
// Read from the Bluetooth module and check if it is a command
if (BTSerial.available())
{
c = BTSerial.read();
// 49 is the ascii code for "1"
// 48 is the ascii code for "0"
if (c==49) { digitalWrite(LEDpin,HIGH); }
if (c==48) { digitalWrite(LEDpin,LOW); }
Serial.println(c);
}
}
Вот полные скетчи.
На первом Arduino — HM-10_Example_01_simpleLED_Central:
// HM-10_Example_01_simpleLED_Central
//
// Simple remote control using HM-10s: LED on. LED off
//
//
// Pins
// BT VCC to Arduino 5V out.
// BT GND to GND
// Arduino D8 (ASS RX) - BT TX no need voltage divider
// Arduino D9 (ASS TX) - BT RX through a voltage divider
//
#include <AltSoftSerial.h>
AltSoftSerial BTserial;
byte switchPin = 2;
boolean switch_State = LOW;
boolean oldswitch_State = LOW;
void setup()
{
Serial.begin(9600);
Serial.print("Sketch: "); Serial.println(__FILE__);
Serial.print("Uploaded: "); Serial.println(__DATE__);
Serial.println(" ");
BTserial.begin(9600);
Serial.println("BTserial started at 9600");
Serial.println(" ");
pinMode(switchPin, INPUT);
// connect to the remote Bluetooth module
BTserial.print("AT+IMME1" );
delay(1000);
BTserial.print("AT+ROLE1" );
delay(1000);
BTserial.print("AT+CONA81B6AAE5221" );
delay(1000);
}
void loop()
{
// Very simple debouce.
boolean state1 = digitalRead(switchPin); delay(1);
boolean state2 = digitalRead(switchPin); delay(1);
boolean state3 = digitalRead(switchPin); delay(1);
if ((state1 == state2) && (state1==state3))
{
switch_State = state1;
if (switch_State != oldswitch_State)
{
if ( switch_State == HIGH) { BTserial.print("1" ); Serial.println("1"); }
else { BTserial.print("0" ); Serial.println("0"); }
oldswitch_State = switch_State;
}
}
}
На втором Arduino — HM-10_Example_01_simpleLED_Peripheral:
// HM-10_Example_01_simpleLED_Peripheral
//
// Pins
// BT VCC to Arduino 5V out.
// BT GND to GND
// Arduino D8 (ASS RX) - BT TX no need voltage divider
// Arduino D9 (ASS TX) - BT RX through a voltage divider
//
#include <AltSoftSerial.h>
AltSoftSerial BTSerial;
char c=' ';
byte LEDpin = 4;
void setup()
{
Serial.begin(9600);
Serial.print("Sketch: "); Serial.println(__FILE__);
Serial.print("Uploaded: "); Serial.println(__DATE__);
Serial.println(" ");
BTSerial.begin(9600);
Serial.println("BTserial started at 9600");
Serial.println(" ");
pinMode(LEDpin, OUTPUT);
digitalWrite(LEDpin,LOW);
}
void loop()
{
// Read from the Bluetooth module and check if it is a command
if (BTSerial.available())
{
c = BTSerial.read();
// 49 is the ascii code for "1"
// 48 is the ascii code for "0"
if (c==49) { digitalWrite(LEDpin,HIGH); }
if (c==48) { digitalWrite(LEDpin,LOW); }
Serial.println(c);
}
}
Вышеприведённый пример работает хорошо, но что произойдёт, если вы перезагрузите Arduino #1 при активном соединении? Светодиод загорится.
Когда вы перезагружаете Arduino, но не HM-10, соединение остаётся активным, и AT-команды в функции setup() отправляются как данные, при этом любые «1» в данных распознаются как команды для светодиода. Есть несколько способов это предотвратить:
Перед отправкой AT-команд отправьте приветственное сообщение, чтобы проверить наличие активного соединения. Удалённое устройство ответит на сообщение.
Проверьте вывод STATE HM-10 перед отправкой AT-команд. Вывод STATE = HIGH при наличии соединения.
Установите модули в режим автоподключения и уберите AT-команды. На мой взгляд, это лучший вариант.
Реализацию я оставляю вам.
Если вы хотите узнать больше об использовании последовательных данных для управления устройствами, посмотрите руководства по Arduino Serial.
В следующей части я управляю светодиодом только с HM-10, без второго Arduino.