Часы в щитке на даче отработали год и ушли на минуту — пустяк, пока полив не стал запускаться на двадцать минут раньше по вашему ощущению, а график в журнале перестал сходиться с фотографиями закатов. Роутера там нет и не будет: Wi-Fi вариант с ESP32 разобран в уроке про NTP и RTC, а здесь сеть заменить нечем. Зато в кармане лежит телефон — а телефон точен: его время подводится по сети оператора, и расхождение с истиной вы не заметите никогда. Здесь строю канал сверка-подвод между смартфоном и DS3231 без единого метра кабеля: Bluetooth-модуль HC-05, приложение-терминал и протокол из одной буквы.
Задача распадается на две половины. Первая — поверить часы: спросить у платы, сколько сейчас времени, и сравнить с экраном телефона. Вторая — поправить: отправить команду подвода так, чтобы дата в чипе не пострадала. Обе половины по проводу через USB мы уже делали в уроке про Serial-команду SET — здесь тот же контракт переезжает в радиоэфир, и заодно обсуждаем, где этот вариант лучше NTP, а где хуже.
Почему телефон и почему Bluetooth
Телефон как эталон — не компромисс, а честный стандарт для бытовой автоматики. Мой замер в полевом тесте дрейфа сверялся именно с телефоном, и погрешность такого эталона на дистанции минуты никого не волнует: DS3231 с её компенсацией уходит на минуту в год, как посчитано в уроке про точность и компенсацию, а телефон уходит меньше. Сверка нужна не для науки, а чтобы поймать крупные события: севшую батарейку, ручную подводку мимо графика, моргание питания после которого чип стартовал с 2000 года.
Канал выбран по экономике. HC-05 — копеечный модуль, живёт на 5 В по питанию, а дальность держит порядка десяти метров по прямой — для щитка на стене это с запасом. Дата-режим модуля из коробки — 9600 бод: SoftwareSerial на такой скорости работает ровно, о его потолках я писал в уроке про второй UART. Со стороны телефона ставьте приложение-терминал с кнопками-макросами: одна кнопка — «спросить время», вторая — «подвести». Пара модуля — стандартные 1234 или 0000, соединение поднимается без единой строки кода в телефоне.
Единственное место, где нельзя спешить, — электрика. Питание модуля берите с 5-вольтовой линии платы: в соединении он тянет порядка 30-40 мА, и 3,3-вольтовый вывод Uno с его потолком в 50 мА лучше не нагружать. А вот логика модуля трёхвольтовая: линия TX платы приходит на RX модуля через делитель из резисторов 1 кОм и 2 кОм. Направление RX платы к TX модуля соединяют напрямую — там модуль отдаёт 3,3 В, и Uno их честно читает как HIGH.
#include <Wire.h>#include <RTClib.h>#include <SoftwareSerial.h> RTC_DS3231 rtc;SoftwareSerial bt(4, 3); // RX платы = D4 (TX модуля), TX платы = D3 (через делитель на RX модуля) void pechatVremya(DateTime t) { if (t.hour() < 10) bt.print("0"); bt.print(t.hour()); bt.print(":"); if (t.minute() < 10) bt.print("0"); bt.print(t.minute()); bt.print(":"); if (t.second() < 10) bt.print("0"); bt.println(t.second());} void podvod(int ch, int mi) { DateTime now = rtc.now(); // дату храним, правим только время rtc.adjust(DateTime(now.year(), now.month(), now.day(), ch, mi, 0)); bt.print("OK podvod: "); pechatVremya(rtc.now());} void setup() { Serial.begin(9600); bt.begin(9600); // дата-режим HC-05 по умолчанию - 9600 бод if (rtc.begin() == false) { bt.println("DS3231 ne najden: SDA A4, SCL A5"); while (1) {} } bt.println("Chasy na svyazi. T0729 - podvod, S - sverka");} void loop() { if (bt.available() > 0) { String s = bt.readStringUntil(10); s.trim(); if (s.startsWith("T")) { String rest = s.substring(1); if (rest.length() >= 4) { int ch = rest.substring(0, 2).toInt(); int mi = rest.substring(2, 4).toInt(); if (ch >= 0 && ch <= 23 && mi >= 0 && mi <= 59) { podvod(ch, mi); } else { bt.println("Otkaz: chasy 0-23, minuty 0-59"); } } else { bt.println("Format: T0729"); } } else if (s.startsWith("S")) { bt.print("Sverka: "); pechatVremya(rtc.now()); // сравните со экраном телефона } } delay(50);}Протокол одной буквы и проверка руками
Протокол нарочно примитивный. Буква T — глагол подвода, за ней четыре цифры часа и минуты; буква S — запрос сверки, ответ уезжает строкой вида «15:42:07». Почему не JSON и не полные даты: команду набирают пальцами на экране телефона, и каждый лишний символ — шанс промахнуться. Секунды в подводе я не тащу сознательно: нажатие кнопки в приложении всё равно отправит строку с задержкой в полсекунды-секунду, и мнимая точность лишь путает. Механика validate-и-adjust здесь та же, что в уроке про установку времени: сначала разбор и диапазоны, потом одна запись, потом эхо — дата при этом сохраняется из текущего снимка, чтобы подвод не стёр число и месяц.
Эхо-ответ — не украшение, а половина пользы канала. Нажмите в приложении кнопку сверка: телефон покажет, например, «Sverka: 15:42:07», и вы глазами сравните с часами на его экране. Разница в пределах секунды — часы здоровы; разница в минуты — повод заглянуть в историю про сработку в 18:30, где расследование инцидента началось ровно с расползающихся часов. После подвода повторите сверку ещё раз: до, действие, после — три строки в терминале стоят целого вечера догадок, что именно записалось в чип.
Прогоните модель по сценарию реальной сверки. Сначала дайте часам покрутиться с уведённым вверх ползунком: в строках [ЧАСЫ] растёт метка ushod — так выглядит уход, который вы не видите глазами. Затем отправьте T0729: подвод пройдёт, счётчик сбросится, LED мигнёт — это то же подтверждение, которое на плате уезжает строкой OK в приложение. Кнопка D2 сработает как запрос сверка из приложения: одна строка — и вы видите, сколько сейчас у платы. Весь контракт — спросил, поправил, проверил — умещается в три нажатия.
На настоящей плате добавьте только три вещи. Первая — делитель на линии RX модуля, без него каждый запуск лотерея. Вторая — отдельная кнопка-макрос в приложении на строку T: набирать четыре цифры руками вы быстро устанете. Третья — правило частоты: подвод по Bluetooth нужен после пропажи питания и раз в несколько месяцев, а не каждый день; о том, как встроить суточную сверку в связке с сетью, говорит уже упомянутый NTP-урок, а слепая запись по кругу портит журнал метками-дублями.
И про границы канала. Bluetooth в этом сценарии — средство подвода, а не телеметрия: десяток команд в месяц — его нормальный рацион, поток байтов через SoftwareSerial с буфером в 64 байта на Uno кончится слезами. И не ведите часы по таймеру сами: плате нельзя звонить в чип по расписанию без спроса — та же спорная запись из NTP-урока, только с телефоном в роли источника. Сверка остаётся ручной процедурой, и в этом её сила: перед вами живая цифра, а не тихий фоновый процесс.
| Способ подвода | Что нужно | Когда беру |
|---|---|---|
| Кнопки на модуле | две тактовые кнопки минус-час плюс-минута | тест на столе, пока крышка открыта |
| Serial по USB | ноутбук с IDE и кабелем | сборка и пусконаладка в мастерской |
| Bluetooth и телефон | HC-05, делитель 1к/2к, приложение-терминал | щиток за стеной, руки заняты, сети нет |
| NTP по Wi-Fi | ESP32 или плата с сетью, роутер | дом, где интернет работает всегда |
Куда расширять. Если устройств в щитке несколько, добавьте в протокол адресный префикс: T2 0729 — подвод вторым часам. Разбор остаётся тем же, добавляется один шаг: цифра адреса перед глаголом, и каждый узел отвечает только на свои команды. Тот же приём открывает дорогу другим буквам: F — спросить показания датчика, B — запросить заряд резервной батарейки, R — перечитать вчерашний журнал. Протокол растёт линейно, и каждая буква живёт по контракту из этого урока: разбор, диапазоны, действие, эхо.
Про журнал сверок скажу отдельно: каждая команда S и каждый подвод — строка с меткой времени в Serial. Через полгода таких строк видно всё: как часто часы просятся под руку, сколько насчитал уход между подводками, не было ли среди зимы рывка на сутки — след севшей батарейки или моргнувшего питания. Без этого списка вы управляете часами по вере; с ним — по цифрам, и разговор с автоматикой становится скучным, как и положено.
- 1. Почему линию TX платы к RX модуля ведут через делитель 1к/2к?
- 2. Какая скорость у HC-05 в дата-режиме из коробки?
- 3. Что делает команда S в протоколе этого урока?
- 4. Почему подвод принимает только часы и минуты без секунд?
- 5. Когда Bluetooth-подвод предпочтительнее NTP-синхронизации?
- Телефон — честный эталон для бытовой автоматики: его время подводится сетью оператора
- HC-05: питание 5 В, логика 3,3 В, делитель 1к/2к на RX обязателен, дата-режим 9600 бод
- Протокол одной буквы: T0729 — подвод, S — сверка; разбор, диапазоны, одна запись, эхо
- Дату при подводе берите из текущего снимка rtc.now() — правится только время
- Канал для объектов без сети: спросил, поправил, проверил — три нажатия в приложении
Частые вопросы по теме урока
- Почему линию TX платы к RX модуля ведут через делитель 1к/2к?
- RX HC-05 рассчитан на 3,3 В, а TX Uno отдаёт полные пять. Делитель 1 кОм и 2 кОм даёт на входе модуля 3,3 В. Обратное направление прямой провод — модуль отдаёт 3,3 В, Uno читает их как HIGH. Логика модуля трёхвольтовая, а пин отдаёт пять вольт
- Какая скорость у HC-05 в дата-режиме из коробки?
- Дата-режим по умолчанию — 9600 бод, и SoftwareSerial на ней работает ровно. 38400 — скорость AT-режима, в которой модуль настраивают через команды. 9600 бод
- Что делает команда S в протоколе этого урока?
- S — запрос сверки: плата отвечает строкой вида 15:42:07, и вы сравниваете её с экраном телефона. Автоматической синхронизации по Bluetooth в этом уроке нет — подвод всегда руками. Возвращает строку с текущим временем для сверки глазами
- Почему подвод принимает только часы и минуты без секунд?
- Нажатие кнопки в приложении доезжает до платы за доли секунды с переменной задержкой. Секундная точность в таком канале фиктивна, поэтому протокол честно ограничен минутами, а запись обнуляет секунды. Отправка с телефона всё равно задерживается, и секундная точность мнимая
- Когда Bluetooth-подвод предпочтительнее NTP-синхронизации?
- NTP требует сети и Wi-Fi-платы, Bluetooth — только модуля и телефона в руках. На даче или в гараже без интернета это единственный автоматизированный канал подвода; там, где сеть есть, точнее и беспечнее NTP. На объекте без сети, где ESP32 и роутеру неоткуда взять время