Совершенствуя свой комнатный термостат, о котором писал раньше, я задался целью дополнить его беспроводным датчиком температуры для измерения температуры воздуха на улице, собрать термостат с питанием от батареек и заменить модули приемник-передатчик RF 433MHz другой парой радиомодулей с большей дальностью связи при напряжении питания не более 3В. По ходу решения этих задач вырисовалась автономная метеостанция, речь о которой пойдет ниже.
Метеостанция состоит из двух узлов, назовем их для простоты анализатором и термометром. Связь между узлами — беспроводная, по радиоэфиру.
Анализатор, построен на контроллере ATMEGA328P, измеряет температуру и влажность в помещении (датчик температуры и влажности DHT22) и напряжение питания анализатора, которое обеспечивают две батарейки АА 1,5В. На контроллер поступает сигнал с приемника LoRa, который по эфиру принимает информацию с термометра (выносного датчика). Информация с контроллера выводится на ЖК-дисплей NOKIA 5110.
В термометре, собранном тоже на контроллере ATMEGA328P, измеряется температура воздуха на улице (датчик температуры DS18B20) и напряжение питания выносного узла, организованного на двух батарейках АА 1,5 В. Передатчик LoRa этого узла передает температуру и напряжение питания на анализатор.
Контроллер ATMEGA328P и передатчик LoRa термометра для экономного расходования заряда батареек после измерений и отправки информации переводятся в режим сна. Напряжение питания на датчик DS18B20 программно подается только на время измерения температуры. Измерения и отправка данных с термометра выполняется с периодом около одной минуты.
В таком же режиме работа-сон работает и анализатор. Продолжительность работы контроллера и приемника анализатора несколько больше одной минуты (около 65 сек). Это сделано для уверенного приема сигнала с термометра — ведь работа термометра и анализатора не синхронизированы. Затем ATMEGA328P и приемник LoRa переводятся на 14 мин в режим сна до пробуждения и старта очередного цикла. Питание на DHT22 подается только во время измерений.
Для программирования режима сна контроллеров ATMEGA328P используется библиотека LowPower.h.
С разрядом батареек на них понижается величина напряжения.
Нижний предел рабочего напряжения питания контроллера ATMEGA328P — 1,8В. При этом, заводская установка фьюз ATMEGA328P выполнена на мониторинг порога напряжения питания 2,7В, поэтому необходимо изменить заводские установки фьюз на мониторинг порога 1,8В, чтобы гарантировать работу контролера при напряжении питания ниже 2,7В при питании от батареек.
Внутренний генератор контроллера может не запускаться на частоте 16 МГц при напряжении питания 3В или несколько ниже. У меня оба контроллера работают с кварцем 16 МГц при пониженном напряжении питания 2,7…2,8В, поэтому я не стал менять кварц 16 МГц на 8 МГц.
Для сборки устройства понадобятся компоненты, перечень которых и их ориентировочная стоимость по ценам сайта AliExpress приведены в таблице.
Компонент | Цена, $ |
анализатор | |
Контроллер ATMEGA328P-PU | 1,59 |
Датчик температуры и влажности DHT22 | 2,34 |
Приемник-передатчик LoRa Rа-01 | 3,95 |
ЖК-дисплей NOKIA 5110 | 1,91 |
Макетная (монтажная) плата, монтажные провода, батарейки АА, кварцевый резонатор 16 МГц (8 МГц), резисторы и др. | 4,00 |
термометр | |
Контроллер ATMEGA328P-PU | 1,59 |
Датчик температуры DS18B20 | 0,63 |
Приемник-передатчик LoRa Rа-01 | 3,95 |
Макетная плата (стеклотекстолит), монтажные провода, батарейки АА, кварцевый резонатор 16 МГц (8 МГц), резисторы и др. | 4,00 |
Всего (примерно): | 24 |
Анализатор
Мозг анализатора – контроллер ATMEGA328P. Он принимает сигналы с датчика DHT22 и формирует сигналы управления приемником LoRa и дисплеем NOKIA 5110.
В Интернете много нареканий на низкую точность измерения влажности датчика DHT22. На сегодня есть альтернатива: более современные датчики температуры и влажности HTU21 (GY21), (Vcc = 3...5 В), Si7021,(Vcc = 1,9… 3,6 В), SHT21, (Vcc = 2.1….3,6 В).
Я использую DHT22, поскольку расхождение между показаниями влажности моего экземпляра этого датчика и серийно выпускаемого термогигрометра LaCrosse WS-9024IT составляют не более 8-ми единиц, что вполне приемлемо для бытовых целей. Расхождение между показаниями влажности сильно увеличиваются, если величина напряжение питания DHT22 ниже 3В. Это и понятно, ведь напряжение питания DHT22 должно находиться в пределах 3…5В. Суммируя – идеально в этих условиях в схему анализатора вписывается датчик Si7021.
На картинке ниже — цоколевка элементов метеостанции.
Фьюзы и многое другое различных контроллеров, в том числе ATMEGA328P, можно читать и редактировать утилитой SinaProg. Если вы впервые сталкиваетесь с этой программой, то несмотря на интуитивно понятный интерфейс, не пытайтесь после инсталляции приложения начинать с ним работать. Сначала почитайте тут, где HWman приводит необходимые дополнения SinaProg при использовании Arduino UNO и подробные инструкции.
Советую вначале прочитать заводские установки фьюз ATMEGA328P и сохранить их значения, чтобы вернуться к ним в случае неудачи. В моих контроллерах заводские установки фьюз бит такие: LOW: 0xFF, HIGH: 0xDE, EXTENDED: 0x05 (Vcc=2.7V, BODLEVEL=101). Фьюзы на мониторинг порога 1,8В: LOW: 0xFF, HIGH: 0xDE, EXTENDED: 0x06 (Vcc=1.8V, BODLEVEL=110).
Скетч анализатора для загрузки в ATMEGA328P находится под спойлером.
/*
* Автономная метеостанция на контроллере ATMEGA328P и питанием от батареек с беспроводным выносным датчиком, анализатор
*/
#include <SPI.h>
#include <LoRa.h>
#include "DHT.h"
#define DHTPIN 3 // what digital pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);
float Tin=0;
int Hin=0;
float BatteryInLevel; // напряжение батареи базы
String LoRaData, Tout_str, BatteryInLevel_str, BatteryOutLevel_str;
//sleep
#include <LowPower.h>
#define PowerDHT (4) //пин питания DHT22
unsigned int sleepCounter;
//Nokia 5110
#include <SPI.h>
#include <Adafruit_GFX.h> //https://esp8266.ru/forum/threads/esp8266-5110-nokia-lcd.1143/#post-16942
#include <Adafruit_PCD8544.h> //https://esp8266.ru/forum/threads/esp8266-5110-nokia-lcd.1143/#post-16942
//timer
#include <SimpleTimer.h>
SimpleTimer timer;
Adafruit_PCD8544 display = Adafruit_PCD8544(5, 7, 6);
void sendSensor(){
digitalWrite(PowerDHT, 1);
delay (2000);
Hin = dht.readHumidity();
Tin = dht.readTemperature();
/* if (isnan(Hin) || isnan(Tin)) {
// Serial.println("Failed to read from DHT sensor!");
return;
}*/
digitalWrite(PowerDHT, 0);
// измерение напряжения батареи:
analogReference(INTERNAL);
int sensorValue = analogRead(A4);
BatteryInLevel = (sensorValue * 3.2 / 1024);
}
void draw(){
display.clearDisplay();
//Tin
{
display.setTextSize(2);
display.setCursor(8,0);
display.println (Tin, 1); // один знак после запятой
display.setCursor(68,0);
display.println("C");
}
//Hin
{
// Hin = 58; // ТЕСТ, удалить!
display.setTextSize(2);
display.setCursor(8,16);
display.println(String(Hin)+ "%");
}
//Tout
{
char chr_Tout [12];
Tout_str.toCharArray(chr_Tout, 5);
display.setTextSize(1);
display.setCursor(50,16);
display.println(String(chr_Tout)+"C");
}
// Battery Out Level
{
char chr_BatteryOutLevel [12];
BatteryOutLevel_str.toCharArray(chr_BatteryOutLevel, 4);
display.setTextSize(1);
display.setCursor(2,32);
display.println("BAT Out: " + String(chr_BatteryOutLevel)+"V");
}
// Battery In Level
{
display.setTextSize(1);
display.setCursor(2,40);
display.println("BAT In: ");
display.setCursor(56,40);
display.println(BatteryInLevel, 1); //один знак после запятой
display.setCursor(74,40);
display.println("V");
}
display.display();
/* Serial.println("Tin: " + String(Tin)+"*C");
Serial.println("Hin: " + String(Hin)+"%");
Serial.println("Tout: " + String(Tout_str)+"*C");
Serial.println("BAT_In: " + String(BatteryInLevel)+"V");
Serial.println("BAT_Out: " + String(BatteryOutLevel_str)+"V");
Serial.println("......"); */
}
void sleepDevice(){
// sleepCounter = 65 - 10 min
// sleepCounter = 91 - 14 min
for (sleepCounter = 91; sleepCounter > 0; sleepCounter--) //91!!!
{
LoRa.sleep ();
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
LoRa.sleep ();
}
void SignalReception (){
// try to parse packet
int packetSize = LoRa.parsePacket();
if (packetSize) {
// read packet
while (LoRa.available()) {
LoRaData = LoRa.readString();
// Serial.println("Принято: "+(LoRaData));
}
int pos1 = LoRaData.indexOf('#');
Tout_str = LoRaData.substring(0, pos1);
BatteryOutLevel_str = LoRaData.substring(pos1+1, LoRaData.length());
}
}
void setup() {
// Serial.begin(9600);
pinMode(PowerDHT, OUTPUT);
// инициализация и очистка дисплея
display.begin();
display.clearDisplay();
display.display();
display.setContrast(60); // установка контраста
display.clearDisplay();
display.setTextSize(2);
display.setCursor(12,16);
display.println (">>>>>"); //индикация начала работы при включении
display.display();
dht.begin();
sendSensor();
draw();
while (!LoRa.begin(433E6)) {
// Serial.println(".");
delay(500);
}
// Диапазон для синхрослова – между «0-0xFF».
LoRa.setSyncWord(0xF3);
// Serial.println("LoRa Initializing");
timer.setInterval(20000, sendSensor);
timer.setInterval(5000, draw);
timer.setInterval(62000, sleepDevice);
}
void loop() {
SignalReception();
timer.run();
}
Для работы с контроллерами ATMEGA328P в качестве программатора я использую плату Arduino UNO. Процесс установки загрузчика и загрузки скетчей в контроллер ATMEGA328 с помощью платы Arduino UNO подробно описан тут. На Youtube есть хорошее видео на эту тему.
В скетче закомментированы команды вывода в монитор последовательного порта (Serial). В случае необходимости — раскомментируйте команды.
Цикл начинается с прослушивания эфира и приема информации приемником LoRa. Таймером установлено время прослушивания — 62 сек. В это время с периодом 5 сек обновляется информация на дисплее NOKIA и с периодом 20 сек (3 раза) датчиком DHT22 проводятся измерения температуры, влажности, а также уровень напряжения батареек через один из аналоговых входов контроллера. Напряжение питания на DHT22 подается только во время измерений с минимальной задержкой 2 сек, при которой датчик еще работает. Выход АЦП в скетче масштабирован на напряжение новых батареек, которое составляет 3,2В (1,6В х 2). Время прослушивания эфира выбрано несколько больше 1 мин для уверенного приема одной пачки с термометра, который работает на передачу с периодом 1 мин, но об этом ниже. Затем на 62-ой секунде контроллер и приемник переводятся в режим сна, который длится примерно 14 мин, т.е. период цикла «работа/сон» анализатора — около 15 мин. Замечу, что режим сна в анализаторе – это вынуждения мера, призванная существенно уменьшить потребление. С другой стороны – за 15 минут температура и влажность воздуха кардинально не изменятся. Как показал расчет времени работы от батареек, режим сна можно уменьшить до 8-9 мин, но я не стал этого делать, поскольку в будущем узел будет дополнен функциями термостата, что приведет к увеличению потребления.
Для сравнения — в таблице ниже приведены характеристики термогигрометра LaCrosse WS-9024IT и анализатора с этого проекта. Большинство параметров LaCrosse из таблицы не приводятся в ее техническом описании, а были измерены. Хотел дополнить таблицу результатами аналогичных любительских разработок, но, к сожалению, ничего не нашел.
Параметр | LaCrosse WS-9024IT | Сadil_TM |
Питание | 2хАА, 3В, Durasell | 2хАА, 3В, GP Ultra+, 2.72 Wh |
Потребление сна | 8 мкА | 10 мкА |
Продолжительность сна | 14 мин | |
Операционное потребление | 200 мкА | 3 мА |
Продолжительность работы | 65 сек | |
Период цикла работа/сон | 30 сек | 15 мин |
Время эксплуатации | более 2 лет | около 1 года |
Расчет времени работы.
Средний ток потребления: 3 мА / 15 + 0,01 мА = 0,21 мА, где 15 – скважность. Емкость батарейки GP Ultra+ в мА*час: 2.72 Вт*час / 1,5 В = 1,81 А*час = 1800 мА*час. Время эксплуатации: 1800 мА*час / 0,21 мА = 8600 час (11,9 мес).
Уточню:
— Расчет очень приблизительный, поскольку в основу расчета положено максимальное (пиковое) потребление анализатора.
— Время работы LaCrosse приведено, исходя из собственного опыта. Этот девайс у меня давно.
Термометр
Емкость и напряжение батареек на морозе сильно понижаются. Поэтому, чтобы не подвергать батарейки да и устройство в целом столь сильным испытаниям я вынес за пределы помещения только датчик температуры DS18B20, а сам узел и батарейки находятся в помещении. DS18B20 соединяется с платой узла тонким трехжильным проводом. Это решение я подсмотрел в своей серийной метеостанции – разработчики уверены, что в квартире всегда найдется щель для укладки провода диаметром в несколько миллиметров.
Фьюзы для ATMEGA328P термометра такие же, как и для анализатора.
Узел термометра тоже построен на контроллере ATMEGA328P. Он принимает сигнал с датчика DS18B20, измеряет напряжение питания и управляет передатчиком LoRa.
Скетч термометра – под спойлером.
/*
* Автономная метеостанция на контроллере ATMEGA328P и питанием от батареек с беспроводным выносным датчиком, термометр
*/
#include <OneWire.h>
OneWire ds(7); //pin 13, Atmega328P
#include <SPI.h>
#include <LoRa.h>
#include <LowPower.h>
#define PowerDS18B20 (6) //pin 12 (Atmega328P), питаниe DS18B20
unsigned int sleepCounter; // счетчик, задающий время сна
float Tout; //температура
int i; // отсчет числа циклов при включении устройства интенсивного режима(20 циклов за 1 мин)
String messageTout; // LoRa-сообщение
float batteryLevel; // напряжение батареи
const int batteryPin = A0; // pin 23 (Atmega328P), к которому подключена батарея для измерения напряжения
void Measurement (){
//измерение температуры
byte data[2];
digitalWrite(PowerDS18B20, 1);
ds.reset();
ds.write(0xCC); // пропуск поиска по адресу (1 датчик)
ds.write(0x44); // команда на измерение
delay(700);
ds.reset();
ds.write(0xCC);
ds.write(0xBE); // передача регистров со значением температуры
data[0] = ds.read();
data[1] = ds.read();
Tout = ((data[1] << 8) | data[0]) * 0.0625;
// Serial.println("Tout= "+ String(Tout));
digitalWrite(PowerDS18B20, 0);
// измерение напряжения батареи:
analogReference(INTERNAL);
int sensorValue = analogRead(A0);
batteryLevel = (sensorValue * 3.2 / 1024);
// Serial.println("BAT= "+ String(batteryLevel));
}
void SetSynchLoRa () {
int counter = 0;
while (!LoRa.begin(433E6) && counter < 10) {
// Serial.print(".");
counter++;
delay(500);
}
/* if (counter == 10) {
// Serial.println("Failed to initialize ...");
}*/
LoRa.setSyncWord(0xF3);
}
void SendMessage (){
// отправка данных (температура, напряжение батареи)
messageTout = String(Tout) + "#" + String(batteryLevel);
// Serial.println(messageTout);
delay(250);
LoRa.beginPacket();
LoRa.print(messageTout);
LoRa.endPacket();
}
void setup() {
// Serial.begin(9600);
// Serial.println("Initializing ...");
pinMode(PowerDS18B20, OUTPUT);
SetSynchLoRa ();
}
void loop() {
// Serial.println("");
// Serial.println("i = " + String(i));
if (i >= 30){// i >= 30 (1 мин) - обычный режим (измерение, отправка - 1 раз/1 мин)
for (sleepCounter = 5; sleepCounter > 0; sleepCounter--)
{
LoRa.sleep ();
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
Measurement ();
SendMessage ();
LoRa.sleep ();
} else
{ //интенсивный режим продолжительностью 1 мин, отправка - 1 раз/2 сек
Measurement ();
SendMessage ();
delay (1000);
}
i++;
if (i >= 30) i = 30; //уменьшение разрядности заполнения счетчика
}
Вначале при подключении питания термометр на протяжении одной минуты работает в интенсивном режиме. Он измеряет температуру, напряжение батареек и посылает их значения в эфир через каждые 2 сек. Это сделано для удобства. Допустим, при замене батареек или отладке не придется ждать минуту. Информация с датчика появится на дисплее анализатора в первые секунды после подключения батареек термометра и анализатора. Естественно, стоит поторопиться и не делать разрыва во времени больше минуты между подключением батареек на обоих узлах.
Затем выносной датчик переходит в штатный режим. После измерений и отправки информации, которые длятся несколько больше 1-ой секунды, контроллер и передатчик программно переводятся в режим сна длительностью около 1-ой минуты.
Расчет времени работы.
Средний ток потребления: 8 мА / 60 + 0,01 мА = 0,14 мА, где 60 – скважность. Емкость батарейки GP Ultra+, (мА*час): 2.72 Вт*час / 1,5 В = 1,813 А*час = 1800 мА*час. Время эксплуатации: 1800 мА*час / 0,14 мА = 12800 час (18 мес).
Предыдущие уточнения относительно точности рассчитанного значения времени работы от одного набора батареек остаются в силе.
И сравнительная таблица. В ней есть результаты пары похожих проектов из Интернета.
Параметр | LaCrosse WS-9024IT | maniacbug | avs24rus | Сadil_TM |
Питание | 2хААА, 3В, Durasell | 3В, CR2450 Renata, 540 мА*ч | 3В, CR2450, 550-610 мА*ч | 2хАА, 3В, GP Ultra+, 2.72 Wh |
Потребление сна | 10 мкА | 0,14 мА (?) | 14 мкА | 10 мкА |
Продолжительность сна | 1 мин | |||
Операционное потребление | 90 мкА | 13,57 мА | 16 — 18 мА | 8 мА |
Продолжительность работы | 0,027 сек | 1 сек | ||
Период цикла работа/сон | 5 сек | 1 мин | 10 мин | 1 мин |
Время эксплуатации | более 2 лет | более 0,5 года | около 1,5 года |
Если узлы собраны без ошибок, то на дисплее увидим такую картинку:
Из сравнительных таблиц видно, что операционное потребление любительских устройств на два порядка выше (более 100 раз!) выше, чем в аналогичной за функциями промышленной LaCrosse. Например, 8 мА против 90 мкА для выносного датчика и 3 мА: 200 мкА для анализатора. Потребление сна примерно одинаково – около 10 мкА. Такое разительное отличие в операционном потреблении объясняется, на мой взгляд, тем, что контроллеры в любительских схемах запрограммированы на языке Arduino IDE, а в промышленных продуктах скорее всего на одном из языков низкого уровня или C#/C. Если же использовать регистры микроконтроллера, язык программирования C, то, уверен, можно выйти на потребление, сравнимое с промышленными образцами. Впрочем, это очень убедительно экспериментально показал HWman в своей публикации «Почему многие не любят Arduino». Выполнение простейшего скетча до десятка строк (Blink), выполненного на языке в одном случае Arduino и в другом — C приводит к проигрышу в производительности в 26 раз. Короче, повышенное потребление ресурсов – это плата за комфорт и небольшие усилия со стороны программиста – остальное за него в Arduino сделают «прожорливые» функции среды разработки. Предчувствую — придется напрячься и освоить C#/C…
Выводы
• Собранные анализатор и термометр имеют слишком большое операционное потребление тока по сравнению с промышленными образцами. Для уменьшения энергопотребления в оба узла введен режим сна. Существенно уменьшить операционное потребление можно, переписав скетч на языке C#/C.
• К двум батарейкам питания в схемах напрашивается третья, тогда автоматически решаются следующие проблемы — отпадает необходимость в переустановке фьюз, устойчивая работа контроллера на частоте 16 МГц, работа датчиков DHT22, DS18B20 вдали от нижнего порога напряжения питания. Последнее немаловажно, поскольку напряжение питания подается на датчики не прямо, а программно через ключ с пина контроллера, на котором падает порядка 1В.
• Применение радиомодулей LoRa, с дальностью связи при прямой видимости до 1,5 км, позволило установить устойчивую связь в пределах квартиры с питанием модулей на уровне 3В.
Ссылки по теме
Узел беспроводного датчика с низким энергопотреблением
Беспроводный Lighting-Sensor с питанием от CR2450
Термометр с беспроводной передачей данных
Превращаем Arduino в полноценный AVRISP программатор
LoRa и сон
Узнайте о битах конфигурации ATmega328P и о том, как использовать их с внешним кварцевым резонатором
Калькулятор фьюзов AVR
Почему многие не любят Arduino
Грандиозное тестирование батареек
Батарейки на морозе
Комментарии (47)
Javian
08.10.2019 08:17+1Попробуйте вот так отключать нагрузку habr.com/ru/post/386735
Cadil_TM Автор
08.10.2019 08:54Попробуйте вот так отключать нагрузку habr.com/ru/post/386735
Модуль TIDA-00484 TI Design — фантастика! Обязательно посмотрю этот модуль.Javian
08.10.2019 11:18Там фокус в TPL5111 таймере и выключателе нагрузки TPS22860. Они сами потребляют микроскопический ток и с фиксированной частотой включают прожорливое устройство для передачи данных, а потом отключают.
Cadil_TM Автор
08.10.2019 12:21Там фокус в TPL5111 таймере и выключателе нагрузки TPS22860. Они сами потребляют микроскопический ток и с фиксированной частотой включают прожорливое устройство для передачи данных, а потом отключают.
Спасибо за уточнения! Но, собственно, неважно что вводит модули в режим сна: таймер контроллера или внешний таймер. К тому же многие модули управляются по нескольким проводам (протокол SPI). Справится с их включением/выключением выключатель нагрузки TPS22860?Javian
08.10.2019 12:55200 mA Maximum Continuous Switch Current
В копилку идей:
Вотериус: Передача показаний воды на телефон по Wi-Fi (4 года от батареек) — 3 батарейки АА
Метеостанция на Arduino от А до Я. Часть 4. Заоконный датчик — используется солнечная батарея.
Схема питания от батарей с повышающим стабилизатором NCP1400
smart_alex
08.10.2019 08:32Такое разительное отличие в операционном потреблении объясняется, на мой взгляд, тем, что контроллеры в любительских схемах запрограммированы на языке Arduino IDE
Дело не в Arduino, а в опыте и квалификации проектировщика. В Arduino никто не мешает в критических местах использовать низкоуровневый код, программирование регистров и т. д. А также никто не мешает использовать здравый смысл и смекалку для минимизации потребления датчика.
Например, на модифицированной Pro Mini и nRF24L01 прекрасно делаются датчики со временем жизни от 1 года до 10 лет от одного комплекта батареек, в зависимости от типа датчика и режима его работы.
Анекдот на эту тему из жизни. Во время беседы с представителем «Стрижа», я задал ему вопрос: «Скажите, а как вам удалось добиться времени работы датчика 10 лет?». Ответ: «А наши датчики выходят на связь 1 раз в сутки». :)Cadil_TM Автор
08.10.2019 09:20В Arduino никто не мешает в критических местах использовать низкоуровневый код, программирование регистров и т. д.
Это полумеры и шараханье из одной крайности в другую. Хотя, не спорю — вторая крайность требует соответствующей квалификации. Код на языке С — мне кажется оптимальным решением.
Cadil_TM Автор
08.10.2019 10:00… на модифицированной Pro Mini и nRF24L01 прекрасно делаются датчики со временем жизни от 1 года до 10 лет от одного комплекта батареек, в зависимости от типа датчика и режима его работы.
Сначала надо победить nRF24L01. Посмотрите как мучаются люди с nRF24L01 — 114 страниц форума за несколько лет! Я тоже возился с этим радиомодулем. Возможно, в будущем дополню эту статью.smart_alex
08.10.2019 10:28Люди может и мучаются, но если понимать, что делаешь, то nRF24L01 работает как часы. Вот прямо сейчас делаю скриншот одного из своих работающих проектов.
Это пример работы беспроводного датчика расхода воды на Pro Mini и nRF24L01. Два канала, холодная и горячая вода, период отсылки показаний (актуализации) в системе (AMS) 5 минут.
Расчётное время работы датчика в динамическом режиме (период 5 минут) — 2 года, в тарификационном режиме (период 1 день) — 6+ лет.
Всё сделано на Wiring (нативом языке Ардуино) в Arduino IDE.
Cadil_TM Автор
08.10.2019 11:04Где можно посмотреть ваш проект? Дополню хотя бы сравнительные таблицы.
smart_alex
08.10.2019 11:11+1Публичные версии системы, включая (работающие) примеры nFR24 датчиков здесь:
https://hi-lab.ru/arduino-mega-server/details/download
Частные проекты и разработка здесь:
https://hi-lab.ru/arduino-mega-server/ams-pro
Polaris99
08.10.2019 14:041 раз в 5 минут — это такая скважность, учитывая возможную скорость передачи по BLE, что 2 года от батарейки выглядит издевательством.
igrushkin
08.10.2019 13:55мучаются птому, что изобретают велосипед. Я использую либу MySensors и получаю удовольствие. Сейчас правда перешел на nrf52
Polaris99
08.10.2019 14:01+1Если использовать низкоуровневый код и программирование регистров, то разработчику и Ардуина не нужна, так что не вижу никакого противоречия в словах автора :)
Pafnutyi
08.10.2019 12:23Давно-давно повторял(не моя придумка) проджект температурного датчика на MSP430 в качестве передатчика был контур на 200Кгц ударно возбуждаемый с ножки микроконтролера — никаких радиомодулей ;). Приёмник такой же контур + усилитель и на компаратор встроенный в МК. Дальность была около 20..25 метров на одной не новой солевой батарейке датчик продержался больше года, потом механически был повреждён сосулькой…
gerasimenkoao
08.10.2019 13:58Такое разительное отличие в операционном потреблении объясняется, на мой взгляд, тем, что контроллеры в любительских схемах запрограммированы на языке Arduino IDE
Вот не нужно валить все с больной головы на здоровую!
Моя "ардуинка"(голый микроконтроллер) от двух батареек потребляет 0.5 мА в активном режиме(отрабатывая скетч из Arduino IDE), и знаете почему?
Она работает на 1МГц!
Удивляет то, что коль уж зацепились с фьюзами, не перешли хотя-бы на 8МГц (внутренний генератор)
А впрочем, не удивляет — сам столкнулся со следующей вещью — многие библиотеки заточены именно под частоту Атмеги 16МГц!
Пример — библиотека того-же DHT11/DHT22 — прекрасно работает на быстрой версии Arduino,
на версии Pro Mini 8Mhz 3.3В приходится править саму библиотеку, и дело не в напряжении — проверял, но даже с правками — работа нестабильна.
AM2320 — аналогичная картина.
А вообще автор-молодец!
Polaris99
08.10.2019 14:05многие библиотеки заточены именно под частоту Атмеги 16МГц
П — платформонезависимость! Ардуино во всей своей красе.gerasimenkoao
08.10.2019 14:33Вы хотите сказать, что для микроконтроллеров есть библиотеки, одинаково работающие и на Atmega328, и на STM32, и на ESP8266???
Вот хотя-бы для DHT22
Polaris99
08.10.2019 14:42+1То есть, зависимость от частоты кварца — это нормально, Вы это хотите сказать? Да в гробу я видал такие библиотеки, которые даже в рамках одной модели микроконтроллера не способны нормально работать. А судя по Вашим словам, в мире Ардуино это нормально.
iig
09.10.2019 10:56Наверное, есть библиотеки, пихающие данные в регистры напрямую, но не умеющие в F_CPU.
FGV
09.10.2019 18:49рамках одной модели микроконтроллера не способны нормально работать.
да как бы:
Atmega328, и на STM32, и на ESP8266
все разные мк, с абсолютно разной архитектурой и ядрами.
iig
10.10.2019 12:54все разные мк, с абсолютно разной архитектурой и ядрами.
Как минимум на Atmega328 и на ESP8266 ардуиновский код вполне работает. Так что ардуиновские либы могут работать на разных архитектурах, если под ту архитектуру есть ардуиновское ядро. П — платформонезависимость, ага ;)FGV
10.10.2019 16:17Как минимум на Atmega328 и на ESP8266 ардуиновский код вполне работает.
ага. а как реализовано?
ifdef esp8266
//шмат кода для есп
...
ifdef atmega
//шмат кода для атмеги
...
Так что ардуиновские либы могут работать на разных архитектурах, если под ту архитектуру есть ардуиновское ядро.
Адуриновская обертка единственное что может организовать универсально — программный ногодрыг с уартом. Остальная периферия esp8266/32 фактически не задействуется, собственно понятно почему, иначе универсальности не будет.
П — платформонезависимость, ага ;)
Как бы абсолютно не нужная вещь получатся не находите? Уж ногами подрыгать по таймеру / байты по уарту послать это надо страниц 40-20 любого datasheet-а осилить (заодно узнаете архитектуру). Ну или открыть пример из sdk аля gpio / hello world / uart, там и на страницу не наберется.
iig
10.10.2019 18:54а как реализовано?
ifdef esp8266
//шмат кода для есп
…
ifdef atmega
//шмат кода для атмеги
…
Если библиотеку писали правильные программисты — то да. Разница в архитектуре будет закодирована на #ifdef'ах, а интерфейсная часть будет одинаковая для любой поддерживаемой платформы.
Адуриновская обертка единственное что может организовать универсально — программный ногодрыг с уартом. Остальная периферия esp8266/32 фактически не задействуется, собственно понятно почему, иначе универсальности не будет.
Дисплей 1602 по I2C подключается одинаково что к ардуине что к 8266. Никакая периферия вроде не страдает ;)FGV
11.10.2019 08:36Дисплей 1602 по I2C подключается одинаково что к ардуине что к 8266.
Учитывая что у 8266 i2c софтварный то разницы особо нет. Подцепите sd-карточку, или spi-дисплей. Чую на адурине что для 8266 что для avr все через digitalread/write написано.
Никакая периферия вроде не страдает ;)
А чего ей страдать? Речь о том что она не используется :)
iig
11.10.2019 10:50П — переносимость. О — оптимальность. П != О.
Учитывая что у 8266 i2c софтварный то разницы особо нет.
В ардуиновском ядре для 8266 своя реализация SPI, софтовая, да. А для тех контроллеров, что умеют поддержку SPI — аппаратная. SPI.h внутри разные, а интерфейсы одинаковые.
igrushkin
08.10.2019 14:50поставил (+) «за старание». но честно говоря, в конце 2019 года хотелось бы видеть какие-то прорывные статьи, а не очередную погодную станцию на античном DHT22
Cadil_TM Автор
09.10.2019 07:44поставил (+) «за старание». но честно говоря, в конце 2019 года хотелось бы видеть какие-то прорывные статьи, а не очередную погодную станцию на античном DHT22
У каждого свое понимание прорыва. В общем-то, в избитой теме метеостанции я не нашел в Инете решений с питанием базы метеостанции от батареек. Как правило, речь идет о аккумуляторах, солнечных батареях и т.п.
Осознаю — мое решение не идеальное, но с чего-то надо начинать.
А что касается DHT22, то это техническая работа — заменить один датчик на другой.
Успехов!igrushkin
09.10.2019 09:35те «прорыв» — использование батареек? Разочарую, это не прорыв. Большинство ПС как раз сделано на батарейках, тк у них низкий саморазряд.
328p далеко не лидер по энергоэффективности, и опять же, странно пользоваться им в 2019 годуCadil_TM Автор
09.10.2019 10:25Большинство ПС как раз сделано на батарейках, тк у них низкий саморазряд.
Относительно низкого саморазряда батареек — в этом не надо никого переубеждать. По поводу большинства — хотелось бы хоть один пример, чтобы дополнить сравнительную таблицу приемного узла в статье конкретными результатами из других проектов. Повторюсь, мне таких примеров найти не удалось. Возможно не там искал.
328p далеко не лидер по энергоэффективности, и опять же, странно пользоваться им в 2019 году
Учту на будущее.igrushkin
09.10.2019 10:28откройте для себя сайт mysensors.org и их дочерний сайт openhardware.org, не изобретайте велосипед.
Вся коммуникация и на lora, и на nrf24 давно реализована в этой библиотеке. С очень эффективным энергосбережением.
И почитайте про smart sleep
enjoyneering
08.10.2019 18:54+1А почему не использовали прерывание — wake on radio, встроенное в чип? Как только SX1278 словил сигнал, он выставляет высокий уровень на DIO4. Atmega328 просыпается делает дела и засыпает до следующего прерывания.
If a Preamble signal is detected, the Sequencer is switched off. The PreambleDetect signal can be mapped to DIO4, in
order to request the user's attention. The user can then take appropriate action.Cadil_TM Автор
09.10.2019 08:11А почему не использовали прерывание — wake on radio, встроенное в чип? Как только SX1278 словил сигнал, он выставляет высокий уровень на DIO4. Atmega328 просыпается делает дела и засыпает до следующего прерывания.
Да, но приемник LoRa при этом должен быть все время включен. Потребление работающего приемника вряд ли ниже потребления сторожевого таймера контроллера, поэтому я не смотрел в сторону прерывания. Возможно ошибался.enjoyneering
10.10.2019 04:34Приёмник включается по пребыванию таймера встроенного в SX1278 и ест не больше меги. Включился проверил несущую и выключилчился если ничего не нашел. Если нашел, то читаем мой пост выше Иногда полезно заглядывать в datashee. Этим простым спосоьом вы решаете проблему с синхронизацией.
iig
08.10.2019 21:43Если батарейки в комнате, сам датчик снаружи, и между ними провод, непонятно, зачем в этой схеме ещё и радио ?
Cadil_TM Автор
09.10.2019 08:23Уточнил в статье: Метеостанция состоит из двух узлов, назовем их для простоты гигрометром и термометром. Связь между узлами — беспроводная, по радиоэфиру.
iig
09.10.2019 08:51Так то, если под термином "термометр" понимать измеритель температуры, а "гигрометр", соответственно, влажности, то связь между ними особого смысла не имеет. Да и разносить их в конструктивно разные узлы зачем? (Но если хочется, то можно)
[Зануда офф]
zoldaten
09.10.2019 15:11Вставлю свои 5 копеек, т.к. делал аналогичное решение на esp8266-esp01, которое уже несколько лет работает. Только на улицу у меня «пошел» dht-22.
Так вот. Зимой датчик замерзает, его едят птицы, он нагревается на солнце, нагревается от стены дома. Чтобы этого не происходило он был погружен в отрезанную горловину пластиковой бутылки, закутанную в фольгу. Кроме того, из-за длины питающих датчик проводов(более метра), он ловит помехи извне, а также на показания влияет сопротивление длины проводов. Немного помогла скрутка проводов в косичку.
VT100
09.10.2019 20:20@Cadil
- Неплохо-бы добавить на линии питания конденсатор микрофарад на 100 для облегчения работы батареек.
- Контроль питания. С такими сопротивлениями делителя — надо зашунтировать "нижний" конденсатором (10..100 нФ), чтобы данные соответствовали действительности.
А лучше — измерять напряжение питания полностью встроенными средствами МК. Сконфигурировать опорное напряжение АЦП как напряжение питания и измерять относительно него внутреннее опорное напряжение 1,1 В.
igrushkin
"328p далеко не лидер по энергоэффективности, и опять же, странно пользоваться им в 2019 году"
Правда?Cadil_TM Автор
10.10.2019 10:00Неплохо-бы добавить на линии питания конденсатор микрофарад на 100 для облегчения работы батареек.
Для батареек с током короткого замыкания больше 2А (точнее не позволяет измерить шкала моего амперметра) вряд ли нужна помощь при работе с нагрузкой около 10-ти мА.
Контроль питания. С такими сопротивлениями делителя — надо зашунтировать «нижний» конденсатором (10..100 нФ), чтобы данные соответствовали действительности.
Я думал над этим и проверял — ставил конденсатор 470 нФ, но изменений в десятых вольта не заметил. Конденсатор, по-моему, важен при подключении к блоку питания — для сглаживания пульсаций напряжения. Для страховки — поставлю.
А лучше — измерять напряжение питания полностью встроенными средствами МК. Сконфигурировать опорное напряжение АЦП как напряжение питания и измерять относительно него внутреннее опорное напряжение 1,1 В.
Обязательно реализую этот подход.VT100
11.10.2019 08:24"Для батареек с током короткого замыкания больше 2А (точнее не позволяет измерить шкала моего амперметра) вряд ли нужна помощь при работе с нагрузкой около 10-ти мА."
Это для новых. А когда они разрядятся и внутреннее сопротивление вырастет — будет помогать.
"470 нФ"
Возможно, эффект маскируется analog_read'ом?
lenz1986
10.10.2019 17:31Nrf52 в любом режиме, выкинуть DS18b20 штука абсолютно бестолковая в батарейных термометрах, поставить хотя бы sht2x — 3x и будет работать от пары АА а лучше от одной LisoCi2 пару лет в режиме шлем инфу каждую минуту. Количество компонентов в разы меньше, стабильность выше.
ittakir
1. C# != C.
2. Если сделаете синхронизацию устройств, то не нужно будет ждать 65 секунд во время приема. Достаточно сделать период отправки сигнала датчиком более-менее фиксированный, а на базе запоминать время приема предыдущего пакета и включать приемник как раз к моменту следущего пакета. Это здорово сэкономит энергию.
Cadil_TM Автор
Спасибо!
Но для синхронизации надо ввести в оба узла часы, которые будут потреблять постоянно. Еще не факт, что общее потребление уменьшится. Надо считать.
AlexanderS
Не надо никакие часы. Нужна просто общая виртуальная шкала времени, которую станция создаст для датчиков.
В своё первое включение станция ожидает данных от датчика и держит приёмник включенным. Первый корректный пакет данных синхронизирует обмен и приёмник отключается. Затем станция включает приёмник через 60 секунд на 10 секунд — открывается «окно приёма». Понятное дело, что кварцевые генераторы на станции и датчике тикают по разному и время будет разбегаться, поэтому каждый принятый пакет должен калибровать внутренний счётчик таймаута приёма. Если станция не получила подряд три пакета — нужна полная ресинхронизация (аналог первого включения).
Однако всё усложняется, если датчиков несколько и они могут быть включены в совершенно произвольное время — станции придётся дожидаться первой посылки от каждого датчика и каждому выделять персональное «окно», за которым и следить. Понятно, что это чисто алгоритмическая нагрузка, которая тем не менее энергопотребление может тоже снизить, но тут уже зависит от количества датчиков и порядка их включения. Хотя, конечно, это не очень красиво, когда время жизни устройства зависит от того в какой последовательности я почесал за ухом и включил тот или иной датчик) Эти проблемы просто решаются введением в систему двунаправленного обмена данными станции с датчиками (введение просто часов не поможет, т.к. всё равно возникнет вопрос их синхронизации), но это повышает сложность и стоимость самих датчиков.
Cadil_TM Автор
Свежий, неожиданный для меня подход! Обязательно займусь им, не откладывая на будущее.
Возможно, он присутствует в технологии iT+? Описание технологии мне не удалось найти, но производители ее рекламируют.
AlexanderS
Я просто предложил решение, которое в голову пришло. Вам же как таковое абсолютное время не нужно — можно и относительным, ни к чему не привязанным обойтись. Решение простое, изменений в аппаратной части не требует — надо только накодить. Вряд ли я изобрёл что-то новое)
Надо заметить, что синхронизировать моменты приёмо-передачи можно по источнику из вне. Это может быть время GPS (просто опрос модуля GPS), GSM (запрос времени AT+ командами от модуля GSM модема), WiFi (модули на базе ESP, который сам бы подключался к сети, внутри крутился бы опрос по NTP какого-нибудь stratum сервера + ответы на запросы от атмеги) или вообще по радиосигналам точного времени (но не везде они «долетают»). Конечно, всё это будет жрать энергию, но тут зависит от концепции — все эти «обвески» могут включаться, например, только раз в сутки для точной синхронизации. При этом вы получите очень точное время. Окно приемо-передачи можно реально сузить до полсекунды. Однако, с моей точки зрения, если уж заниматься чем-то своими руками и ради хобби, то гораздо интереснее построить именно автономную систему, которая бы минимально зависела от внешних условий. В принципе, сама станция может периодически излучать синхросигнал, по которому будут синхронизироваться датчики. Причём можно его хоть как-то закодировать, чтобы помехоустойчивость поднять.