Беспроводной модуль для ёмкостного датчика влажности почвы на nRF52832

от автора

Всем привет, сегодня расскажу о том как я решил проапгрейдить датчик влажности почвы с Алиэкспресс. Примерно месяц назад был куплен датчик влажности почвы. Зачем покупал и сам не знаю, наверное все из-за цены в 40 рублей 🙂

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

Схема датчика построена на микросхеме таймере TLC555. В схему добавлен стабилизатор напряжения XC6206P332 (даташит) на 3.3в, соответственно схему можно запитывать от источника максимум в 6в. При подаче напряжения питания ниже 3.3в, стабилизатор отдает на выходе тоже, что и получает на входе.

Уже как месяца два у меня лежали без дела два модуля nRF52832 от компании EBYTE — E73-2G4M04S1B. Очень дешевые модули, в вопросе цены оставляют далеко позади все другие модули nRF52.

Но у них есть 2 существенных для меня минуса. Первый и менее важный это размеры модуля. Они довольно большие. Второй минус, более важный это отсутствие в схеме двух маленьких элементов из-за чего модуль теряет половину своей привлекательности. Отсутствующие элементы это две индуктивности подключаемые к ножкам DCC и DEC4. Плохо это тем что не позволяет использовать модули в режиме пониженного энергопотребления, 7-8мА VS 15-16мА. Почему их не стали ставить я не могу понять, вариант «из-за экономии» не вписывается, так как на схеме можно было сэкономить и на других элементах. В общем добавляем в хотелки установку индуктивностей и наличие режима DC-DC.

Следующее что надо решить это управление питанием датчика. Так как наша тема это батарейная тема то постоянное питание это плохой вариант. Самое простое что сразу напрашивается это использование транзистора в режиме ключа. Выбор пал на полевой p-канальный транзистор IRLML6402TRPBF.

Следующее о чем нужно было подумать это порт программирования, под SWD и Serial сделал просто контактные площадки. Конечно так же добавил микро разъем, который использую и в других устройствах 2x3P | 6pin | 1.27mm | SMT | Pin Header Female, но это теперь чисто опциональная штука.

Так же нужно добавить тактовую кнопку и как минимум один светодиод, что бы было по проще понимать работает оно или нет :).

Следующее что надо было решить это как соединять ноду радио модуль и емкостный датчик. Розетку которая установлена на датчике и провода идущие в комплекте использовать совсем не хотелось. Шаг отверстий в разъёме на плате куда напаивается розетка, составляет 2.54мм, так же на плате выведен дополнительный дублирующий ряд. Было принято решение использовать обычную «гребенку» с шагом 2.54, а использование сразу обоих рядов придаст дополнительную жесткость соединения.

Вроде бы всё, из плюшек несколько элементов которые можно оставить или спаять на черный день и розетка с проводом (где нибудь пригодится :)).

Плату, как обычно, делал в программе Диптрейс. Первый вариант был сделан для ЛУТ, собственно о том что получилось как раз речь в этой статье. Позже был сделан вариант платы для заказа на производстве.

После травления, лужения, вырезания, сверления и пайки пришло время тестов. Вообще ничего особого от датчика на модуле от EBYTE не ждал, тем более с каким то внешним влагомером с Али. Но по итогу был даже удивлен некоторыми результатами. Потребление в режиме передачи данных составило не более 9мА(на полу разряженной батарейке), потребление в режиме измерений составило не более 5 мА. Потребление в режиме сна составило 2.1-2.2мкА!!!

Итого что теперь может датчик. Работать в пониженном режиме энергопотребления. Измерять и передавать на контролер УД по средствам сети Майсенсорс показания влажности почвы, показания температуры, показания оставшегося заряда батарейки, показания уровня радиосигнала.

А что такое Майсенсорс?

A это сообщество разработчиков програмного обеспечения с открытым исходным кодом. Данный протокол разработан сообществом для создания радио и проводных сетей. Первоначально проект разрабатывался для платформы Arduino.

Поддерживаемые аппаратные платформы: Linux / Raspberry Pi / Orange Pi | ATMega 328P | ESP8266 | ESP32 | nRF5x | Atmel SAMD, используемое в Arduino Zero (Cortex M0) | Teensy3(MK66FX1M0VMD18) | STM32F1.

Поддерживаемые радиопередатчики: NRF24L01 | RFM69 | RFM95 (LoRa) | nRF5x

Поддерживаемый проводной тип связи: RS485

Поддерживаемые типы связи между гейтом и контролером: MQTT | Serial USB | WiFi | Ethernet | GSM

Код программы

uint16_t m_s_m; uint16_t m_s_m2; uint16_t m_s_m_calc; boolean flagSendmsm = 0; float celsius = 0.0; uint32_t rawTemperature = 0; uint32_t rawTemperature2 = 0; uint16_t currentBatteryPercent; uint16_t batteryVoltage = 0; uint16_t battery_vcc_min = 2300; uint16_t battery_vcc_max = 3000; int16_t linkQuality;  //#define MY_DEBUG #define MY_DISABLED_SERIAL #define MY_RADIO_NRF5_ESB #define MY_RF24_PA_LEVEL (NRF5_PA_MAX) //#define MY_PASSIVE_NODE #define MY_NODE_ID 83 #define MY_PARENT_NODE_ID 0 #define MY_PARENT_NODE_IS_STATIC #define MY_TRANSPORT_UPLINK_CHECK_DISABLED #define MSM_SENS_ID 1 #define MSM_SENS_C_ID 2 #define TEMP_INT_ID 3 #define SIGNAL_Q_ID 10 #include <MySensors.h> MyMessage msg_msm(MSM_SENS_ID, V_LEVEL); MyMessage msg_msm2(MSM_SENS_C_ID, V_LEVEL); MyMessage msg_temp(TEMP_INT_ID, V_TEMP);  void preHwInit() {   pinMode(6, OUTPUT);   digitalWrite(6, HIGH);   pinMode(15, OUTPUT);   pinMode(5, INPUT); }  void before() {   delay(3000);   NRF_POWER->DCDCEN = 1;   NRF_UART0->ENABLE = 0;   analogReadResolution(12);   analogReference(AR_VDD4);   NRF_CLOCK->TASKS_HFCLKSTART = 1;   NRF_TEMP->TASKS_STOP;   NRF_TEMP->EVENTS_DATARDY = 0;   NRF_TEMP->INTENSET = 1; }   void presentation() {   sendSketchInfo("PWS GREEN nRF52", "1.01");   wait(300);   present(MSM_SENS_ID, S_CUSTOM, "DATA - SOIL MOISTURE");   wait(300);   present(MSM_SENS_C_ID, S_CUSTOM, "% - SOIL MOISTURE");   wait(300);   present(TEMP_INT_ID, S_TEMP, "TEMPERATURE");   wait(300);   present(SIGNAL_Q_ID, S_CUSTOM, "SIGNAL QUALITY");   wait(300); }  void setup() { }  void loop() {   int_temp();   digitalWrite(15, HIGH);   sleep(100);   digitalWrite(15, LOW);   msm ();   digitalWrite(15, HIGH);   sleep(100);   digitalWrite(15, LOW);   wait(50);   if (flagSendmsm == 1) {     send(msg_msm2.set(m_s_m_calc), 1);     wait(3000, 1, 37);     wait(200);     send(msg_msm.set(m_s_m), 1);     wait(3000, 1, 37);     flagSendmsm = 0;   }   wait(200);   send(msg_temp.set(celsius, 1), 1);   wait(3000, 1, 0);   sleep(15000);   //sleep(2000);   sendBatteryStatus();   sleep(21600000); //6h   //sleep(43200000); //12h   //sleep(86400000); //24h   //sleep(20000); //20s }  void int_temp() {   for (byte i = 0; i < 10; i++) {     NRF_TEMP->TASKS_START = 1;     while (!(NRF_TEMP->EVENTS_DATARDY)) {}     rawTemperature = NRF_TEMP->TEMP;     rawTemperature2 = rawTemperature2 + rawTemperature;     wait(10);   }   celsius = ((((float)rawTemperature2) / 10) / 4.0);   rawTemperature2 = 0;  }  void msm () {   digitalWrite(6, LOW);   wait(500);   for (byte i = 0; i < 10; i++) {     m_s_m = analogRead(5);     m_s_m2 = m_s_m2 + m_s_m;     wait(50);   }   m_s_m = m_s_m2 / 10;   m_s_m2 = 0;   digitalWrite(6, HIGH);   wait(50);   if(m_s_m >3000){     m_s_m = 3000;   }   if(m_s_m <1100){     m_s_m = 1100;   }   m_s_m_calc = map(m_s_m, 3000, 1100, 0, 100);   flagSendmsm = 1; }  void sendBatteryStatus() {   wait(100);   batteryVoltage = hwCPUVoltage();   wait(20);    if (batteryVoltage > battery_vcc_max) {     currentBatteryPercent = 100;   }   else if (batteryVoltage < battery_vcc_min) {     currentBatteryPercent = 0;   } else {     currentBatteryPercent = (100 * (batteryVoltage - battery_vcc_min)) / (battery_vcc_max - battery_vcc_min);   }   sendBatteryLevel(currentBatteryPercent, 1);   wait(3000, C_INTERNAL, I_BATTERY_LEVEL);    linkQuality = calculationRxQuality();   wait(50);   sendSignalStrength(linkQuality, 1);   wait(2000, 1, V_VAR1); }    //****************************** very experimental *******************************   bool sendSignalStrength(const int16_t level, const bool ack) {   return _sendRoute(build(_msgTmp, GATEWAY_ADDRESS, SIGNAL_Q_ID, C_SET, V_VAR1,                           ack).set(level)); } int16_t calculationRxQuality() {   int16_t nRFRSSI_temp = transportGetReceivingRSSI();   int16_t nRFRSSI = map(nRFRSSI_temp, -85, -40, 0, 100);   if (nRFRSSI < 0) {     nRFRSSI = 0;   }   if (nRFRSSI > 100) {     nRFRSSI = 100;   }   return nRFRSSI; }  //****************************** very experimental ******************************* 

ПО естественно тестовое, что я бы непременно добавил(и добавлю), это учет коэффициента разряда батарейки, хоть я и использую в ПО настройку опорного напряжения как внешнее батарейное vdd/4, но все равно присутствует небольшой шум при измерениях с разным уровнем напряжения. Так же пока не ясно стоит ли или нет вводить температурный коэффициент в расчеты. Неясно потому что пока нет статистики. Но, а в целом на выходе очень симпатиШные результаты:). Стоимость всего что пришлось добавить к китайскому датчику влажности составила что-то в районе 400 рублей. Вполне неплохо.

Видео с тестами

Фотографии

ГитХаб проекта — github.com/smartboxchannel/EFEKTA_E73B_PWS_MODULE

Вот такой вот вышел проектик,… пока аля Ардуино модуль, но места для крепления к корпусу предусмотрел заранее, так что дальше будет корпус. Потребляет мало, в основном всегда спит с потреблением примерно 2 мкА, так что батарейки CR2450 должно хватить надолго.

Место где всегда с радостью помогут всем кто хочется познакомиться с MYSENSORS (установка плат, работа с микроконтроллерами nRF5 в среде Arduino IDE, советы по работе с протоколом mysensors, обсуждение проектов — телеграмм чат @mysensors_rus


ссылка на оригинал статьи https://habr.com/ru/post/460587/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *