Связь 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. Оба подключены одинаково.

Схема подключения двух Arduino с HM-10 Макетная плата — вид сверху

Если вы задаётесь вопросом, откуда второй HM-10 получает питание — соединения на обратной стороне.

Макетная плата — вид сзади

Я использую 2 разных Arduino IDE. Версию 1.82 как основную и версию 1.63 как дополнительную (портативная IDE). Это даёт мне 2 монитора порта. Arduino на COM6 — это #1, Arduino на COM9 — это #2.

Две Arduino IDE

Ручное подключение HM-10 к HM-10

Для установления соединения:

  1. Установите второй модуль в режим Peripheral (настройка по умолчанию).

  2. Установите основной модуль в ручной режим запуска с помощью «AT+IMME1».

  3. Установите основной модуль в режим Central с помощью «AT+ROLE1».

  4. Используйте «AT+CON» для подключения. Конечно, вам нужно знать адрес второго модуля, который можно найти с помощью «AT+DISC?».

Настройка Central и обнаружение устройств

Теперь, когда у нас есть адрес второго HM-10, мы можем подключиться, используя адрес или индекс из списка найденных устройств.

Я использую адрес, поэтому команда: «AT+CONA81B6AAE5221». Вам нужно изменить адрес в соответствии с вашими модулями.

Команда подключения AT+CON

Если соединение успешно, мы получаем «OK+CONNA», и светодиоды на HM-10 перестают мигать и горят постоянно.

Успешное подключение

Теперь всё, что введено в одном мониторе порта, передаётся в другой.

Передача данных — монитор 1 Передача данных — монитор 2

Автоматическое подключение 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» в данных распознаются как команды для светодиода. Есть несколько способов это предотвратить:

  1. Перед отправкой AT-команд отправьте приветственное сообщение, чтобы проверить наличие активного соединения. Удалённое устройство ответит на сообщение.

  2. Проверьте вывод STATE HM-10 перед отправкой AT-команд. Вывод STATE = HIGH при наличии соединения.

  3. Установите модули в режим автоподключения и уберите AT-команды. На мой взгляд, это лучший вариант.

Реализацию я оставляю вам.

Если вы хотите узнать больше об использовании последовательных данных для управления устройствами, посмотрите руководства по Arduino Serial.

В следующей части я управляю светодиодом только с HM-10, без второго Arduino.