Русский
Русский
English
Статистика
Реклама

Nrf24l01+

Победа над nRF24L01 на три шага ближе

25.02.2021 00:07:45 | Автор: admin

Многие испытывают трудности при соединении по эфиру радиомодулей nRF24L01. Об этом свидетельствует тема на форуме Амперки, открытая в конце 2014г. За пять с небольшим лет в теме накопилось более 120(!) страниц. Это при том, что автор темы не просто обозначил проблему, а поделился своим трехнедельным опытом победного для него боя. Кроме того, он тут же в первом сообщении создал навигатор по страницам темы, где приводит ссылки на решения проблемы другими. Этот своеобразный путеводитель постоянно обновляется.



Я тоже не из тех счастливчиков, которым легко удалось связать радиомодули. Ниже мой подход к решению проблемы.



Модули nRF24L01 работают в полудуплексном режиме. Это как разговор порации: каждый из корреспондентов в один момент времени либо говорит, либо слушает. То есть, каждый из двух узлов работает в режиме и приемника и передатчика: передатчик, отправив сообщение ждет на подтверждение приема сообщения со стороны приемника.



Как правило, все тесты, которые мне встречались в Инете, сводятся к проверке работы и качества связи пары радиомодулей в полнофункциональном режиме, когда передатчик, послав пакет, ждет на подтверждение приема пакета приемником.



Я же разделил эту задачу на несколько простых задачек. Вначале модули проверяются на работоспособность и правильность подключения (шаг 1), затем один из пары работающих радиомодулей тестируется на работу в режиме передатчика без ожидания отклика с приемника (шаг 2) и последний этап улучшение качества связи в этой связке передатчик-приемник (шаг 3).



Итак ...





Шаг 1



Загрузить в контроллер платы Ардуино скетч сканера эфира, который можно найти среди примеров Arduino IDE: Файл -> Примеры -> RF24 -> scanner. Ниже под спойлером есть этот скетч с несущественным изменением. В нем изменено время между стартом и остановкой сканирования одного канала с 128 мксек на 512 мксек. Увеличение времени позволило за один цикл выявлять бОльше источников помех и сигналов. Это равнозначно замене результата измерений в канале на сумму результатов в этом канале за четыре цикла сканирования эфира до изменения времени задержки. При этом, время прохода всего прослушиваемого диапазона сканером увеличилось несущественно: примерно с 8-ми до 10-ти сек.



В разных скетчах адрес канала в командах приводится в разных форматах: в одних ...(0x6f), в других ...(112). Перевод с одного формата в другой станет понятным с примера перевода. Например, для (0x1а) это: (1+1)*16 + а = (1+1)*16 + 10 = 42. Отсчет каналов начинается с частоты 2,4 ГГц, далее идет увеличение частоты на 1 МГц с увеличением номера канала на 1.



скетч сканера эфира
/*Победа над nRF24L01: на три шага ближе, сканер эфираhttp://personeltest.ru/aways/habr.com/ru/post/476716/*//*  Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>  This program is free software; you can redistribute it and/or  modify it under the terms of the GNU General Public License  version 2 as published by the Free Software Foundation.*//**   Channel scanner   Example to detect interference on the various channels available.   This is a good diagnostic tool to check whether you're picking a   good channel for your application.   Inspired by cpixip.   See http://arduino.cc/forum/index.php/topic,54795.0.html*/#include <SPI.h>#include "nRF24L01.h"#include "RF24.h"#include "printf.h"//// Hardware configuration//// Set up nRF24L01 radio on SPI bus plus pins 9 & 10RF24 radio(9, 10); //Arduino UNO//// Channel info//const uint8_t num_channels = 128;uint8_t values[num_channels];//// Setup//void setup(void){  //  // Print preamble  //  Serial.begin(57600);  Serial.println("Scanner Air On");  printf_begin();  //  // Setup and configure rf radio  //  radio.begin();  radio.setAutoAck(false);  // Get into standby mode  radio.startListening();  radio.stopListening();  // Print out header, high then low digit  int i = 0;  while ( i < num_channels )  {    printf("%x", i >> 4);    ++i;  }  printf("\n\r");  i = 0;  while ( i < num_channels )  {    printf("%x", i & 0xf);    ++i;  }  printf("\n\r");}//// Loop//const int num_reps = 100;void loop(void){  // Clear measurement values  memset(values, 0, sizeof(values));  // Scan all channels num_reps times  int rep_counter = num_reps;  while (rep_counter--)  {    int i = num_channels;    while (i--)    {      // Select this channel      radio.setChannel(i);      // Listen for a little      radio.startListening();      delayMicroseconds(512);      radio.stopListening();      // Did we get a carrier?      if ( radio.testCarrier() )        ++values[i];    }  }  // Print out channel measurements, clamped to a single hex digit  int i = 0;  while ( i < num_channels )  {    printf("%x", min(0xf, values[i] & 0xf));    ++i;  }  printf("\n\r");}// vim:ai:cin:sts=2 sw=2 ft=cpp



Далее подключаем модуль nRF24L01 к плате Ардуино или любому прототипу, собранному, допустим, на контроллере ATMEGA328P. Я собрал два образца на платах для прототипирования на контроллере ATMEGA328P по схеме контроллер + резонатор. Один образец подключаю к компу через плату Arduino UNO, а второй через конвертор USB/TTL.

Мощность стабилизатора платы Arduino UNO вполне приемлема для подключения дополнительной импульсной нагрузки такой, как nRF24L01+ c адаптером 5В/3,3В для этого модуля или без адаптера.





На мониторе последовательного порта Arduino IDE увидите нечто похожее:





Если вы увидели похожую картинку тест на работоспособность (исправность) радиомодуля и правильность его подключения пройден успешно. Замените радиомодуль другим, с которым планируете работать дальше.



Обратите внимание на чистый диапазон, начиная с канала 4а. У меня он остается чистым даже, если на расстоянии нескольких метров работает старая СВЧ-печь мощный источник помех в этом диапазоне. А в общем-то, в Интернете рекомендуют выбирать каналы для своих проектов выше 60.



Если на каналах шум, но радиомодуль определяется (смотрим преамбулу на мониторе Arduino IDE, подробно тут) это однозначно копия (подделка). Не отчаивайтесь ее тоже можно запустить.



Шаг 2



По схеме, аналогичной первой собираем второй радиоузел. Это будет передатчик. В его контроллер загружаем скетч передатчика (под спойлером).



скетч приемника
/*Победа над nRF24L01: на три шага ближе, приемникhttp://personeltest.ru/aways/habr.com/ru/post/476716/*/#include <SPI.h>#include <RF24.h>RF24 radio(9, 10); // порты D9, D10: CSN CEconst uint32_t pipe = 111156789; // адрес рабочей трубы;byte data;void setup() {  Serial.begin(115200);  Serial.println("TransmitterTester ON");  radio.begin();                // инициализация  delay(2000);  radio.setDataRate(RF24_1MBPS); // скорость обмена данными RF24_1MBPS или RF24_2MBPS  radio.setCRCLength(RF24_CRC_8); // размер контрольной суммы 8 bit или 16 bit  radio.setPALevel(RF24_PA_MAX); // уровень питания усилителя RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX  radio.setChannel(0x6f);         // установка канала  radio.setAutoAck(false);       // автоответ  radio.setRetries(0, 15);  //время между попыткой достучаться, число попыток  radio.powerUp();               // включение или пониженное потребление powerDown - powerUp  radio.stopListening();  //радиоэфир не слушаем, только передача  radio.openWritingPipe(pipe);   // открыть трубу на отправку}void loop() {  data = 109;  radio.write(&data, 1);  Serial.println("data= " + String(data));}



Передатчик без пауз в работе передает сигнал на канале 6f (112).



Подаем питание на сканер эфира и передатчик. Присмотритесь что творится на канале 6f и соседних с ним каналах. Сканер эфира при включенном передатчике рано или поздно прорисует единички или другие одноразрядные числа в шестнадцатиричном исчислении в области 6f, на который запрограммирован передатчик. Наберитесь терпения, особенно при работе со сканером из примеров.





Увидев сигнал от передатчика делаем следующий шаг.



Шаг 3



Загружаем вместо сканера скетч приемника (под спойлером).



скетч приемника
/*Победа над nRF24L01: на три шага ближе, передатчикhttp://personeltest.ru/aways/habr.com/ru/post/476716/*/#include <SPI.h>#include "nRF24L01.h"#include "RF24.h"RF24 radio(9, 10); // порты D9, D10: CSN CEconst uint32_t pipe = 111156789; // адрес рабочей трубы;byte data[1];int scn;  //счетчик циклов прослушивания эфираint sg;  //счетчик числа принятых пакетов с передатчикаvoid setup() {  Serial.begin(9600);  Serial.println("ReceiverTester ON");  radio.begin();  // инициализация  delay(2000);  radio.setDataRate(RF24_1MBPS); // скорость обмена данными RF24_1MBPS или RF24_2MBPS  radio.setCRCLength(RF24_CRC_8); // размер контрольной суммы 8 bit или 16 bit  radio.setChannel(0x6f);         // установка канала  radio.setAutoAck(false);       // автоответ  radio.openReadingPipe(1, pipe); // открыть трубу на приём  radio.startListening();        // приём}void loop() {  if (scn < 1000)  { // прослушивание эфира    if (radio.available())    {      radio.read(data, 1);      if (data[0] == 109) {        sg++;      }    }  } else {//всего принято    {      Serial.println("Принято: " + String(sg) + " пакетов");      sg = 0;    }    scn = 0;  }  scn++;  delay(20);  if (scn >= 1000) scn = 1000; //защита от переполнения счетчика}



Логика работы приемника такая же, как и у сканера эфира, но он в отличие от сканера принимает сигналы только на частоте передатчика 6f и, как и сканер, не посылает автоответ. Скорость обмена информацией и размер контрольной суммы у приемника такие же, как у передатчика. После каждых 1000-и циклов прослушивания в скетче обнуляется счетчик числа циклов и выводится инфа о количестве принятых пакетов с передатчика в монитор порта Arduino IDE.



Включаем передатчик и приемник. Если приемник принимает хотя бы каждый третий пакет это уже успех. У меня не получилось. Приемник по непонятным причинам принимал максимум 40 пакетов.



Подумал о увеличении мощности передаваемого сигнала с помощью дополнительной антенны. Для начала, подключил зажимом монтажный провод папа-мама к корню штатной антенны. И счастье привалило сразу 999 принятых пакетов!



Юзерам, которые захотят сделать все грамотно, придется поработать. Дополнительная антенна в данном случае это отрезок коаксиального кабеля с волновым сопротивлением 50 Ом и длиной 115 мм. Антенна подключается к выводу 13 (АNT2) микросхемы nRF24L01+. Схему подключения и номиналы нескольких недостающих smd компонентов, которые надо поставить на плату радиомодуля, можно найти на принципиальной электрической схеме nRF24L01+ тут. Впрочем, есть альтернатива в магазин за NRF24L01+PA+LNA





Теперь обязательно припаиваем между пинами GND и VCC обеих радиомодулей по два конденсатора. Керамический конденсатор, выполняющий роль ВЧ-фильтра, емкостью не менее 0,15 мкФ (чем больше, тем лучше) и электролит емкостью около 10 мкФ (можно и больше, но бесполезно) это НЧ-фильтр. ВЧ-фильтр шунтирует высокочастотные помехи по цепи питания радиомодуля, а НЧ-фильтр сглаживает пульсации питания. Для надежности, цепи питания радиомодулей лучше непосредственно подпаять к пинам контроллеров.



Все. Надеюсь, у вас в дальнейшем поубавится проблем с nRF24L01 в своих проектах. Успехов!



Безусловно эти простые шаги не могут гарантировать решение всех проблем с nRF24L01 мне их и не перечесть, но теперь вы, как и я, будете уверены:


  • радиомодули не бракованные;
  • подключены верно;
  • уровень сигнала передатчика, чуствительность приемника удовлетворительны и, в случае необходимости, обеспечиваются дополнительной антенной;
  • пара nRF24L01+ однозначно работает в режиме передатчик-приемник без откликов и их ожидания. Иногда этого достаточно.


Ссылки по теме



  1. Обзор радио модуля NRF24L01+
  2. nRF24L01+: побеждаем модуль.
  3. nRF24L01 и Ардуино: побеждаем модуль (видео)
  4. SE8R01. Подделка под NRF24L01 (видео)
  5. Обзор радио модуля NRF24L01+PA+LNA
Подробнее..

Снова о автономной Arduino-метеостанции на батарейках

03.03.2021 00:13:52 | Автор: admin

Еще донедавна мне не удавалось найти в Интернете любительскую метеостанцию с питанием от батареек. Я имею ввиду бытовую автономную метеостанцию с измерениями параметров в помещении, на улице и отображением информации на дисплее метеостанции. Любители не заморачиваются на этой проблеме, а питают свои автономные девайсы от солнечных батарей, аккумуляторов и т.п. Уточню проблема касается только одного из узлов метеостанции базы, а первые проекты малогабаритных беспроводных автономных выносных датчиков на Ардуино появились 10 лет назад. Вместе с тем, промышленные устройства такого плана бытовые метеостанции, комнатные термостаты годами работают от пары батареек АА и этот факт является той целью, которой хотелось бы достичь.


Это было донедавна. Несколько дней назад меня поразил очередной проект @Berkseo, как поражают все его проекты: "Беспроводная мини погодная станция с e-paper экраном на батарейках". Тут все на уровне промышленного продукта. Удивляет единственное в устройстве нет внешнего датчика.


Год назад разместил статью Автономная метеостанция на контроллере ATMEGA328P и питанием от батареек с беспроводным выносным датчиком. Хотя прототип и выполнял свои функции, но имел серьезные недостатки слишком малая частота обновления данных и большое энергопотребление. Ниже другой вариант метеостанции с новым алгоритмом, элементной базой и кодом с низкоуровневыми вставками. Все это позволило выйти на время работы метеостанции от одного комплекта батареек даже несколько больше, чем гарантируют производители некоторых товаров такого плана.



Что сделано:


Датчики DHT22 и DS18B20, которые использовались в предыдущем проекте, заменены энергосберегающим модулем это датчик температуры и влажности HTU21D. Период измерений, отправки/приема данных уменьшен с 15-ти мин до 53,5 сек. Сделан переход на устойчивую частоту работы контроллера (8 МГц) при напряжении питания ниже 3В. Для уменьшения объемов занимаемой памяти в скетчах использованы некоторые функции С/С++. И главное, принципиально изменен алгоритм передачи пакетов с выносного датчика и алгоритм приема этих пакетов базой метеостанции. Теперь для обеспечения надежного приема пакетов с выносного датчика в нем формируется и отправляется с интервалом около 0,3 сек не один, а три пакета с данными о параметрах воздуха на улице и состоянии батареек. Только после отправки третьего пакета контроллер в. датчика вместе с периферией уходит в сон. База метеостанции уходит спать после приема одного из 6-ти пакетов с выносного датчика и просыпается за полсекунды до поступления очередной серии пакетов с выносного датчика.


Метеостанция состоит из двух автономных узлов с питанием от двух батареек AA: базы и выносного датчика. Назовем их для простоты анализатором (по-другому база) и беспроводным в.датчиком (выносным датчиком).


Анализатор, построен на контроллере ATMEGA328P, измеряет температуру и влажность (датчик температуры и влажности HTU21D) в помещении, а также измеряет и анализирует величину напряжения питания узла, которое обеспечивают две батарейки АА 1,5 В. На контроллер также поступает сигнал с приемника LoRa, который по эфиру принимает информацию с выносного датчика. Вся инфа с контроллера выводится на ЖК-дисплей NOKIA 5110.


В в.датчике, тоже собранном на контроллере ATMEGA328P, измеряется температура и влажность воздуха на улице (модуль HTU21D), а также напряжение питания выносного узла, организованного на двух батарейках АА 1,5 В. Передатчик LoRa этого узла передает инфу о температуре, влажности и состоянии батарейки на анализатор. С в.датчика выполняется отправка 3-х пакетов с интервалом около 0,3 сек, затем контроллер ATMEGA328P, передатчик LoRa и модуль HTU21D для экономного расходования заряда батареек переводятся в режим сна. Измерения и отправка данных с в.датчика выполняется с циклом несколько меньше 1-ой минуты.


Работа анализатора построена по следующему алгоритму:


Вначале, при включении обеих узлов метеостанции, контроллер анализатора подает команды на измерение температуры и влажности внутри помещения и выводит эти параметры на дисплей, затем устанавливает приемник LoRa в режим прослушивания эфира. После приема сигнала с в.датчика и успешной дешифрации принятых данных контролер подает команду на повторное измерение температуры, влажности и выводит инфу в полном объеме на экран. Затем анализатор уходит в сон, просыпаясь примерно за полсекунды до планируемого поступления сигнала с в.датчика. Приняв и дешифровав один из трех пакетов с в.датчика, повторно выполняет свои измерения, выводит информацию на экран и снова уходит спать. Если по каким-то причинам сигнал с в.датчика отсутствует около одной минуты (например, сели батарейки), что по времени соответствует отправке 6-ти пакетов с в.датчика, анализатор проводит измерения только в помещении, изредка сканируя эфир: а вдруг в.датчик появился в эфире?! Это сделано для того, чтобы постоянно работающий на прием модуль LoRa не посадил за короткое время батарейки анализатора.


Для сборки устройства понадобятся радиодетали:


  1. Контроллер ATMEGA328P-PU 2 шт.
  2. Датчик влажности и температуры HTU21D/SHT21/Si7021 2 шт.
  3. ЖК-дисплей NOKIA 5110 1 шт.
  4. Приемник-передатчик LoRa Rа-01 2 шт.
  5. Макетная плата (стеклотекстолит), монтажные провода, батарейки АА, кварцевые резонаторы 8 МГц, резисторы, конденсаторы, другие мелочи.

Ориентировочная стоимость компонентов по ценам AliExpress примерно $25.


Для работы с контроллерами ATMEGA328P в качестве программатора я использую плату Arduino UNO. На Youtube есть хорошее видео по установке загрузчика и загрузки скетчей в контроллер ATMEGA328P с помощью платы Arduino UNO.


На этот раз мы не будем устанавливать новые фьюзы программой SinaProg, а воспользуемся, на мой взгляд, более универсальным способом созданием новых конфигураций плат в платформе Arduino IDE.


В новые контроллеры надо установить загрузчик Arduino as ISP и надо учитывать то, что контроллеры ATMEGA328P поступают в продажу с заводской настройкой фьюз для мониторинга (контроля) напряжения питания не ниже 2,7 В. Мы же будем работать от батареек, напряжение на которых при разряде может быть ниже установленного заводского порога 2,7 В, и с кварцем 8 МГц. Установим загрузчик и изменим фьюзы под наши условия, используя в качестве программатора плату Arduino UNO, в такой последовательности:


  1. Найти по адресу c:\Program Files\Arduino\hardware\arduino\avr\ файл boards.txt и открыть его текстовом редакторе с форматированием, например, AkelPad.
  2. Дополнить файл блоком, который приведен под спойлером, и сохранить файл.

    блок установок 1
    ##############################################################

    amega.name=Mega Low (8 MHz, >1.8V)

    amega.upload.tool=avrdude
    amega.upload.protocol=arduino
    amega.upload.maximum_size=32256
    amega.upload.maximum_data_size=2048
    amega.upload.speed=57600

    amega.bootloader.tool=avrdude
    amega.bootloader.low_fuses=0xFF
    amega.bootloader.high_fuses=0xDA
    amega.bootloader.extended_fuses=0xFE
    amega.bootloader.unlock_bits=0x3F
    amega.bootloader.lock_bits=0x0F
    amega.bootloader.file=optiboot/optiboot_atmega328.hex

    amega.build.mcu=atmega328p
    amega.build.f_cpu=8000000L
    amega.build.board=AVR_UNO
    amega.build.core=arduino
    amega.build.variant=standard

  3. В плату Arduino UNO загрузить скетч ArduinoISP.ino из примеров платформы Arduino IDE (Файл > Примеры > ArduinoISP).
  4. Собрать схему (плата Arduino UNO, контроллер ATMEGA328P, кварц 16 МГц) для установки в контроллер загрузчика ArduinoISP (инструкции тут), подключить ее компьютеру и записать в контроллер бутлоадер Arduino as ISP.
  5. Заменить кварц в схеме 16 МГц на 8 Мгц. В меню ИНСТРУМЕНТ выбрать из списка плату Mega Low (8 MHz, >1.8V), которая появилась в меню после дополнения файла boards.txt новым блоком, выбрать тут же Программатор: Arduino as ISP и, нажав Записать загрузчик изменить фьюзы и другие установки в контроллере.
  6. Далее загружаем в контроллер необходимый скетч, используя ту же схему, что и для установки загрузчика (п.4), через Скетч > Загрузить через программатор.

Выносной датчик


В.датчик построен на контроллере ATMEGA328P. В нем осуществляется прием данных с HTU21D по протоколу I2C, измерение и анализ величины напряжения питания узла и управление передатчиком LoRa.


скетч в.датчика
/*   Снова о автономной Arduino-метеостанции на батарейках, выносной датчик   http://personeltest.ru/aways/habr.com/ru/post/544936/*/#include <avr/io.h>#include <util/delay.h>#include <SPI.h>#include <LoRa.h>#include <LowPower.h>#include <Wire.h>#include <avr/power.h>#include "HTU21D.h"#define VccHTU 8  //питание и подтяжка HTU21D (pin 14 AtMega328P, D8)HTU21D myHTU21D;float Tout; // температураint Hout;  // влажностьunsigned int sleepCounter, sleepCounter0; // счетчик, задающий время снаint pct;  //счетчик числа пакетов перед уходом в сонString messageOut; // LoRa-сообщениеfloat BatOut; // напряжение батареекconst int batteryPin = A0; // pin 23 (Atmega328P), к которому подключена батарея для измерения напряженияconst float typVbg = 1.132; //калибровачная константа, 1.0 - 1.2int counter = 0;// измерение опорного напряженияfloat readVcc() {  byte i;  float result = 0.0;  float tmp = 0.0;  for (i = 0; i < 1; i++) {    // Read 1.1V reference against AVcc    // set the reference to Vcc and the measurement to the internal 1.1V reference#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)    ADMUX = _BV(MUX5) | _BV(MUX0);#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)    ADMUX = _BV(MUX3) | _BV(MUX2);#else    // works on an Arduino 168 or 328    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);#endif    _delay_ms(3); // Wait for Vref to settle    ADCSRA |= _BV(ADSC); // Start conversion    while (bit_is_set(ADCSRA, ADSC)); // measuring    uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH    uint8_t high = ADCH; // unlocks both    tmp = (high << 8) | low;    tmp = (typVbg * 1023.0) / tmp;    result = result + tmp;    _delay_ms(5);  }  return result;}void Measurement () {  // измерение температуры и влажности  Hout = myHTU21D.readHumidity();  Hout = 62;  //delete!  float Tout_p = myHTU21D.readTemperature();  Tout = 0.1 * int(Tout_p * 10 + 0.5);  //округление до десятых  // измерение напряжения батареек  BatOut = 0.1 * int(readVcc() * 10 + 0.5);  if (BatOut < 2.2) {    BatOut = 0.0;  } else {    BatOut = 2.2;  }}void SendMessage () {  // отправка данных (температура, влажность, состояние батареек)  if (BatOut > 2.1) {    messageOut = String(Tout) + "#" + String(Hout) + "$" + String("BGood");  }  else {    messageOut = String(Tout) + "#" + String(Hout) + "$" + String("BLow");  }  LoRa.beginPacket();  LoRa.print(messageOut);  LoRa.endPacket();}void setup() {  Serial.begin(9600);  Serial.println("Power ON");  analogReference(DEFAULT);  pinMode(VccHTU, OUTPUT);  digitalWrite(VccHTU, 1);  _delay_ms(200);  myHTU21D.begin();  int counter = 0;  while (!LoRa.begin(433E6) && counter < 10) {    Serial.println("Не удалось найти LoRa-передатчик!");    counter++;    _delay_ms(500);  }  LoRa.setTxPower(4); //мощность передатчика, 2...20 дБ  LoRa.setSyncWord(0xF3);}void loop() {  digitalWrite(VccHTU, 1);  if (pct < 3)  { // измерения, отправка пакетов    Serial.println(messageOut);    Measurement ();    SendMessage ();  } else {// измерения, отправка пакета и длительный сон    Serial.println(messageOut);    Serial.println("sleep ...");    Measurement ();    SendMessage ();    for (sleepCounter = 6; sleepCounter > 0; sleepCounter--)    {      digitalWrite(VccHTU, 0);      digitalWrite(VccHTU, 1);      LoRa.sleep ();      LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);    }    pct = 0;  }  pct++;  if (pct >= 3) pct = 3; //защита от переполнения счетчика}int main() {  init();  setup();  for (;;) {    loop();  }}

Электрическая схема в.датчика:



Питание и подтяжка выводов модуля HTU21D осуществляется с пина 14 контроллера ATMEGA328P. Это сделано для того, чтобы программно обнулить питание HTU21D и перевести этот датчик в режим низкого энергопотребления во время сна.


Изначально в схеме в.датчика планировалось использовать барометр-термометр BMP280, но мне не удалось программно перевести BMP280 в режим низкого потребления во сне. Хотя по даташиту BMP280 для перехода в режим низкого потребление требуется, как и для HTU21D, кратковременное обнуление питания. Разрыв питания BMP280 во время сна снижает потребляемый ток в схеме ATMEGA328P + BMP280 с 130 мкА до 5 мкА, но, повторюсь, смоделировать этот разрыв питания программно у меня пока не получилось.


В в.датчике формируется и отправляется с интервалом около 0,3 сек три пакета с данными о температуре и влажности на улице и состоянии батареек. Если напряжение на батарейках выше установленного порога (2,2 В), то в коде пакета присутствует BGood, а ниже BLow. После отправки третьего пакета контроллер в.датчика вместе с периферией уходят в сон. Цикл отправки серий пакетов 53,5 сек.


Анализатор


Мозг анализатора контроллер ATMEGA328P. Он принимает сигналы с датчика HTU21D по протоколу I2С и по SPI взаимодействует с приемником LoRa и дисплеем NOKIA 5110.


скетч в.датчика
/*   Снова о автономной Arduino-метеостанции на батарейках, анализатор   http://personeltest.ru/aways/habr.com/ru/post/544936/*/#include <avr/io.h>#include <util/delay.h>#include <SPI.h>#include <LoRa.h>#include <LowPower.h>#include "HTU21D.h"#include <LCD5110_Graph.h>#define VccHTU 8  //питание и подтяжка HTU21D(pin 14 AtMega328P, D8)HTU21D myHTU21D;float Tin; // температура в помещенииint Hin;  // влажность в помещенииLCD5110 myNokia(3, 4, 5, 6, 7);extern uint8_t SmallFont[];extern uint8_t MediumNumbers[];float BatIn = 0; // напряжение батареиconst int batteryPin = A0; // pin 23(Atmega328P), к которому подключена батарея для измерения напряженияconst float typVbg = 1.132; //калибровачная константа, 1.0 - 1.2unsigned int sleepCounter;  //счетчик, задающий время снаint r; //счетчик циклов прослушивания эфираint mlc;  //счетчик циклов работы без в.датчикаString LoRaData, Tout_str, Hout_str, BatIn_str, BatOut_str;// измерение напряжения батареекfloat readVcc() {  byte i;  float result = 0.0;  float tmp = 0.0;  for (i = 0; i < 1; i++) {    // Read 1.1V reference against AVcc    // set the reference to Vcc and the measurement to the internal 1.1V reference#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)    ADMUX = _BV(MUX5) | _BV(MUX0);#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)    ADMUX = _BV(MUX3) | _BV(MUX2);#else    // works on an Arduino 168 or 328    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);#endif    _delay_ms(3); // Wait for Vref to settle    ADCSRA |= _BV(ADSC); // Start conversion    while (bit_is_set(ADCSRA, ADSC)); // measuring    uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH    uint8_t high = ADCH; // unlocks both    tmp = (high << 8) | low;    tmp = (typVbg * 1023.0) / tmp;    result = result + tmp;    _delay_ms(5);  }  return result;}void Measurement() {  float Tin0;  // измерение напряжения батареи:  BatIn = readVcc();  // измерение температуры  и влажности в помещении  Hin = myHTU21D.readHumidity();  // Hin = 58; // delete!  float Tin_p = myHTU21D.readTemperature();  Tin = 0.1 * int(Tin_p * 10 + 0.5);  //округление до десятых  //  Tin = 21.4; // delete!}void draw() {  myNokia.enableSleep();  myNokia.clrScr();  //Tin  char chr_Tin [5];  String Tin_str = String(Tin);  myNokia.setFont(SmallFont);  myNokia.print("            C", LEFT, 0);  myNokia.print("In", LEFT, 8);  myNokia.setFont(MediumNumbers);  Tin_str.toCharArray(chr_Tin, 5); //количество знаков+1  myNokia.print(String(chr_Tin), CENTER, 0);  //Tout  char chr_Tout [5];  myNokia.setFont(SmallFont);  myNokia.print("            C", LEFT, 16);  myNokia.print("Out", LEFT, 24);  myNokia.setFont(MediumNumbers);  Tout_str.toCharArray(chr_Tout, 5);  myNokia.print(String(chr_Tout), CENTER, 16);  // Hin, Hout  char chr_Hout [5];  Hout_str.toCharArray(chr_Hout, 4);  myNokia.setFont(MediumNumbers);  myNokia.print(String(Hout_str), RIGHT, 32);  myNokia.setFont(SmallFont);  myNokia.print("    In Out", LEFT, 40);  myNokia.print("      %", LEFT, 32);  myNokia.setFont(MediumNumbers);  myNokia.print(String(Hin), LEFT, 32);  myNokia.setFont(SmallFont);  // Battery Level  if (BatIn < 2.2) {    myNokia.setFont(SmallFont);    myNokia.print("Bat", LEFT, 0);  }  if (BatOut_str == "BLow") {    myNokia.setFont(SmallFont);    myNokia.print("Bat", LEFT, 16);  }  myNokia.disableSleep();  _delay_ms(5);}void drawStart() {  myNokia.enableSleep();  myNokia.clrScr();  //Tin  char chr_Tin [5];  String Tin_str = String(Tin);  myNokia.setFont(SmallFont);  myNokia.print("            C", LEFT, 0);  myNokia.print("In", LEFT, 8);  myNokia.setFont(MediumNumbers);  Tin_str.toCharArray(chr_Tin, 5); //количество знаков+1  myNokia.print(String(chr_Tin), CENTER, 0);  // Battery Level  if (BatIn < 2.2)  {    myNokia.setFont(SmallFont);    myNokia.print("Bat!", RIGHT, 28);  }  //Hin  myNokia.setFont(SmallFont);  myNokia.print("         %", LEFT, 18);  myNokia.print("In", LEFT, 28);  myNokia.setFont(MediumNumbers);  myNokia.print(String(Hin), CENTER, 18);  //No signal!  myNokia.setFont(SmallFont);  myNokia.print("Out - - -", CENTER, 40);  myNokia.update();  myNokia.disableSleep();  _delay_ms(5);}void setup() {  Serial.begin(9600);  pinMode(VccHTU, OUTPUT);  digitalWrite(VccHTU, 1);  Serial.println("Power ON!");  analogReference(DEFAULT);  // инициализация дисплея  myNokia.InitLCD();  myNokia.setFont(SmallFont);  myNokia.clrScr();  myNokia.print(">>>>>", CENTER, 20);  myNokia.update();  _delay_ms(1000);  myNokia.setFont(SmallFont);  myNokia.clrScr();  myNokia.print("))-->", CENTER, 20);  myNokia.update();  if (!LoRa.begin(433E6)) {    Serial.println("Ошибка загрузки LoRa-приемника!");    while (1);    myNokia.setFont(SmallFont);    myNokia.clrScr();    myNokia.print(" ->  ->", CENTER, 20);    myNokia.update();  }  // Диапазон для синхрослова  между "0-0xFF".  LoRa.setSyncWord(0xF3);  Serial.println("Прослушивание эфира. Ожидание пакета с в.датчика ...");  myHTU21D.begin();  Measurement();  drawStart();  digitalWrite(VccHTU, 0);  _delay_ms(1000);  myNokia.clrScr();  myNokia.print("Waiting", CENTER, 10);  myNokia.print("Message from", CENTER, 22);  myNokia.print("OUTSIDE", CENTER, 34);  myNokia.update();}void loop() {  r++;  digitalWrite(VccHTU, 1);  if (r < 600)  // 8 MHz;  {    mlc = 0;    // Прослушивание эфира, прием, дешифрация, если сигнал с в.датчика принят,    // то измерения в помещении, вывод инфы на экран и - в спячку.    {      int packetSize = LoRa.parsePacket();      if (packetSize) {        while (LoRa.available()) {          LoRaData = LoRa.readString();        }        int pos1 = LoRaData.indexOf('#');        int pos2 = LoRaData.indexOf('$');        Tout_str = LoRaData.substring(0, pos1);        Hout_str = LoRaData.substring(pos1 + 1, pos2);        BatOut_str = LoRaData.substring(pos2 + 1, LoRaData.length());        if ((LoRaData).substring(pos1, pos1 + 1) == "#") {          Serial.println("Принято, декодировано! r = " +  String(r));          r = 0;          Measurement();          draw();          digitalWrite(VccHTU, 0);          // sleepCounter = 49; 16 MHz          // sleepCounter = 48; 8 MHz          for (sleepCounter = 48; sleepCounter > 0; sleepCounter--)          {            digitalWrite(VccHTU, 1);            LoRa.sleep ();            LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);          }        }      }    }  } else {    r = 600;    if (mlc < 250) //4 часа, время работы без датчика    {      Serial.println("Работа без в.датчика.");      LoRa.sleep ();      Measurement();      drawStart();      digitalWrite(VccHTU, 0);      for (sleepCounter = 6; sleepCounter > 0; sleepCounter--)      {        digitalWrite(VccHTU, 1);        LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);      }      mlc++;    } else {      r = 0;      mlc = 0;    }  }  _delay_ms(110); }int main() {  init();  setup();  for (;;) {    loop();  }}

Работа анализатора начинается в setup'e с инициализации модулей, измерения параметров воздуха, анализа напряжения на батарейках и вывода этой инфы на дисплей. Далее уже в loop'e прослушивается эфир приемником LoRa. После приема и дешифрации сигнала с в.датчика повторно проводятся измерения, анализа напряжения на батарейках и вывод измеренной и принятой инфы на дисплей. Выполнив эту работу все элементы схемы уходят поспать примерно на полсекунды меньше, чем период отправки пакетов с в.датчика. В следующем цикле контроллер просыпается и включает приемник приблизительно за 0,5 сек до ожидаемого прихода сигнала с в.датчика. Таким образом, контроллер и периферия анализатора работают около полсекунды с периодом (циклом) меньше минуты (53,5 сек). Если радиосигнал с в.датчика не поступает на приемник анализатора на протяжении приблизительно одной минуты (время, достаточное для приема одного из 6-ти пакетов), то анализатор переходит в режим работы без в.датчика на 4 часа, измеряя параметры воздуха и оценивая состояние батареек только в помещении с индикацией на дисплее этих данных. Период обновления данных в режиме работы без в. датчика 56,7 сек. В конце четырехчасового цикла работы анализатора без в.датчика он прослушивает эфир: а вдруг в.датчик снова в эфире?




Для перевода модуля HTU21D в режим низкого энергопотребления во время сна его питание также, как и в в.датчике, организовано с контроллера ATMEGA328P (пин 14).


В целом, на дисплее анализатора видна такая картинка:



Дисплей из-за низкого разрешения и малого размера экрана плотно забит символами. Эта картинка смотрелась бы намного лучше на современном дисплее с электронными чернилами. В будущем в своих проектах буду использовать e-paper дисплей.


Ресурс батареек и другое


Для расчета срока работы батареек понадобится время и потребляемый ток во время выполнения работы (операционное время) и сна. Операционное время и рабочий ток измерялись с использованием тестовых скетчей, идея которых взята отсюда.


Рабочий ток измерялся с использованием тех же тестовых скетчей. Для исключения разрывов цепи питания или значительного увеличения величины выходного сопротивления батареек можно использовать шунт 3,9...5,6 Ом и параллельно подключенный к нему цифровой мультиметр с механическим переключением в режиме вольтметра на диапазоне 2000 мкВ. Это критично при измерении потребления тока сна анализатора, поскольку разрыв питания или значительное ограничение тока приводят к цикличесому ресету анализатора. Да и выносной датчик может переходить в постоянный рестарт. По мере возможности необходимо проверять ток потребления разными способами на разных диапазонах шкал прибора и с батарейками, которые планируется использовать, притом, обязательно без вывода результатов на монитор порта Ардуино. Невыполнение этих правил сказались на результатах измерений тока в предыдущем моем посте на тему метеостанции в одних случаях они занижены, в других завышены.


Результаты измерений сведены в таблицу:


в.датчик анализатор
Операционное время функции измерений параметров воздуха, состояния батареек 0,25 сек 0,39 сек
Операционный ток функции измерений параметров воздуха, состояния батареек 3,4 мА 3,5 мА
Операционное время функции передачи/приема сигнала 42 мсек 83 мсек
Операционный ток функции передачи/приема сигнала 30,0 мА

(4 дБ)


11,5 мА
Ток сна 10 мкА 190 мкА

Что бросается в глаза, глядя на эту таблицу. Операционный ток передачи сигнала 30,0 мА при мощности передатчика LoRa 4 дБ. Для сравнения, ток передачи для модуля nRF24L01 13,5 мА. Вывод очевиден: надо переходить на nRF24L01, но не все так просто.


В режиме приемника в nRF24L01 используется так называемыйLNA (малошумящий усилитель). Разработчик библиотеки предполагает, что нет никакого программного обеспечения, которое могло бы повлиять на режим LNA.В режиме приема модуль постоянно демодулирует сигнал для поиска входящего пакета. Именно по этой причине Berkseo не поставил внешний датчик. У меня задача, вроде, попроще организовать режим сна с библиотекой LowPower.h. Сомневаюсь, что задача имеет решение. Буду благодарен за ваши мнения на этот счет.


Средний ток потребления по данным таблицы в. датчика 0,13 мА. Емкости батареек типа АА GP Litium для выносного датчика должно хватить на 2,5 года.


Средний ток потребления анализатора 0,27 мА. Ресурс батареек АА GP Litium в анализаторе 1,2 года. Для беспроводного комнатного термостата Computherm Q7RF, например, срок действия батареек: около 1 года.


Еще на тему энергопотребления долго копался в этой теме и хочется выговориться.


Составил код на С в Atmel Studio и эмулировал его в Proteus'е для для барометра-термометра.



На картинке ниже показаны результаты сравнения кода для одного и того же устройства на языке С и в среде разработки Arduino IDE.



Объем флеш-памяти, занимаемой в коде в Ардуино 12968 байт, на С 5954 байта и оценочно на Ассемблере не больше 200 байт.


Из этих чисел сделал несколько выводов, в которых убедился на собственном опыте:
Код на Ассемблере уменьшает размер памяти на порядки. Соответственно пиковое потребление падает в сотни раз. С десятков миллиампер при прошивках контроллеров устройств на Ардуино или С, С++ до десятых миллиампера на Ассембере.
Поиск компромисса. Так благодаря использованию компилируемых в Arduino IDE библиотек и функций на С/С++ в некоторых скетчах этого поста удалось уйти от предупреждения: Недостаточно памяти, программа может работать нестабильно. Притом, чем проще код, тем выше соотношение: размер памяти в Arduino IDE к памяти на С/С++. Для простейшего кода мигания светодиодом в несколько строк это соотношение составит 6 раз, а проигрыш в производительности 28 раз.


Не буду скромничать, полученный результат энергопотребление прототипа на уровне промышленных образцов, меня радует, а совершенству нет предела


И, наконец, искренне благодарю AlexanderS, который донес до меня идею виртуальной шкалы времени или синхронизации, а также других участников обсуждения статьи Автономная метеостанция на контроллере ATMEGA328P и питанием от батареек с беспроводным выносным датчиком (ittakir, Javian, smart_alex, Polaris99, gerasimenkoao, igrushkin, enjoyneering) за предложения, конструктивную критику и замечания.


Спасибо, кто дочитал. Всем отличного иммунитета во времена коронавируса и не только.


Ссылки по теме


Узел беспроводного датчика с низким энергопотреблением


Беспроводная мини погодная станция с e-paper экраном на батарейках


Превращаем Arduino в полноценный AVRISP программатор


LoRa и сон


Узнайте о битах конфигурации ATmega328P и о том, как использовать их с внешним кварцевым резонатором


Калькулятор фьюзов AVR


Почему многие не любят Arduino

Подробнее..

Рожденные в карантине беспроводной датчик и все-все-все. Битва роботов в конце

26.04.2021 12:16:37 | Автор: admin
image
Рабочая неделя сокращена и теперь ты мой
Твоя прокрастинация. Апрель 2020.


imageВ этой статье я c удовольствием хочу поделится с Вами универсальной платой, которую легко можно использовать для:
  • метеостанции, беспроводного датчика температуры\влажности на солнечной батарее или без нее;
  • автоматического полива цветов на солнечной батарее;
  • безопасным пускателем фейерверков;
а также
  • управлением открывание/закрывая форточки в парнике или механический кнопконажиматель;
  • модуль охранной сигнализации или контактный датчик;
  • управление светодиодной лентой или небольшим вентилятором;
  • умный уличный фонарь на солнечных батареях;
  • наручными/настенными часами или кухонным таймером;
  • и даже электрическая мышеловка или кормилка для животных.


Устройство представляет собой микроконтроллер с приемопередатчиком nrf24l01 и выходами до 3А стоимостью всего от 2*. Заинтересовались и хотите попробовать сами? Последние 10 плат вышлю по Германии абсолютно бесплатно.
* по ценам на 07.2020

Что в черном ящике?

Требования к устройству


Необходимость разработки, как ни странно, пришла от желания установить банальный беспроводной датчик температуры. Я знаю, на Хабре и в Интернете представлено огромное количество температурных датчиков на любой вкус. Но у большинства готовых работ есть серьезный недостаток цена. Платить по 10-15 за штуку, на фоне текущего дефицита и подорожания микросхем, это не серьезно, особенно когда тебе надо больше 10 штук.
Почему так много?
Когда температура в доме опускается ниже 19C, возникает дискомфорт и желание включать отопление. Двери в комнатах закрываются и там образуется свой микроклимат. Слишком высокая температура плохо скажется на счетах и выбросах СО2, а низкая температура будет способствовать избыточной влажности и появлению плесени.
Для помещений рекомендуется соблюдать следующие температуры: гостиная +22C, спальня +20C, ванная +25C, детская +23C, коридор +18C, подвал > +1C, гараж > 0C.
Вторым недостатком увиденных мною датчиков является радиус действия. WiFi с трудом пробивает междуэтажные перекрытия, а что уже говорить о подвале. Можно протянуть WiFi в подвал, для любимой мышки, но она перегрызет провода, испугавшись излучения. Поэтому, датчик должен уметь ретранслировать сообщения от других датчиков.

Третье требование автономность. Для 10 датчиков нужно более 10 батареек и, конечно, хотелось бы заряжать батарейки не чаще 2-3 раз в год. А лучше вообще забыть про зарядку. Например, датчик расположенный на улице может заряжаться от солнечной батареи, а датчик в кладовке может работать от таблетки, просыпаясь 1 раз в час.

Четвертое требование универсальность. Хочется иметь класс устройств, которые будут долго спать, отправлять 5-8 байт в сеть, а при наступлении события включать что-нибудь маломощное, до 2-3А.

Выбор компонентов


В качестве приемопередатчика был выбран NRF24L01, известный не только благодаря своей низкой цене, но и богатым выбором готовых SMD модулей со встроенным усилителем и разъемом внешней антенны.

Датчик температуры/влажности должен иметь цифровой интерфейс и точность выше 1 градуса и опять же приемлемую цену. Выбор пал на SHTC3.

Дисплей должен быть дешевым и информативным. В качестве дисплея было выбрано семейство больших и малых SSD1306 дисплеев. Кончено, я задумывался и над E-paper и для него зарезервировано место, но он плохо ведет себя на морозе и все еще дорого стоит.

Основной дисплей является не энергоэкономичным, поэтому надо определять необходимость его включения. Датчик движения SR602 понравился из-за его размеров. Также можно включить сенсорную кнопку или ИК-приемопередатчик.

Аккумуляторы были выбраны 2 типов: NiMH, как безопасное и дешевое решение для домашних и уличных нужд, если постоянная отрицательная температура длится меньше 1-2 недель и LiFePo4 для уличных нужд при сильных отрицательных температурах.

Контроллер заряда аккумуляторов был выбран CN3085 для NiMh и CN3058e для LiFePo4. Они имеют схожую цоколевку, за исключением вывода DONE, без которого можно обойтись. NiMH также можно заряжать через токоограничительный резистор.

Так и сложились требования к микроконтроллеру: SPI, I2C, RTC с alarm, PWM, ADC, 5 свободных gpio, малое потребление, рабочую температуру -40C..+85C, диапазон напряжений аналогичный NRF24L01, также, имеет значение цена, комфортный для пайки корпус и большой lifetime.
Взвесив все за и против выбор пал на STM8L051. Некоторые могут обвинить меня в предвзятости к STMicroelectronics и будут правы, но на самом деле
были рассмотрены и отброшены следующие варианты:
ESP32-S2FH4 дешево, но WiFi энергозатратен и придется возиться с отладкой высокочастотных схем;
STM32L0XX + NRF24L01 очень хорош, но хотелось бы дешевле;
PIC16Fxx + NRF24L01 также понравился, но нет RTC;
nRF52810 хорош в своем классе, но будет дороже, чем NRF24L01 + дешевый микроконтроллер;
и некоторые китайские производители были отброшены по причине плохой поддержки.

Таким образом определился следующий список компонентов:
Наименование компонента Цена*, Минимум Обычный Обычный с экраном Метеостанция Внешняя метеостанция
STM8L051 0.4 x x x х х
NRF24L01+ 0.6 x x x х х
PCB 0.2 x x x х х
Кварц. резонатор 1TJF090DP1AI075 0.2 x x х х
Датчик температуры SHTC3 0.8 x x х х
Датчик движения SR602 0.4 x х х
Аккумулятор NiMh 1 x x х х
Зарядка аккумулятора CN3085 и стабилизатор напряжения AP2210K-3.3 0.3 x х х
Дисплей SSD1306 0.91 1.1 x
Дисплей большой SSD1306 2.4 10 х х
Солнечная панель 2 х
Итого, 1.2 3.2 5 13.9 15.9

* по состоянию на 07.2020, текущая цена может отличаться в 2-10 раз. Будем надеяться, что это скоро пройдет.

Схема принципиальная.


Я не настоящий электротехник, поэтому в схеме могут быть допущены ошибки, влияющие на работу устройства в долгосрочной перспективе.
Разработка принципиальной схемы и платы выполнялась в KiCAD.

Основные узлы


Питание


Ключик для датчиков и внешних устройств, 2 шт



и многочисленные разъемы



Схема разрабатывалась универсальная и необходимость пайки элементов зависит от конфигурации устройства. Пайка всех элементов сделает устройство нерабочим.
Например, в схеме предусмотрены 3 варианта зарядки батарей через зарядные контроллеры, с подключением внешнего блока питания и через токоограничительный резистор для подключения солнечной панельки.
Также невозможно одновременно использовать датчик движения и диод D2, как индикатор MCU.
Цоколевки для SMD модулей NRF24L01 и NRF24L01 Long Range разные и можно подключить только один из них.

С целью снижения энергопотребления, был установлен отдельный ключ Q1-VT1, который прерывает питание дисплея, приемопередатчика и датчика температуры. В режиме сна основными потребителями являются микроконтроллер, 100К подтяжки на VT1,VT2 и датчик движения, при его установке. I2C шина также была подтянута на отключаемое питание датчиков, дабы избежать утечки драгоценного заряда в режиме сна.

Для подключения внешних устройств, таких как водная помпа, сервопривод, аналоговые датчики или кнопки управления, предусмотрен разъем J4 с управляемым питанием Q2-VT2. Этот выход может иметь раздельное питание с основной платой J3. Максимальное напряжение зависит от подобранных транзисторов и здравого смысла.

Печатная плата.


Я не настоящий проектировщик печатных плат, поэтому с благодарностью приму все Ваши замечания. Плата проектировалась двухслойная из соображений экономии.
Верхний слой

Нижний слой


SMD компоненты выбраны размером 0804, для комфортного разглядывания номиналов резисторов и ручной пайки. Знаю, что многие из вас способны запаять 0204 с закрытыми глазами 60Вт паяльником, так вот это схема и для тех кто этого не может. Для самого мелкого компонента температурного датчика SHTC3 нанесена разметка для его точного позиционирования. Посадочное место для ключей управления устройством, к которому можно подработать транзистор с переключением до 6А при 8V, что больше возможностей дорожек.

Датчик температуры\влажности разместился рядом с контроллером в надежде, что большую часть времени контроллер будет спать и не будет нагревать датчик. По этой причине, силовые элементы унесены на противоположные концы платы, но это не помогает и в режиме зарядки температура увеличивается на 4-5 градусов. NRF24L01 припаивается отдельным модулем, для экономии времени и возможности выбора типа приемопередатчика. Проект данной платы вы найдете на GitHub.

Если схема зарядки аккумулятора не требуется, то можно ее отломать бокорезами, сделав кусь по линии отверстий(берегите глаза).

Плата распаивалась с помощью паяльной пасты и утюжных технологий. Запекать 2 мин. при температуре Лён:

Смотрится вполне сносно:


Корпус


Размер платы удачно совпадает с размерами 2 батареек ААА, что делает доступными все корпуса с батарейками 2xААА или 2xАА. Также подойдут некоторые корпуса для 1x18650 при диагональном размещении платы. Вид у этих коробочек соответствует цене, но мы их спрячем и замаскируем.
Для устройств находящихся на видном месте спешу поделится технологией быстрого и дешевого изготовления красивых корпусов.
Покупаем или печатаем пластиковый корпус и фанеру толщиной 1-2мм из благородных пород дерева. С помощью цианокрилата(берегите глаза и нос) клеем фанеру на пластик и отрезаем все лишнее. Если у вас такие же кривые руки, то необходимо запастись шпатлевкой по дереву и замазать сделанные щели и сколы. Затем, надо дать просохнуть клею и шпатлевке, затереть всё наждачной бумагой и покрыть маслом или лаком.
Таким образом, из
серой пластиковой коробочки


получается теплый деревянный корпус.


Тестирование


Платы были успешно протестированы при температурах от +40С до -14С в конфигурации с дисплеем и датчиком движения. Для плат, которые будут использоваться на улицы в качестве защитного покрытия был использован специальный лак.

Измеренный ток в спящем режиме ~1.5мкА при 2.6В. При включенном режиме потребление зависит от количества подключенных устройств, яркости дисплея, количестве включенных пикселей и режимах приемопередатчика, в среднем получилось 40мА.
Ниже приведено расчетное время работы в зависимости от используемой батареи.
АКБ Заряд, mAh Номинальное напряжение, V Период передачи данных, c Расчетное время работы на 70% заряде, дней
AAx2 2500 2.4 300 217
AAAx2 900 2.4 300 77
AAx3 2500 3.6 120 174
AAAx3 900 3.6 120 62
CR2025 150 3 3600 189
AAx6 5000 3.6 120 350

На сегодняшний день я не могу подтвердить достоверность расчетных данных, испытания продолжаются.

Программное обеспечение.


STM8L051 является 8 битным MCU, имеет 1Кб RAM и 8 Кб ПЗУ. Это значит, что в 8 Кб необходимо уместить максимальную комплектацию:
поддержка интерфейсов i2c, spi;
поддержка устройств: датчик, NRF, дисплей, часы;
протокол передачи данных SMESH;
шрифт (цифры, знаки, буквы);
график вывоза мусора.
И здесь придется бороться за каждый байт. Программный код был написан на языке С для компилятора sdcc. Из допущенных ограничений стоит отметить, что шрифт уместился только от пробела до заглавной Z, а годовой график вывоза мусора пришлось упаковать в 1 байт на событие. Для дисплея размером 128*32 пикселя требуется RAM буфер 512 байт, что приемлемо для микроконтроллера, а вот для экрана 128*64 требуется уже 1Кб, что в RAM уже не помещается. Поэтому, для большого экрана, его буфер пришлось делить на 2 части верхние 3 строки текста и нижние 3 строки текста.

Возможно, описание программного кода со всеми ухищрениями следует оформить отдельной статьей, но сначала исходный код должен быть приведен в приличный вид. Выкладываться на github он будет постепенно, пропорционально полученному отклику.

SMESH (Simular MESH)


Да, уместить полноценный MESH в 8Кб не получилось, но по крайней мере он умеет ретранслировать сообщения. Для управления необходим контроллер, который будет синхронизировать устройства, принимать показания датчиков, передавать время и другие данные. Каждое устройство имеет уникальный ID(4 байта) и динамический однобайтовый адрес. Одна сеть поддерживает до 126 узлов, с максимальным диаметром 22 узла. Кроме этого, каждый узел может ретранслировать данные с устройств не участвующих в сети.

Подразумевается, что контроллер сети постоянно включен и передает данные устройствам. Устройства же спят большую часть времени, просыпаясь согласно расписанию. Расписание имеет установленный период и всегда кратно одному часу. Таким образом, зная точное время и период цикла можно вычислить следующий сеанс связи. С началом периода устройства должны проснуться, передать свои данные и уснуть до следующего сеанса.
Если устройство не будет просыпаться каждый сеанс связи, то оно должно быть исключено из цепочки ретрансляторов данных.

Основа функционирования сети точное время. Поэтому сообщения с точным временем от контроллера сети передаются регулярно. Это помогает скорректировать время на устройствах и быстро подключить новое устройство.

Как мы знаем в аббревиатуре IoT буква S означает seсurity. Нарушать эти традиции у меня не хватило памяти. Но можно быть уверенным, в случае атаки злоумышленник будет находится в радиусе 100 метров от крайнего узла, и при обнаружении невероятных значений температуры вам следует выпустить ваших собак.

На данный момент полноценного тестирования сети проведено не было, но в первом приближении это работает.

Контроллер сети


Изначально контроллер сети планировалось сделать также на базе микроконтроллера, в виде шлюза NRF24L01 WiFi. Но, посчитав соотношение цена\функциональность\время разработки, выбор пал на полноценный PC Raspberry PI Zero(20) c 6'' HDMI дисплеем+touchscreen(30). Несмотря на свою одноядерность и 1Гб RAM RPi Zero справился со своей задачей отображения сенсоров и почасового прогноза погоды на остаток дня.
В качестве ОС был развернут минимальный образ OC *Linux* и установлен Kivy, который поддерживает egl, умеет работать с framebuffer и не нуждается в Xwindows. Следуя заветам Unix, было написано несколько программ, каждая из которых вносит небольшой вклад в отображение информации. Основной является программа управления сетью, которая также принимает данные с устройств, распределяет динамические адреса и передает точное время, погоду и другую информацию. Программа написана на языке С и может быть портирована на любой микроконтроллер. Также работают несколько небольших Python-скриптов: однин из них прекрасно генерирует картинку первого этажа дома, второй для второго этажа, еще один для генерации погоды от OpenWeatherMap на следующие 12 часов, отправки данных на сервер и телеграмм, и наконец, программа, которая показывает сгенерированные картинки по кругу, с возможностью swipe и обеспечивает интерфейс с пользователем.



Чтобы монитор не светился постоянно, к RPI был приделан все тот же датчик движения, по сигналу с которого или с touchpad подается команда к включению монитора. Через 30 секунд монитор выключится, если сигналы не поступят опять.

С самого начало было очевидно, что в конечном счете разработка вышла дороже, чем готовые датчики, но эту плату можно использовать и для других прекрасных вещей.



Автоматический полив цветов на солнечной батареи


Скоро лето, время когда люди уезжают в отпуска, оставляя свои комнатные растения без воды под жаркими лучами палящего солнца. Я знаю, на Хабре и в Интернете представлено огромное количество систем полива для цветов. Большая их часть требует питания 220В или емких LiPo АКБ.

Для модификации нашей платы в автоматическую поливку цветов нам потребуется маломощная водяная помпа до 3А и напряжением 3-4В. Помпу необходимо поместить в емкую канистру от 5л. Желательно, чтобы канистра находилась на одном уровне с цветком, иначе мощности помпы может быть недостаточно для подъема воды более, чем на 30см. Если канистра с водой будет выше цветка, то необходимо поставить обратный клапан, который будет предотвращать самотек воды, запуская в трубопровод воздух. Помпа подключается к разъему J4.

В простейшем случае, длительность включения насоса можно настроить экспериментально. Например, установить включение на 3 минуты 2 раза в день. Для ручной регулировки цикла подачи воды можно подключить дисплей и 2-3 кнопки к разъему J7. В качестве обратной связи можно использовать ADC канал или поместить датчик влажности ближе к поверхности земли. А источник питания лучше использовать 3-6 аккумуляторов АА и солнечную батарею(блок батарей) площадью от 0.4 кв.м., которую необходимо подключить к разъему J8 и приклеить(прислонить) к окну.

Данная схема уже была реализована и, возможно, работает и по сей день, но на другом микроконтроллере.

Безопасный пускатель фейерверков


Не сомневаюсь, что читатели Хабра соблюдают технику безопасности при запуске фейерверков, но несчастные случаи также возможны при некачественной продукции. Поэтому для безопасности и комфорта инициировать запуск фейерверков лучше на безопасном расстоянии.

Для этого понадобится 2 таких устройства: одно для запуска, с нитью накаливания, а второе для управления. В качестве нити накала можно использовать никелевую нить малого сечения, намотанную на разъем и подключенную к J4. Для нагрева нити достаточно 3-4 аккумулятора АА и соответствующий току и напряжению транзистор в ключе VT2. Длину нити следует подобрать так, чтобы она светилась ярко-желтым светом, но при этом не перегорала мгновенно.

Перед надеванием нити накаливания на фитиль фейерверка, фитиль следует загнуть. Для пульта управления следует использовать второе устройство, подключить кнопку запуска к разъему J12. Соблюдайте осторожность при включении устройства!
Демонстрацию устройства, к сожалению, провести не удалось из-за отмены фейерверков в этом году из-за COVID.

Бонус. Битва роботов.



Их схватка будет легендарна

В качестве побочного продукта(своего рода вложенная прокрастинация) сопряжения STM8L0xx+NRF24L01 были изготовлены роботы для игры всей семьей. Схему печатной платы, ПО и модели деталек для 3D печати можно найти на GitHub.

Идея была в создании дешевой игрушки на радиоуправлении с возможностью расширения. В качестве основы корпуса была взята печатная плата, на которую крепятся моторы N20 с редуктором на 150об/мин и батарейный отсек с поворотным колесом.
Для добавления зрелищности борьбе был предусмотрен крюк с сервоприводом, но в схватке реальной пользы от него почти нет. С помощью крюка робот может самостоятельно переворачиваться и впиваться в ногу. На плате есть возможность подключения излучателя для стрельбы фотонами и фотодиода с операционным усилителем, а также внешней платы управления на базе esp32 c внешней камерой. К сожалению, все это так и не было протестировано.

В проекте также используются NiMH аккумуляторы, терпимые к замыканию и ударам, особенно, в руках детей. Cледует обратить внимание на максимальный ток NiMH аккумуляторов, дешевые аккумуляторы не способны выдать ток, необходимый для работы сервопривода под нагрузкой и просаживают напряжение, сбрасывая микроконтроллер.

Было придумано множество вариантов игр, роботы могут устраивать гонки, драться, играть в футбол. Один из вариантов игры можно увидеть в этом коротком видео:

За все время эксплуатации сломалось 6 больших колес, 2 кнопки пульта управления, 2 сервопривода и 1 мотор. Запасайтесь колесами!
Подробнее..

Приручение nRF пульта для ПК с потерянным приемником

10.05.2021 16:07:24 | Автор: admin

В этой статье я расскажу, как мне удалось заставить работать nRF пульты для ПК, для которых были утеряны приемники. Не обошлось без Arduino, множества попыток бросить это дело, долгого безуспешного гугления, радости маленьким победам, разочарования от неудач и наконец новой жизни для nRF пульта, но обо всем по порядку...

В далекой-далекой галактике...

Для начала, расскажу зачем мне вообще понадобился такой пульт. Будет много и длинно, кому это неинтересно, может сразу перейти к следующей главе. Дело, в том, что я все еще отношусь к той устаревшей модели людей, которые привыкли видеть компьютер центром всего мультимедиа в доме (как это было в середине 2000х) и хоть, теперь для каждой задачи уже давно есть свой гаджет, мне все равно так привычнее и удобнее. Поэтому фильмы я смотрю исключительно через ПК. У меня довольно древний 42' ЖК телевизор подключенный по HDMI, который я не вижу смысла менять на что-то новее. Если мне нужен большой экран - для этого у меня есть проектор и экран с диагональю в 2 метра (так же по HDMI к ПК). Но я уже давно на нем ничего не смотрел, он для чего-то такого эффектного, красивого, вроде Аватара, но что-то за последние пару лет я ничего такого интересного для себя не находил. А простые сериальчики можно глазеть и на экране поменьше, к чему эти огромные головы крупным планом? И вот, уже, наверное, лет 10 назад, попался мне первый пульт для ПК, шел он в комплекте к одной из материнок от ASUSа.

Он был маленький простой и удобный, и я тут же заценил, что больше не надо подрываться и нажимать кнопки на клавиатуре, чтобы поставить на паузу, прибавить громкость, увеличить скорость или мотнуть. Сейчас можно, конечно, использовать для этого Bluetooth клавиатуру или мышку, но я по прежнему вижу это менее удобным, чем использовать пульт. Клавиатура здоровая, на ней куча ненужных кнопок, ей не место на диване. Мышь надо по чему-то возить и еще высматривать там на экране курсор, а это бывает трудновато, когда курсор-то на экране, только вот на другом. А пульт просто взял в руку и нажал нужную кнопку, к которой уже привык и которую найдешь наощупь. Да можно еще поднять DLNA и использовать SmartTV, но там надо думать схавает ли телек этот формат, настраивать транскодинг, если нет (а транскодинг вообще зло, зачем так мучать видео). Поэтому, я очень долго использовал этот пульт (точнее не этот, это запасной, а тот который я использовал, уже слишком истерся и выглядит неприглядно, да, я не из тех людей, которые держат пульты в целлофане, в целлофане ощущения не те). И всем этот пульт был вроде хорош, но со временем мне стало не хватать на нем кнопок. И тогда я заказал с Али вот такой:

Его я использовал вместе с программой EventGhost для Windows, которая позволяет назначать на разные кнопки разные действия и поддерживает некоторые пульты, включая этот. Но вот был один недостаток - для того, чтобы этот пульт нормально работал внутри EventGhost и не делал больше ничего лишнего, для него нужно было поставить специальный драйвер, а драйвер этот был не подписан. Как известно Майкрософт это любит не очень и хоть и оставляет такую возможность, но приходится немного поплясать с бубном, перезагружаясь в тестовый режим, где этот драйвер надо ставить. При этом, во время крупных обновлений 10ки он зачастую слетал и приходилось проделывать это снова. Этот пульт служил мне еще несколько лет, но в какой-то момент, после очередного слета драйвера, мне это надоело и я решил попробовать что-то еще. Тогда я заказал с Али вот такое чудо:

Он уже работает на 2.4Ghz и не требует прицеливания, что конечно большой плюс, а вот минусом было то, что для него не было уже какого-то специального драйвера, который позволил бы мне назначить на каждую его кнопку именно те комбинации клавиш, которые мне нужны. Т.е. я конечно мог назначить на кнопку "домой" какое-то действие в EventGhost и оно выполнялось, но помимо этого кнопка "домой" срабатывала еще и как кнопка "домой" и открывала мне браузер с домашней страницей. Я даже нашел какую-то программу, которая позволяла мне заблокировать прямое назначение некоторых кнопок, на которые у меня были назначены макросы в EventGhost и это улучшило картину. Но я все еще не мог назначить действие на кнопки с цифрами, иначе они выполнялись, когда я нажимал эти цифры на обычной клавиатуре, и заблокировать я их не мог по той же причине. Позже я нашел древнюю программу HidMacros которая могла вешать действия на клавиши с какого-то конкретного устройства, и она даже работала под 10кой, но че-то программ стало слишком много для такой простой задачи и я снова стал бояться, что с очередным обновлением что-то из этого отвалится. К этому времени я как раз увлекся Arduino и понял, что могу сделать, чтобы любой ИК пульт работал у меня, как пульт для ПК. Я снова вернулся к предыдущему пульту, но теперь он передавал сигнал в ИК-приемник Arduino, а тот в свою очередь отдавал команду в EventGhost через ком порт. Единственное, что после 2.4Ghz пульта, использовать снова ИК, которым надо хоть не много, но прицеливаться было шагом назад, но я смирился. И все шло себе тихо-мирно, но вдруг, внезапно, мне достались эти красавцы:

Посмотрев на них и на их набор кнопок, я понял, что хочу чтобы хоть один из этих ребят работал на меня. Я вставил батарейки и радостно начал нажимать кнопки, но на ИК приемник ничего не приходило. И вот тут я понял - они не ИК, они такие же, как и VONTAR на картинке выше, работают на 2.4Ghz и без приемника с ними делать нечего, а приемников от них то у меня и нет. Можно было, конечно, заказать такой же пульт с приемником на Али, но я уже предвидел какие проблемы меня ждут: я снова не смогу нормально назначать действия на кнопки, они будут эмулировать те клавиши которые в них зашиты и только их. Снова надо как-то хитро блокировать прямое назначение этих клавиш, снова все не просто Plug и не просто Play, опять какие-то трудности. А я не люблю, когда трудности. Я люблю когда ахренительно-невероятно-пипец, какие трудности. Поэтому я заказал для Ардуино модуль nRF24L01+ и раз уж нам подарили с барского плеча столько выходных на майские, а погода как-то не все дни обещает быть хорошей, я решил потратить часть этого времени, чтобы хакнуть протокол пультов!

Этап принюхивания

Итак, мой модуль nRF24L01+ пришел, я достал одну из Ардуино нано и был готов перехватывать пакеты!

Это не моя картинка, но подключал я по этой схеме на те же пины с поправкой на их другое расположение в наноЭто не моя картинка, но подключал я по этой схеме на те же пины с поправкой на их другое расположение в нано

Ну вот теперь я точно был готов к перехвату пакетов, но вот пакеты оказались не готовы быть перехваченными. Это было первое разочарование. Вообще модуль nRF24L01+ я брал наугад, типа тут 2.4Ghz, там 2.4Ghz, ну... давайте... работайте вместе как нибудь! Ну пожалуйста! Но, как выяснилось, протоколов этих очень много, те же модули WiFi работают на этих частотах, но пакеты от пульта получать в большинстве своем не могут. И если пульт шлет свои пакеты не по тому протоколу, по которому работает nRF24L01+, то тоже ничего не выйдет. Я понадеялся на удачу и для начала стал искать канал, на котором должны идти данные. Для этого я скачал какой-то нагугленный скетч в интернете, который смотрит на каких каналах есть сигналы. Как оказалось сигналы есть много на каких, но нажатия кнопок на пульте никак на них не влияет. Сигналов больше не становиться ни на одной из частот, а они хаотично появляются на разных частотах, не зависимо от того, нажимаю я что-то на пульте или нет. У nRF24L01+ есть 3 скорости 250Kbit, 1Mbit и 2Mbit. Ни на одной из них и ни на одном из каналов, я пульта не нашел, сколько бы не давил не его кнопки. "Ну что ж", сказал я себе, значит не судьба, и лег спать. Но на утро интерес снова проснулся, и я решил разобрать один пульт и посмотреть, что там все-таки за чип. К моей радости пульт, хоть и собран без единого винтика, но разобрался очень легко:

И что же я вижу на плате?

Именно! Там чип nRF24LE1G, внутри которого сидит nRF24L01. Значит все верно, и протокол тот. Но почему же, я не могу понять на какой частоте он работает? Пульт точно рабочий (когда я нажимаю кнопку, на нем моргает лампочка. А раз лампочка моргает - значит и пульт работает. И не говорите, мне что это не обязательно так!). Я потратил на это еще пару часов, но никаких результатов не добился и тогда я понял:

если уже больше ничего не помогает - прочти наконец этот чертов код, который ты скопировал из интернета и бездумно вставил в свой проект!

И я стал смотреть код и понял в чем причина. Модуль не умеет одновременно случать все частоты, поэтому код написан так, чтобы модуль постоянно переключался с одной частоты на другую слушая каждую по 128мкс. Но частот много, и получается, что те сигналы, которые генерит пульт, не успевают попадать под сканирование или попадают, но в очень малом объеме, не отличимом от общего шума. В результате я переписал скетч, чтобы частоты переключались вручную ('w' в COM порт - следующая, 's' - предыдущая), и о чудо! Уже на первом же канале, я увидел изменения при нажатии кнопок пульта. На втором канале, сигналов при нажатии стало еще больше, на 3м еще, а к 7му все прекратилось. Значит золотая середина - это канал номер 3, по нему и идут данные. Сканер, который получился в итоге выложил сюда:

https://github.com/CodeName33/NRFRemote/blob/main/NRF24Scanner.ino

Итак, пол дела сделано (я так думал), пульт работает по нужному протоколу и частота найдена, осталось только получать данные и использовать их! Как все просто в ожидании. Теперь реальность. Все не так! Как оказалось, nRF24L01 это не вай-фай и в нем нельзя сказать "получай все". Он требует задания скорости, канала и адреса, и без этого ничего получать не будет. Канал я уже знаю, осталось две переменные, скорость и адрес, и если первое можно подобрать (их всего три), то на подбор второго (адрес от 3х до 5 байт) уйдут всего лишь, миллиарды лет. Как хорошо, что они у меня, есть, погнали! (нет). Путем гугления выяснилось, что модуль можно немного обмануть. Адрес может быть от 3х до 5байт, но если передать ему, что длина адреса 2 байта, а само значение 0x55 или 0xAA, то можно таким образом получать все! В одном из случаев данные будут сдвинуты на 1 бит (в зависимости от того, как они передаются передатчиком). Ну что ж, начнем с адреса 0x55 и скорости в 2Mbit и к моему удивлению, это сработало с первого раза, я тут же стал получать кучу пакетов, а зажав кнопку на пульте, я заметил, что среди этих пакетов стали появляться пакеты с однотипным началом:

Естественно, я тут же поставил фильтр по этим 4 первым байтам и о чудо! Пакеты начали появляться, только при нажатии кнопок с пульта:

Успех был так близко, осталось только запомнить какие данные идут от каких кнопок и все решено, но вот тут возникла проблема. При нажатии на одну и ту же кнопку, каждый раз приходили разные данные, точнее если отсеять мусор в конце, я заметил 2 варианта и по началу я решил, что добавлю их оба, но позже, уже начав добавлять коды всех кнопок, я понял, что вариантов уже не 2, а 4. И добавлять на каждую кнопку все 4 варианта кодов было не круто. Да и вообще, не круто распознавать кнопку по данным сырого пакета, надо этот пакет хотя бы расшифровать. Возможно я в нем найду неизменные данные, по которым гораздо проще смогу определять, какая кнопка был нажата. И если формат самой секции данных в пакете знает только производитель пульта (HP), то формат пакета nRF24L01 секретом не является, вот он:

По этой схеме я и стал пытаться разобрать данные:

И все бы тут хорошо и адрес постоянный и доп адрес (5й байт адреса) меняется в зависимости от группы нажатой кнопки, но вот размер данных, я честно пытался взять его из чисел 13, 12, 159 и 130 извлекая 6 бит. Но выходил полный бред, 12 и 13 давали число 3, что явно слишком мало, а 159 - это 39, что явно нарушает все правила протокола, допускающего не более 32 байт данных. Притом, что данные внутри пакета дальше шли даже вроде и не плохо. Чертов Packet Control Header занимает именно 9 бит, и это значит, что все байты дальше надо сдвигать на 1 бит, что я и делал. И вроде все похоже. Но не совсем. Все равно на одну и ту же кнопку, я получал разные данные, странные данные, хотя часть из них выглядела очень правдоподобно. Но времени было уже около 3х ночи, и еще через 3 часа первые петухи начнут петь о том, какой я лошара, и мне нечего будет им ответить. Совсем нечего. На этом я плюнул, и лег спать. Утро вечера мудренее, я уже не раз в этом убеждался и решил, поверить этой пословице снова.

Этап вязки

Мое утро настало позже, чем я ожидал, но все таки подкинуло еще пару идей, я снова начал изучать эти цифры, пытаться крутить биты туда-сюда, понять что я упустил, но все подтверждало то, что у меня все было правильно, а картина все равно не сходилась. Я потратил еще пару часов и результат был нулевой. Черт, что же не так? Я же вроде не дурак? У меня даже справка есть! Мне её выдавали, когда я права менял. С тех пор не должно было ничего сильно измениться. Я еще раз понажимал две соседние кнопки на пульте и кажется начал кое-что понимать. Одна кнопка давала что-то типа последовательности 247 0 где-то в середине данных, другая 246 128 на тех же позициях. 247 и 246 это наверное коды кнопок, они рядом, логично, что соседние кнопки имеют отличие на кода единицу. Но вот следующий байт это 0 в одном случае и 128 в другом. Но ведь 0 это 00000000 по битам, а 128 это 10000000. Такое ощущения что эта единица заехала сюда зря, она из предыдущего байта. Но я точно все правильно смещаю, на 1 бит, как и должно быть, без смещения было еще хуже, было вообще 01000000, что равно 64... Стоп! Все если и правда все смещено еще на 1 бит! Ведь именно этим и отличаются адреса 0x55 и 0xAA которые используются для "хакерского" приема всех пакетов.

Флешбэк:

Адрес может быть от 3х до 5байт, но если передать ему, что длина адреса 2 байта, а само значение 0x55 или 0xAA, то можно таким образом получать все! В одном из случаев данные будут сдвинуты на 1 бит (в зависимости от того, как они передаются передатчиком)

Я определенно дурак, я ведь уже пробовал менять 0x55 на 0xAA до этого, но в этом случае у меня вообще переставали приходить мои пакеты... А они так и должны были сделать! Все сдвинулось на 1 бит, и адрес тоже, а я продолжаю фильтровать пакеты по первым байтам 65, 223, 152, 111, а они тоже меняются! Я отменил фильтр и снова нашел адрес пульта в море сигналов, он и правда стал другим:

И наконец-таки, поле с размером данных стало адекватным, теперь пакеты можно расшифровать:

Но самое главное, теперь при нажатии одной и той же кнопки, данные всегда приходят одни и те же (на самом деле не всегда, а почти всегда, но это уже ошибки связанные с загруженностью 2.4Ghz канала, по идее должно отсеиваться, если проверять CRC). Далее я забил данные всех кнопок в массив, чтобы их распознавать, и при нажатии кнопок в порт стали выводиться адекватные данные, с которыми, в свою очередь можно работать в EventGhost:

Я научился понимать, какие коды соответствуют нажатию клавиши, а какие тому, что все клавиши в группе отпущены. Это важно, для того, чтобы можно было делать авто-повтор нажатия для некоторых клавиш при их зажатии на пульте (перемотка, например или громкость), а для некоторых не делать (Play/Pause, например). В EventGhost все настраивается очень просто, для начала добавляется плагин ком-порта:

Дальше все что приходит из этого ком-порта можно видеть в логе программы:

И назначать макросы на эти события:

Итоговый результат скетча здесь:

https://github.com/CodeName33/NRFRemote/blob/main/NRF24Remote.ino

CRC, я все же решил не проверять, т.к. при включении его проверки (вариант с 1 байтом CRC) почему-то отсеивается довольно приличная часть пакетов, которая на самом деле имеет вполне себе валидные данные внутри. Может быть что-то еще можно подкрутить, но пока сойдет и так. Еще у пульта выявился еще один неприятный момент: Часть его кнопок работает довольно странно (крестовина и цифры). После нажатия одной из этих кнопок, пульт довольно долго шлет еще какие-то команды и ту команду, которую я посчитал за "кнопка больше не нажата", он может присылать с задержкой до 1 сек. Это очень много и можно поставить крест на быстрой навигации стрелочками (она стала медленная). Вероятно это как-то связано с особенностями его работы, может быть приемник ему, что-то должен отвечать, а может я что-то неверно понял, но на данный момент мне не удалось это победить. Возможно, еще поковыряю.

В будущем хочу отказаться от EventGhost и перевести проект на Arduino Pro Micro, которая умеет прикидываться USB клавиатурой и сразу отправлять нужные нажатия клавиш, работая без посредников. В этом случае пульт сможет работать не только в разных ОС, без доп. программ, но и с телевизорами и Андроид устройствами. Но пока все так, как есть. Спасибо за внимание!

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru