В комнате у меня валяются четыре HC-05, и все четыре называются одинаково. Однажды это сыграло злую шутку: телефон показал в списке два устройства HC-05 — мой модуль и модуль соседа, — и я минут десять спаривался не с тем, удивляясь, почему пульт управляет не моей лампочкой. Имя, PIN и скорость зашиты в самом модуле, а не в скетче: они переживают отключение питания, как значения в EEPROM, только перепрошиваются не кодом, а командами AT.
Команды AT — диалог с модулем: печатаете AT+NAME=Banya — модуль отвечает OK, и с этого момента он в эфире называется по-новому. Диалог упрямый: не та скорость, не то окончание строки, не тот режим — и модуль молчит так убедительно, что начинаешь подозревать брак. Ниже — карта всех граблей, по которым я прошёл, и скетч-конфигуратор, который прогоняет настройку целиком одним включением. А когда Bluetooth упрётся в потолок десяти метров и пары устройств, дорога уводит в сеть: в уроке про первый WiFi на ESP32 тот же Serial-диалог переезжает в интернет.
Когда это вообще нужно. Первый случай — у вас больше одного модуля, и все они в эфире называются HC-05: имя нужно, чтобы телефон цеплялся к вашему, а не к соседскому. Второй — безопасность: PIN 1234 знают все, и на мастерской, где дети и гости, заводской пин оставлять не хочется. Третий — связка двух плат: чтобы один HC-05 дозвонился до другого, нужны разные имена и роли, а роль задаётся командой — без AT-режима два модуля друг друга не найдут. И четвёртый — скорость: для обильных данных 9600 может оказаться тесно, и это тоже правится командой, о которой ниже.
Два режима и вход в настройки
У HC-05 два режима. Обычный — данные: пара установлена, и модуль прозрачен, как провод — байты влетают с одной стороны, вылетают с другой. Второй — режим AT: настройки; модуль слушает команды и отвечает OK или ERROR(0). В режиме данных AT-команды бесполезны: они улетают собеседнику как текст. Я однажды полдня слал AT+NAME в работающую пару и не мог понять, почему телефон вместо ответа печатает мне мои же команды.
Вход в режим AT — две дороги. На платах с кнопкой EN (у популярной обвязки ZS-040 она прямо на борту): зажать кнопку, подать питание, отпустить — модуль стартует сразу в настройках. Если кнопки нет, высоко поднимают пин KEY (на платах, где он выведен, это тридцать четвёртая нога чипа): высоко — режим AT, внизу — обычный; подавать туда можно и 5 В — вход переживает, но я всё равно беру 3,3 В, привычка после делителя из прошлого урока. Светодиод не соврёт: в режиме AT он мигает лениво, раз в две секунды; в режиме данных при поиске пары — быстро, несколько раз в секунду.
Самое коварное — скорость. В режиме AT HC-05 всегда говорит на 38400 бод, независимо от того, какая скорость настроена для данных. Я сделал всё по инструкции, но оставил bt.begin(9600) из прошлого урока про HC-05 — и день читал тишину, решая, что модуль сдох. Не сдох: 38400. В скетче-конфигураторе ниже эта цифра стоит не для красоты.
Вторые ворота — окончание строки. Команда уходит с \r\n на хвосте, то есть с возвратом каретки и переводом строки вместе: в мониторе Arduino IDE это настройка Both NL & CR — те же настройки, что мы разбирали в первом уроке про монитор порта. Без \r\n модуль молчит так же, как на неверной скорости, и отличить одну тишину от другой на глаз невозможно. Ответы короткие: OK, ERROR(0), а на вопросы со знаком вопроса — строка значения вида +NAME:HC-05 и следом OK.
Когда модуль молчит, я проверяю в одном порядке — от самого частого к редкому. Скорость: в мониторе выставлено 38400? Окончание: Both NL & CR, а не просто NL? Режим: светодиод мигает лениво, раз в две секунды? Питание: модуль горит стабильно, без подмигиваний? Четыре чекбокса закрывают девять из десяти случаев тишины — я не раз чинил «мёртвые» модули у знакомых, не касаясь схемы, одним этим списком.
| Команда | Ответ | Что делает |
|---|---|---|
| AT | OK | проверка живости: первое, что шлём после входа в режим AT |
| AT+NAME? | +NAME:HC-05, OK | текущее имя; AT+NAME=NovoeImya — сменить |
| AT+PSWD? | +PSWD:1234, OK | PIN пары; AT+PSWD=5678 — сменить (на части прошивок аргумент в кавычках) |
| AT+UART? | +UART:9600,0,0, OK | скорость режима данных; AT+UART=9600,0,0 — задать |
| AT+ORGL | OK | заводские настройки: имя HC-05, PIN 1234 |
| AT+RESET | OK | перезагрузка модуля с новыми настройками |
| AT+VERSION? | +VERSION:..., OK | версия прошивки — полезно при диагностике клона |
| AT+RMAAD | OK | стереть список спаренных устройств |
Конфигуратор одним скетчем
Щёлкать команды руками через монитор годится для первого раза, но при серийной заливке — у меня четыре модуля — удобнее скетч: в setup() он сам шлёт цепочку команд, собирает ответы и печатает в Serial отчёт. Ядро — функция at(): отправляет команду, следом \r\n, и читает ответ с таймаутом на millis() — механизм тот же, что в уроке про millis вместо delay. Таймаут — 800 мс: модуль отвечает за десятки миллисекунд, и если за 800 он не сказал ничего, функция честно печатает, что модуль молчит.
Разбор ответа здесь примитивен: печать «команда -> ответ» в монитор достаточна для человека. Но если захотите, чтобы скетч сам принимал решения по ответам, пригодится тот же приём, что в уроке про командный парсер: startsWith и indexOf по строке ответа. И предупреждение, прежде чем менять скорость: SoftwareSerial стабильно принимает до 38400, поэтому AT+UART=115200,0,0 на Uno — способ потерять связь с модулем. Оставляйте 9600.
Порядок после настройки тоже сценарий. Сначала AT+RESET — без перезагрузки часть версий держит старые параметры до выключения. Потом переоткрыть пару: телефон держит старую сессию по имени, и после смены имени модуль из списка не исчезает, пока не перечитать список — я честно думал, что команда не сработала, а просто не обновил поиск. И контрольный вопрос: AT+NAME? в режиме AT должен показать новое значение — доверяй, но сверяй.
#include <SoftwareSerial.h> SoftwareSerial bt(10, 11); // RX, TX // Шлёт команду и печатает ответ. Таймаут - на millis(), не на delay.void at(String komanda) { bt.print(komanda); bt.print("\r\n"); // обязательный хвост: CR и LF Serial.print(komanda); Serial.print(" -> "); String otvet = ""; unsigned long nachalo = millis(); while (millis() - nachalo < 800) { if (bt.available() > 0) { otvet += (char)bt.read(); nachalo = millis(); // байты идут - таймаут отсчитывается заново } } otvet.trim(); if (otvet.length() > 0) { Serial.println(otvet); } else { Serial.println("(molchit: prover 38400 i NL&CR)"); }} void setup() { Serial.begin(9600); bt.begin(38400); // скорость режима AT, всегда 38400 delay(600); // модуль выходит из сброса at("AT"); // ждём OK - дальше идти смысла нет at("AT+NAME=BanyaGrad"); at("AT+PSWD=1234"); at("AT+UART=9600,0,0"); // скорость данных: не выше 38400 для SoftwareSerial at("AT+RESET"); // перезагрузка с новыми настройками} void loop() {}Тренажёр: модуль в кармане
Bluetooth в движке не поддержан, поэтому симулятор идёт с другой стороны: скетч играет роль самого модуля. Тумблер D2 — это пин KEY: вверх — режим AT, вниз — режим данных. В режиме AT печатайте AT, AT+NAME?, AT+NAME=BanyaGrad, AT+PSWD=5678, AT+UART?, AT+ORGL — «модуль» отвечает OK, ERROR(0) или строкой +NAME:... Опустите тумблер — и те же строки уйдут «в эфир» с пометкой peredacha: это прозрачный режим данных, где настройки недостижимы. Окончание строки эмуляция не проверяет — на реальном модуле Both NL & CR обязателен.
За кадром остаётся радиочасть: настоящий модуль отвечает по RFComm-каналу с паузами в десятки миллисекунд, и в этом смысле таймаут 800 мс из конфигуратора — не перестраховка, а рабочая цифра. Тренажёр же проверяет главное отличие AT-диалога от командного парсера прошлых уроков: у модуля свой словарь, свои два режима и ноль вежливости к опечаткам — ERROR(0) вместо развёрнутого диагноза.
- Проведите в симуляторе весь цикл: смените имя, проверьте вопросом, верните заводские AT+ORGL и сверьте AT+NAME? — имя снова HC-05.
- Разберите функцию at() из конфигуратора: почему таймаут отсчитывается заново на каждом принятом байте и что напечатает at(), если модуль отвечает медленно, тремя кусками.
- Пересчитайте на 38400 бод: сколько миллисекунд едет команда AT+NAME=BanyaGrad с окончанием — 18 символов — и с запасом ли выбран таймаут 800 мс.
- На реальной плате войдите в режим AT кнопкой EN, выставьте в мониторе 38400 и Both NL & CR, отправьте AT и добейтесь OK, прежде чем шлёт что-то ещё.
- Подумайте, что сломается, если два модуля в комнате зовутся одинаково: где телефон берёт имя для списка и почему AT+NAME закрывает вопрос раз и навсегда.
- Режим данных и режим AT — разные вещи: в паре модуль прозрачен, AT-команды улетают собеседнику как текст
- Вход в AT: кнопка EN до подачи питания или пин KEY высоко; светодиод мигает раз в две секунды — значит, вы внутри
- Скорость режима AT всегда 38400, окончание строки — CR и LF (Both NL & CR); иначе модуль молчит безо всяких ошибок
- Базовый набор: AT, AT+NAME, AT+PSWD, AT+UART, AT+ORGL, AT+RESET; настройки живут в модуле и переживают отключение питания
- Скетч-конфигуратор в setup(): at() шлёт команду с CR и LF и собирает ответ с millis-таймаутом; скорость данных оставьте на 9600
- 1. Почему AT-команды не работают в установленной паре?
- 2. Какая скорость у HC-05 в режиме AT?
- 3. Скорость верная, но монитор отправляет команду без окончания строки. Что ответит модуль?
- 4. Что делает AT+ORGL?
- 5. Строка AT+NAME=X отправлена при опущенном пине KEY — модуль в режиме данных. Куда она попадёт?
Частые вопросы по теме урока
- Почему AT-команды не работают в установленной паре?
- Режим данных — прозрачный провод между скетчем и телефоном. Команды настройки принимает только режим AT, в который входят кнопкой EN или пином KEY. Модуль в паре прозрачен: байты идут собеседнику, а не командуют модулем
- Какая скорость у HC-05 в режиме AT?
- Режим AT живёт на 38400 бод всегда: даже если данные настроены на 9600. Самая частая причина «мёртвого» модуля — bt.begin(9600) в попытке поговорить с AT-режимом. 38400 бод — всегда, независимо от скорости данных
- Скорость верная, но монитор отправляет команду без окончания строки. Что ответит модуль?
- HC-05 ждёт хвост из CR и LF — настройка Both NL & CR в мониторе. Без него модуль молчит, и эту тишину глазами не отличить от тишины на неверной скорости. Ничего: без CR и LF команда не принимается, тишина как на неверной скорости
- Что делает AT+ORGL?
- AT+ORGL — откат к заводским значениям: имя HC-05, PIN 1234. Список пар стирает AT+RMAAD, перезагрузка — AT+RESET. Возвращает заводские настройки: имя HC-05, PIN 1234
- Строка AT+NAME=X отправлена при опущенном пине KEY — модуль в режиме данных. Куда она попадёт?
- В режиме данных модуль — прозрачный провод: всё, что влетает с одной стороны, вылетает с другой. Парсер на той стороне честно получит строку AT+NAME=X как обычный текст. В эфир как данные: собеседник получит текст AT+NAME=X