Содержание
- Назначение и принцип работы
- Технические характеристики и возможности
- Подключение к Ардуино
- Примеры использования
- Выводы
- FAQ
Назначение и принцип работы
НС-12 - беспроводной приемник и передатчик цифрового сигнала на расстоянии. Его задача передать сигнал, никак его не меняя, в его оригинальном виде по воздуху с одного устройства на другое (напишем даже “на другие”, так как приемников может быть множество). Для этого у HC-12 есть два сигнальных пина: один для входящего сигнала и второй для приходящего. Если на входящую ногу одного радиомодуля подавать единицу, на выходящих ногах всех подобных радиомодулей в радиусе приема появится эта самая единица. Две ноги - два разнонаправленных канала, что же это напоминает? Конечно же наш любимый UART! Именно для него HC-12 подходит как нельзя лучше и для работы с этим интерфейсом разрабатывался, на это даже намекают сигнальные пины, гордо носящие стандартные для интерфейса названия: RX и TX. Однако, повторюсь, сигнал передается в неизменном виде и никто не мешает вам использовать модуль, скажем, с рубильником на одной стороне и лампочкой на другой.
Что же он из себя представляет? Физически это весьма компактная плата 15х28 мм, не считая припаянных ножек и антенны.
К слову, антенну можно использовать внешнюю, более мощную, для нее на плате имеется специальный разъем. Особенно эта возможность актуальна, если сам модуль планируется спрятать в металлический корпус.
На корпусе имеются подписанные пины, назначение которых очевидно из названий:
- VCC - питание +5В,
- GND - “земля”,
- RXD- пин входящего сигнала, соединяется с TX контроллера,
- TXD - пин приходящего сигнала, соединяется с RX контроллера,
- SET - пин перевода в режим настроек, пока на нем высокий уровень, модуль работает в режиме приемника-передатчика, для чего он притянут к питанию встроенным резистором на 10КОм, для перевода модуля в режим настроек нужно установить на пине низкий уровень.
Далее мы разберемся, как и какие настройки можно менять, а так же нужно ли это делать вообще.
Технические характеристики и возможности
- Рабочая частота: от 433,4 до 473,0 МГц, разбита на 100 “шагов”, устанавливается в настройках,
- Дальность передачи информации: до 1800 м на открытом пространстве при оптимальных условиях,
- Мощность передатчика: до 100 мВт, задается в настройках в виде одного из 8 уровней,
- Четыре режима работы (описание ниже),
- Потребляемый ток: от 3,6 мА до 16 иА, в зависимости от режима работы.
Почти все перечисленные параметры меняются при помощи установок, которые задаются в виде AT-команд. Для этого модуль переводится в состояние настройки путем подачи на пин SET нулевого уровня. Примерно через 80 мс можно начинать “общение”. После установки новых параметров снимаем нулевой уровень с пина SET, модуль переходит в рабочий режим примерно в течение 80 мс. Новые установки сохраняются в энергонезависимой памяти HC-12 и не теряются после выключения питания.
Перечислим, для примера, лишь некоторые основные команды.
“AT” - “приветствие”, работоспособный модуль тут же ответит “OK”, рекомендуется начинать с этой команды работу, чтобы убедиться, что HC-12 на связи и хорошо себя чувствует,
“AT-Bxxxx” - команда изменения скорости передачи данных, возможные значения от 1200 до 115200 с удвоением на каждом шагу, по умолчанию 9600. Обратите внимание, после смены скорости дальнейшее общение с модулем возможно только на вновь заданном битрейте. Разумеется, чем выше скорость, тем ниже надежность и меньше расстояние передачи, учитывайте это при проектировании связи.
“AT+Cxxxx” - команда изменения канала связи (несущей частоты) от 1 до 127. Шаг канала 400 КГц. Удобен для организации нескольких независимых сетей в одном пространстве, достаточно лишь развести их по частотам не менее чем на 5 шагов.
“AT-FUxx” - команда выбора режима работы с 1 по 4: FU1 - экономичный режим, потребляемый ток 3,6 мА. FU2 - сверхэкономичный режим, потребляемый ток 80 мкА. FU3 (по умолчанию) - скоростной режим, потребляемый ток 16 мА. FU4 - дальнобойный режим, потребляемый ток 16 мА, при нем появляются серьезные ограничения: скорость только 1200, не более 60 байт за передачу, интервал передачи пакетов не менее 2 сек. Третий режим самый универсальный, оптимальный и наиболее востребованный, остальные рекомендуются только в специфических случаях работы.
“AT-Px” - команда выбора мощности от 1 до 8. По умолчанию стоит максимальная, уменьшение сокращает потребление и нагрев чипа.
“AT-DEFAULT” - сброс настроек по умолчанию, самая полезная команда.
Для большинства применений настройки по умолчанию являются самыми оптимальными. Тюнинговать следует лишь в случаях если:
- слишком много помех на первом частотном канале,
- нужна одновременная работа двух и более независимых сетей,
- требуется максимальная дальность связи в ущерб скорости, нет возможности сократить расстояние,
- требуется сверхнизкое потребление энергии, когда частая замена элемента питания затруднительна.
Как уже говорилось, все модули HC-12 одновременно принимают сигнал каждого из них в радиусе приема. Это позволяет организовывать не только передачу типа точка-точка, но и создавать простые сети, по примеру RS-485, только без проводов. Разумеется, при этом нужно учитывать специфику радиосвязи, а именно продумать повышенную помехоустойчивость, но в целом, все выглядит очень похоже.
Где купить ардуино датчики?Купить Arduino датчики можно в нашем магазине 3DIY с доставкой по всей России!
Подключение к Arduino
Схема подключения предельно проста:
- VCC - 5V,
- GND - GND,
- RX - TX,
- TX - RX,
- SET - не задействуется, если не планируются настройки, в ином случае на любой свободный пин.
Для примеров и демонстрации работы подключим все пины, кнопку и светодиод, а так же небольшой конденсатор, для сглаживания колебания питания при сеансах связи.
Примеры использования
Для начала создадим простейшее соединение точка-точка. Зальем одинаковую программу на два одинаково собранные устройства. Нажимая кнопку на первом, будем включать светодиод на втором и наоборот.
#define LED 13 // светодиод #define BUT 2 // кнопка #define SET 6 // SET byte but[2]; void setup() { pinMode(BUT, INPUT_PULLUP); pinMode(LED, OUTPUT); pinMode(SET, OUTPUT); digitalWrite(SET, HIGH); Serial.begin(9600); } void loop() { if (Serial.available()) { byte a = Serial.read(); if (a == '1') { // если пришла команда на включение, зажигаем светодиод digitalWrite(LED, HIGH); } else if (a == '5') { // если на выключение - выключаем digitalWrite(LED, LOW); } } but_read(); // отслеживание нажатий кнопки } void but_read() { static unsigned long timerT; if ((timerT + 100) > millis()) return; but[0] = but[1]; but[1] = digitalRead(BUT); if (but[0] && !but[1]) Serial.write("1"); // кнопка нажата, отправляем 1 if (!but[0] && but[1]) Serial.write("5"); // кнопка отжата, отправляем 5 timerT = millis(); }
Полностью асинхронная, ситуационная схема работы: заметили нажатие кнопки - отправили команду длиной в один байт на включение, кнопку отпустили - команду на выключение.
Все работает правильно, однако небезупречно. Довольно быстро выясняется, что светодиоды включаются при нажатии кнопок не всегда и выключается тоже не очень стабильно. Да, радиосвязь часто дает сбои даже на таком коротком расстоянии и малой скорости. Кроме того, если нажать кнопки одновременно, точно ничего не сработает, потому что получится так называемая коллизия - сложение двух сигналов, но это свойственно и для проводных устройств.
Можно ли повысить надежность соединения исключительно программным способом? Давайте попробуем! Для этого воспользуемся старой доброй избыточностью.
На этом месте должна была начаться длинная и умная лекция про коды Хемминга и прочие коррекции ошибок, но здесь мы этим заниматься не будем. Желающие могут всегда углубить свои знания в этом вопросе на сторонних ресурсах, например, разобравшись с тем, как хранятся данные в системе RAID второго уровня. Нам же для передачи нескольких байт достаточно просто продублировать сообщение несколько раз, скажем, три, и надеяться, что в целости дойдет хотя бы одно. Для этого сообщение сделаем чуть длиннее одного байта, а именно четыре: стартовый, номер дубля, собственно команда и стоповый. Благодаря первому и последнему определим тело пакета, с помощью номера дубля узнаем, пришло ли оно сразу, пропустив все лишнее мимо ушей, а команду используем по назначению. Логично было бы добавить в пакет контрольную сумму, но она больше нужна для исключения искажения данных, чем для повышения вероятности приема, что требуется нам. Если важно не перепутать команды, то следует добавить и контрольную сумму тоже.
Заливаем на устройства новую программу.
#define LED 13 // светодиод #define BUT 2 // кнопка #define SET 6 // SET byte but[2]; byte out_mail[4] = {0x10, 0, 0, 0x20}; // исходящий пакет: старт, номер копии, команда, стоп byte in_mail[4]; // входящий пакет void setup() { pinMode(BUT, INPUT_PULLUP); pinMode(LED, OUTPUT); pinMode(SET, OUTPUT); digitalWrite(SET, HIGH); Serial.begin(9600); } void loop() { if (Serial.available()) { for (byte i = 0; i < 3; i++) in_mail[i] = in_mail[i + 1]; in_mail[3] = Serial.read(); if (in_mail[0] == 0x10 && in_mail[3] == 0x20) { // пришло полное сообщение if (in_mail[2] == 0x01) { // если пришла команда на включение, зажигаем светодиод digitalWrite(LED, HIGH); } else if (in_mail[2] == 0x05) { // если на выключение - выключаем digitalWrite(LED, LOW); } if (in_mail[1] < 2) { // если копия не последняя, сбрасываем все последующие while (Serial.available()) { byte a = Serial.read(); } } } } but_read(); // отслеживание нажатий кнопки } void but_read() { static unsigned long timerT; if ((timerT + 100) > millis()) return; but[0] = but[1]; but[1] = digitalRead(BUT); if (but[0] && !but[1]) { // кнопка нажата, отправляем 1 out_mail[2] = 0x01; send_mail(); } if (!but[0] && but[1]) { // кнопка отжата, отправляем 5 out_mail[2] = 0x05; send_mail(); } timerT = millis(); } void send_mail() { // отправка сообщения в трех экземплярах for (byte i = 0; i < 3; i++) { out_mail[1] = i; for (byte ii = 0; ii < 4; ii++) { Serial.write(out_mail[ii]); } delay(5); // ждем пока уйдет } }
Теперь сбоев практически нет, надежность повысилась в разы. Более того, если собрать и прошить третье устройство, четвертое и так далее, стабильно работать будет вся связка.
Как можно усовершенствовать систему? Избавиться от delay(), добавить контрольную сумму, как уже говорилось выше, развести функции опроса кнопок и отправки данных. Если же существует вероятность одновременного использования двух и более связанных устройств, следует создать систему последовательного опроса по типу RS-485, что физически сделать даже проще, чем в проводном варианте.
И последний штрих. В реальных условиях может потребоваться предварительная проверка модуля на его наличие и работоспособность. Сделать это можно путем перевода модуля в режим установки при включении, отправки на него команды “AT” и получения ответа “OK”. Если ответ пришел, можно не сомневаться, что все готово к работе. Приведу небольшой пример, как это можно сделать.
#define HC12 Serial // указываем сериал для обмена с HC-12 #define SET 6 // пин установки режима модуля (0-настройка, 1-работа) String _response = ""; // Переменная для хранения ответа модуля void setup() { pinMode(SET, OUTPUT); digitalWrite(SET, HIGH); Serial.begin(9600); // sendATCommand("AT+B9600", true); do { _response = sendATCommand("AT", true); // _response.trim(); // Убираем пробельные символы в начале и конце } while (_response.indexOf("OK") == -1); // Не пускать дальше, пока модем не вернет ОК } void loop() { HC12.print("1234"); // теставая отправка информации delay(1000); } String sendATCommand(String cmd, bool waiting) { String _resp = ""; // Переменная для хранения результата digitalWrite(SET, LOW); // устанвливаем в режим команды delay(100); // ждем пока "устаканится" HC12.println(cmd); // Отправляем команду модулю if (waiting) { // Если необходимо дождаться ответа... _resp = waitResponse(); // ... ждем, когда будет передан ответ } digitalWrite(SET, HIGH); // устанвливаем в режим работы delay(100); // ждем пока "устаканится" return _resp; // Возвращаем результат. Пусто, если проблема } String waitResponse() { // Функция ожидания ответа и возврата полученного результата String _resp = ""; // Переменная для хранения результата long _timeout = millis() + 2000; // Переменная для отслеживания таймаута (2 секунды) while (!HC12.available() && millis() < _timeout) {}; // Ждем ответа 10 секунд, если пришел ответ или наступил таймаут, то... if (HC12.available()) { // Если есть, что считывать... _resp = HC12.readString(); // ... считываем и запоминаем } else { // Если пришел таймаут, то... _resp = "ERROR"; // Serial.println("Timeout..."); // ... оповещаем об этом и... } return _resp; // ... возвращаем результат. Пусто, если проблема }
Выводы
HC-12 - недорогое, но простое и достаточно надежное приспособление для беспроводного обмена данными между контроллерами, а также между контроллером и другим устройством, например, компьютером или датчиком. Удобно применять для создания сети без прокладки кабеля и/или для подключения автономных и мобильных точек. Важно соблюдать рекомендации по питанию, использовать оптимальные настройки, следить за покрытием и помехами, результатом будет стабильная устойчивая связь без проводов.
FAQ
1. Какие факторы могут мешать передаче данных и как свести их к минимуму?В идеале между точками не должно быть толстых стен, крупных металлических предметов и прочих экранирующих препятствий. Отрицательно влиять на качество могут помехи, источником которых могут выступать электромоторы и прочие мощные электроприборы.
2. Как можно уменьшить влияние электропомех?
Частично можно попробовать сдвинуть частоту в более чистый диапазон. Просканировать эфир при помощи осциллографа или логического анализатора на ножке TX модуля, если много шумов, сдвинуть на 5 каналов, сканировать еще и так до максимально тихой частоты. И максимально изолировать источники помех.
3. Как аппаратно улучшить качество связи?
Использовать внешнюю антенну, достаточно мощный и стабильный блок питания, использовать оптимальные настройки скорости, мощности и режима.
4. Можно ли использовать HC-12 с устройствами, поддерживающими протокол UART, и если да, то как.
Можно. Требуется лишь, чтобы скорость передачи устройства была согласована с HC-12, в остальном, на физическом уровне, связь ничем не отличается от проводной.
5. Чем отличаются HC-12 и HC-11? Совместимы ли они?
Отличаются трансивером на борту, SI4463 у HC-12 и CC1101 у HC-11. С точки зрения подключения, настройки и работы разницы между ними нет, но между собой они несовместимы. То есть HC-11 не видит HC-12 и наоборот, что печально и следует учитывать при подготовке проекта, покупать полным комплектом либо те, либо другие. Лучше всего использовать в одном проекте устройства из одной партии.