Привет, Хабр!

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

Небольшая предыстория


На тот момент я не имел счетчиков учета воды со смарт функциями, поэтому, для интеграции в свою систему умного дома, использовал проект AI on the edge device, который реализован на базе модуля ESP32 CAM и для распознания значения расхода использует алгоритмы машинного обучения (платформа Tensorflow lite) на базе машинного зрения.

Ниже фото установленного модуля для считывания показаний на базе ESP32 CAM:


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

  • Точность распознания — очень часто передавались ошибочные показания;
  • Большое потребление, что затрудняет использование в местах с отсутствием доступа к сети питания;
  • Сильный нагрев. Алгоритмы машинного зрения достаточно сильно нагружают модуль, что вызывает его перегрев;

Использовав данное решение несколько месяцев, я понял, что оно меня категорически не устраивает, поэтому решил разработать собственное, тем более, срок поверки установленных счетчиков подходил к концу и появилась возможность установить подходящие для моих целей счетчики. В итоге был приобретен комплект счетчиков с импульсным выходом от компании ITELMA, цена вопроса 2247 руб или $25,84. Согласовав замену счетчиков с управляющей компанией, была произведена их установка.

Установка новых счетчиков ITELMA в техническом отсеке:


Разработка аппаратного устройства


Итак, счетчики установлены, концы выведены, можно сказать, что половина дела сделана :) Далее нам предстоит немного интеллектуального труда, а именно — разработать принципиальную схему устройства, исходя их наших «хотелок» (назовем их «техническим заданием»). В итоге у меня сформировалось следующее ТЗ:

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

С коммуникацией ясно, как и в прошлой статье, будем использовать микроконтроллер ESP8266 от компании Espressif Systems. Но для снижения потребления энергии нам придется перенести функцию подсчета импульсов на более энергоэффективный и маломощный микроконтроллер, так как ESP8266 в активном режиме потребляет много энергии (даже с отключенным радиомодулем), если рассматривать его в контексте автономного питания. К счастью, у меня есть под рукой кандидат, который справится с этой задачей — это проверенный временем микроконтроллер от компании Microchip Technology ATtiny 2313A. В результате у нас «вырисовывается» следующая принципиальная схема устройства.

Принципиальная схема устройства


Для достижения максимальной энергоэффективности ATtiny 2313A, согласно технической документации, необходимо обеспечить уровень питающего напряжения в 1,8 В. Ниже приведена техническая информация возможностей данного микроконтроллера:

Возможности ATtiny 2313A-SU
Features
• High Performance, Low Power AVR® 8-Bit Microcontroller • Advanced RISC Architecture
– 120 Powerful Instructions – Most Single Clock Cycle Execution – 32 x 8 General Purpose Working Registers
– Fully Static Operation
– Up to 20 MIPS Throughput at 20 MHz
• Data and Non-volatile Program and Data Memories
– 2/4K Bytes of In-System Self Programmable Flash
• Endurance 10,000 Write/Erase Cycles
– 128/256 Bytes In-System Programmable EEPROM
• Endurance: 100,000 Write/Erase Cycles
– 128/256 Bytes Internal SRAM
– Programming Lock for Flash Program and EEPROM Data Security
• Peripheral Features
– One 8-bit Timer/Counter with Separate Prescaler and Compare Mode
– One 16-bit Timer/Counter with Separate Prescaler, Compare and Capture Modes – Four PWM Channels
– On-chip Analog Comparator
– Programmable Watchdog Timer with On-chip Oscillator
– USI – Universal Serial Interface
– Full Duplex USART
• Special Microcontroller Features
– debugWIRE On-chip Debugging
– In-System Programmable via SPI Port
– External and Internal Interrupt Sources
– Low-power Idle, Power-down, and Standby Modes – Enhanced Power-on Reset Circuit
– Programmable Brown-out Detection Circuit
– Internal Calibrated Oscillator
• I/O and Packages
– 18 Programmable I/O Lines
– 20-pin PDIP, 20-pin SOIC, 20-pad MLF/VQFN
• Operating Voltage – 1.8 – 5.5V
• Speed Grades
– 0–4MHz@1.8–5.5V – 0–10MHz@2.7–5.5V – 0–20MHz@4.5–5.5V
• Industrial Temperature Range: -40°C to +85°C • Low Power Consumption
– Active Mode
• 190 μA at 1.8V and 1MHz
– Idle Mode
• 24 μA at 1.8V and 1MHz
– Power-down Mode
• 0.1 μA at 1.8V and +25°C


Чтобы обеспечить данный уровень питающего напряжения, в схеме предусмотрен линейный регулятор LP2985-18DBVR с низким падением напряжения и имеющий ток собственного потребления 850 мкА при максимальном загрузочном токе в 150 мА.

Моя реализация подразумевает использование в качестве источника питания li-ion аккумулятор форм фактора 18650, но также в схеме предусмотрена возможность питания от элементов АА с напряжением 1,5 В.

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

Ниже приведена визуализация проекта печатной платы.

Трассировка и габаритные размеры платы


Рендер трехмерной модели платы^



Изготовление печатной платы


Изготовление платы выполнялось «лазерным» методом, о котором я писал статью раннее. Я просто в восторге этого метода, он позволяет значительно ускорить процесс изготовления прототипов плат, обеспечивая высокое качество и значительную экономию времени. Для общего понимания, ниже показаные некоторые этапы изготовления:

Активация фоторезиста лазером:



Видео процесса:

Процесс активации паяльной маски лазером:

Плата после монтажа радиокомпонентов:


Корпус устройства


Здесь всё просто, по классике DIY, модель корпуса была спроектирована во FreeCAD и напечатана на моем любимом и проверенным временем принтере Flyingbear Ghost 5.

Рендер модели корпуса:


Корпус после печати:


Сборка устройства


Установка системы питания в корпус:


Как можно видеть на изображении, в качестве контроллера зарядки применен модуль на базе TP4056, а в качестве разъема питания — USB Type-C. И для улучшения качества связи, применена внешняя Wi-fi антенна с разъемом SMA. А в качестве световода, для отображения индикации заряда, был применен прозрачный термоклей. Я считаю что DIY без термоклея — это не DIY.

Установка платы в корпус. Для фиксации платы в корпусе предусмотрены специальные прорези.


Пример с моделью платы:


Поэтому печатная плата без труда устанавливается и фиксируется в корпусе, как показано ниже на изображении.


Устройство в собранном виде:


Порт зарядки и выключатель:


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

Прошивка, интеграция в «Умный дом» интерфейс устройства


Прошивка устройства


Микро ПО устройства реализовано на моей «базовой» прошивке для умных устройств. Здесь я опишу несколько важных моментов, в остальном коде вы можете «поковыряться» на моем GitHub. Для простоты реализации, используется среда разработки Arduino IDE, а для программирования ATtiny 2313 — библиотека ATtiny Сore.

Так как в устройстве применяется два микроконтроллера: ESP8266 в качестве ведущего, а ATtiny2313 в качестве ведомого, то я хотел бы описать метод коммуникации между устройствами. Ниже представлен полный код прошивки ATtiny 2313:

Исходный код прошивки ATtiny 2313
#include <Wire.h>

int32_t  counter0 = 0;
int32_t  counter1 = 0;
uint16_t data = 0;
uint16_t data_t;

void setup() {
  pinMode(4, INPUT_PULLUP);                  // Пин счетчика 1
  pinMode(5, INPUT_PULLUP);                  // Пин счетчика 2


  attachInterrupt(0, countPulses0, FALLING); // Прерывание на INT0 при падении сигнала
  attachInterrupt(1, countPulses1, FALLING); // Прерывание на INT1 при падении сигнала

  Wire.begin(18);                            // Устанавливаем адрес устройства I2C
  //PB5: SDA (Serial Data)  - 12
  //PB7: SCL (Serial Clock) - 14
  Wire.onRequest(sendCounters);              // Устанавливаем функцию обработки запроса на передачу данных
}

void loop() {
     sender();                               // Это пустая функция в точке входа, чтобы контроллер работал, иначе не работает
}

void countPulses0() {
  counter0++;
}

void countPulses1() {
  counter1++;
}

void sender(){
  if((millis() - data_t) > data*3600000 && data >= 1 ){    // Событие которое не сработает никогда 
          data_t    = millis();
          digitalWrite(10, HIGH);
          while((data_t + 1000) > millis()){}
          digitalWrite(10, LOW);
        }

}

void sendCounters() {
    byte byteData[8];                                      // массив для хранения байтов
    byteData[0] = (counter0 >> 24) & 0xFF;                 // старший байт счетчика 0
    byteData[1] = (counter0 >> 16) & 0xFF;
    byteData[2] = (counter0 >> 8) & 0xFF;
    byteData[3] = counter0 & 0xFF;                         // младший байт счетчика 0

    byteData[4] = (counter1 >> 24) & 0xFF;                 // старший байт счетчика 1
    byteData[5] = (counter1 >> 16) & 0xFF;
    byteData[6] = (counter1 >> 8) & 0xFF;
    byteData[7] = counter1 & 0xFF;                         // младший байт счетчика 1


    Wire.write(byteData, 8);                               // Отправляем данные по шине I2C
   
   }


Как можно видеть, код довольно простой. И как вы уже, наверное, могли догадаться, связь между контроллерами обеспечивается по I2C шине. Функция обмена по шине реализована с помощью библиотеки <Wire.h>, где используются методы:

  • Wire.begin(18) — назначает адрес устройства;
  • Wire.onRequest(sendCounters) — установка функции обработки запроса на передачу данных;
  • Wire.write(byteData, 8) — метод для отправки данных;

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

 attachInterrupt(0, countPulses0, FALLING); // Прерывание на INT0 при падении сигнала
 attachInterrupt(1, countPulses1, FALLING); // Прерывание на INT1 при падении сигнала

Обратите внимание, что для обеспечения энергоэффективного режима работы микроконтроллера ATtiny2313A, необходимо использовать внутренний генератор тактирования, частота которого должна составлять 1 МГц. На данную особенность указывает техническая документация:

– Active Mode
• 190 μA at 1.8V and 1MHz

Данный параметр устанавливается в среде программирования:


Запрос со стороны ведущего ESP8266:

Здесь код запроса

void read_count(){
             Wire.requestFrom(SLAVE_ADDRESS, 9);                  // Запрос данных у ведомого устройства
             while (Wire.available() < 9) {}                      // Ожидание доставки всех данных
                  receiveData();                                  // Получение данных счетчиков    
}

void receiveData() {
  byte byteData[8];                                              // Массив для хранения принятых байтов
  Wire.readBytes(byteData, 9);                                   // Чтение данных из шины I2C
  uint32_t receivedCounter0 = ((uint32_t)byteData[0] << 24) | ((uint32_t)byteData[1] << 16) | ((uint32_t)byteData[2] << 8) | byteData[3]; // Собираем данные счетчика 0
  uint32_t receivedCounter1 = ((uint32_t)byteData[4] << 24) | ((uint32_t)byteData[5] << 16) | ((uint32_t)byteData[6] << 8) | byteData[7]; // Собираем данные счетчика 1
  uint32_t c0 = receivedCounter0 - receivedCounter0_storage;
  uint32_t c1 = receivedCounter1 - receivedCounter1_storage;
  if(receivedCounter1 != 4294967295 && receivedCounter0 != 4294967295){
              if(c0 > 429496652 && c1 > 429496652){
                    L_1 = 0;
                    L_2 = 0;
                  }else{
                    L_1 = c0;
                    L_2 = c1;
              }
              receivedCounter0_storage = receivedCounter0;
              receivedCounter1_storage = receivedCounter1;
              ESP.rtcUserMemoryWrite(0, &receivedCounter0_storage, sizeof(receivedCounter0_storage));
              ESP.rtcUserMemoryWrite(sizeof(receivedCounter0_storage), &receivedCounter1_storage, sizeof(receivedCounter1_storage));
              if(!config_st){
                  MQTT_send_data("json", JSON_DATA());
              }
    }
}


Интеграция в Home Assistant и интерфейс устройства


Конфигурация устройства выполняется через web интерфейс. При первоначальном подключении, устройство создает точку доступа CYBEREX-COUNT с беспарольным доступом. После подключения к точке доступа, у пользователя автоматически откроется страница авторизации, где необходимо будет ввести пароль по умолчанию «admin». После входа необходимо выполнить конфигурацию устройства. Интерфейс простой и интуитивно понятный. Ниже представлены скриншоты интерфейса.

Главная страница:


Конфигурация веса импульса:


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

Настройка MQTT протокола и периодичности отправки данных:


В данном устройстве реализован механизм MQTT Auto Discovery, позволяющий в автоматическом режиме добавлять объекты счетчика в Home Assistant.

Скриншот энергомониторинга:


И для возможности интеграции в Энергомониторинг Home Assistant, в MQTT запросе реализована передача параметра:

"state_class": "total"

При необходимости, Вы можете «собрать» карточку объектов для отображения данных нашего устройства.

Пример карточки объектов:


Аппаратные органы управления

На устройстве также присутствуют кнопки управления, которые отвечают за переход в режим конфигурации и отправку данных (она же функция перезапуска устройства).



Для перехода в режим конфигурации необходимо выполнить следующие действия:

  • Зажать кнопку 1 и не отпуская, кратковременно начать кнопку 2;
  • Не отпуская кнопку 1, дождаться постоянного мигания светодиода (примерно 10 секунд);
  • Отжать кнопку 1 и перейти в web интерфейс для конфигурации устройства.

Итоги


Давайте подведем итоги. Данная статья вышла с задержкой в восемь месяцев, именно столько времени мне потребовалось, чтобы проверить работу данного устройства. Устройство показало себя с наилучшей стороны, точность и стабильность работы на высоте. Что касается энергопотребления устройства — оно соответствует моим ожидания и полностью меня устраивает:

  • Ток потребления устройства в обычном режиме: 540 мкА; (ESP8266 (DeepSleep) — 25 мкА + ATtiny2313A (Active mode) — 190 мкА + Остальное — линейные регуляторы напряжения и подтягивающие резисторы );
  • Ток потребления в режиме передачи данных: 74 мА (зависит от уровня сигнала сети в точке установки).

Бюджет проекта, если рассматривать стоимость «железа», составляет не более $ 5,66.

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

Если вам понравилась статья, поддержите её стрелочкой вверх. А если есть что добавить, то добро пожаловать в комментарии. Всем добра и спасибо за внимание.

Токи потребления и фото установки
Устройство в техническом отсеке:


Токи потребления. Активный режим (режим передачи данных):


Ток потребления в обычном режиме:



Ссылки к статье:





Читайте также:

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале

Комментарии (22)


  1. tigreavecdesailes
    19.07.2024 08:29

    так как ESP8266 в активном режиме потребляет много энергии (даже с отключенным радиомодулем)

    "An ESP8266 in deep sleep mode can consume as little as 8 to 20µA." что и указано в конце статьи. Так зачем ещё attiny?


    1. Tirarex
      19.07.2024 08:29

      Attiny судя по коду выступает этаким маложрущим счетчиком, у которого ESP забирает данные по i2c. Возможно есп будить ради подсчета было дорого.


      1. tigreavecdesailes
        19.07.2024 08:29
        +5

        Мой коммент саркастически-риторический. Я имел в виду, что это большой оверхед по железу (возможно, как результат ардуино-подхода).

        По паспорту данных счётчиков воды у них 1 импульс на 10 литров. Это если исключить эпизодическое использование душа, то импульс будет приходить раз в минуты/десятки минут. Не думаю, что пробуждение esp из deep-sleep режима раз в 10 минут сожрёт больше, чем сожжёт attyny+её линейный стабилизатор за это же время (или за целую ночь).

        Ну и настоящим "маложрущим счётчиком" может быть обычный 14-битный CD4020 чтение с которого без всяких i2c происходит напрямую и которого хватит без сброса на 163 кубометра. (это если хочется совсем отвязать подсчёт импульсов по пробуждению esp)


      1. CyberexTech Автор
        19.07.2024 08:29

        Верно


    1. CyberexTech Автор
      19.07.2024 08:29

      ATtiny отвечает за функцию подсчёта импульсов счётчика, пока esp8266 "спит".


      1. Ivanii
        19.07.2024 08:29

        В современных ЕСП есть дополнительный маломощный проц(ESP32 ULP).


  1. kalapanga
    19.07.2024 08:29

    Очень много написано про токи потребления, энергоэффективность и т.п., стоило уж сосчитать и привести конечную циферку - сколько проживёт-то на одной зарядке? И продолжая тему питания. Контроля и индикации заряда аккумулятора нет или я что-то пропустил? Зачем схема зарядки на устройстве? Его что, надо будет от трубы открутить, нести куда-то на зарядку, заряжать, нести прикручивать обратно? Или удлинитель к нему кидать? Не проще аккумулятор менять?


  1. Soorin
    19.07.2024 08:29
    +1

    Интересно, почему было не использовать готовые решения? У меня дома 2 группы стояков ХВС/ГВС, два устройства подсчёта на 2 АА-батарейках, и уже не первый год они отправляют показания на почту.. И да, в них тоже есть ESP и Attiny.


  1. la0
    19.07.2024 08:29
    +1

    Когда рассматривал ровно такую же задачу пришел к нескольким вариантам:

    1. ESP32 современных версий в deep sleep c пробуждением от UP/DOWN на пинах (т.е. если нет изменений на пинах устройство спит себе тихо пробуждаясь дополнительно по таймеру раз в несколько часов)

    2. Решения типа PCF8593 со своими ограничениями (типа только 2 возможных i2c адресов, необходимости отдельно подавлять дребезг контактов), тут я пришел к выводу что проще делать ровно так как и сделал автор -- поставить на входах attiny

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

    Почти получилось решение по первому варианту, но работает крайне нестабильно, часто перезагружается сразу по выходу из дипслипа, может из онного не выйти и т.п. Может это и какие-то простые проблемы(= мои кривые руки), но с моим нулевым опытом в этой теме для меня выглядит препятствием.
    ESP видел первый раз в жизни, для себя задачу "посмотреть как эти SoC применимы в реальной жизни для задач с низким энергопотреблением" я решил.
    Без дипслипа всё естественно работает, было +- просто, но настолько энергонеэфективно просто не интересно.


    1. tigreavecdesailes
      19.07.2024 08:29

      На esp32 это предлагается делать не выходя из deep sleep посредством работающего ULP ядра https://github.com/espressif/esp-idf/tree/master/examples/system/ulp/ulp_fsm/ulp


      1. KonstantineZ
        19.07.2024 08:29

        У меня уже полтора года трудится самоделка с тем же функционалом. Основа - Wemos Lolin32 v1.0.0 на базе контроллера ESP32, сразу на плате есть зарядник для аккумулятора, стабилизаторы низкопотребляющие - супер модуль! Просыпается по таймеру раз в минуту или по прерыванию от счетчика и передает показания по блютуз в home assistant. За полтора года заряжал два раза и сейчас есть еще 50% заряда, и это с аккумулятором от старого ноута с остаточной емкостью около 1200мАч. Единственная проблема, которую поймал - прерывание повторно многократно будит еспешку если водосчетчик остановился в замкнутом состоянии геркона и программно настроить пробуждение так и не получилось. Пришлось допаивать развязку на RC цепочке для формирования короткого пробуждащего импульса.

        Сейчас читаю Вашу ссылку чтобы переписать счет на ULP.


  1. Zivaka
    19.07.2024 08:29
    +1

    Интересно, но ведь все ради фана? Тот же Ватериус отлично работает, стоит не сильно дорого, плюс еще и отправляет автоматически показания в УК.


    1. Iv38
      19.07.2024 08:29

      И по схемотехнике на ватериус похоже. Тоже тинька для счёта импульсов и ESP8266 для коммуникации.


  1. Sergey78
    19.07.2024 08:29

    Немного не по теме статьи, просто хотел бы поделиться, вдруг вам понравится. Я светодиоды применяю в smd виде. А для вывода на корпус использую световод диаметром 4мм. Из корпуса ничего не торчит, проще моделировать и паять, приятно светится. Просто как альтернатива запаянному выводному светодиоду.


  1. ruomserg
    19.07.2024 08:29
    +2

    Вы чего же это, ироды, делаете чтобы у вас tiny2313 столько ела ?! Зачем вы ее в цикле крутите на 1 МГц ? Заведите клок I2C на INT0, а вход от датчика на INT1. Они оба пробуждают тиньку от глубокого сна с остановленным тактированием. После отработки прерывания от датчика, оно должно ложиться спать сразу. А при активации клока на I2C - засыпайте сразу после STOP-condition. При этих условиях, саморазряд лития будет больше, чем потребление тиньки за тот же период. И на надо LDO - тинька прекрасно работает напрямую от аккумулятора, и если вы ее правильно положите спать, то есть она почти ничего не будет (у нее нет DRAM, а SRAM без переключения ничего считай и не потребляет - только токи утечки).


    1. SanSeich_78
      19.07.2024 08:29
      +1

      полностью согласен!
      А вообще, выше уже писали, что она тут сбоку-припёку.

      у меня был проект, где тинька управляла питанием и опрашивала приёмник RFID-карты (низкочастотная). Так в ТЗ было "проработать от двух АА не менее 2х лет".
      И хватало реально на все три, от минус 20'c до плюс 35'c.


  1. maxwolf
    19.07.2024 08:29

    Кстати, может кто знает, не появилось ли функционального аналога Dallas/Maxim DS2423 от какого-нибудь другого производителя?


  1. tklim
    19.07.2024 08:29

    Как-то все усложнено и не особо эффективно.
    Если хочется совсем низкого потребления - то вместо LDO - что-то вроде TPS62742 или TPS62842 и P-мосфет на управление ESP.
    В качестве малопотребляющего МК вполне подойдет стандартная atmega328p: Power-save Mode: 0.75µA (Including 32kHz RTC). Т.е. туда устанавливается кварц на 32768, просыпается по прерыванию от датчиков или RTC. Дальше уже включать ESP раз в несколько минут если счетчик тикает и раз в 12-24 часа по таймеру, чтоб доложить что устройство работает.
    Итого потребление в ждущем режиме - 2-3мкА максимум.
    А вообще, тут просится BLE или Zigbee. И одна батрейка CR123A лет на 5-10..


    1. anapogo
      19.07.2024 08:29

      CR123A лет на 5-10 - на Нобеля тянет... слабо?


      1. tklim
        19.07.2024 08:29

        https://apac.itron.com/o/commerce-media/accounts/-1/attachments/3808651
        Battery lifetime Up to 14 years*
        Там по идее 2хCR123. Плюс там нет контактов, датчик индуктивный, так что больше потребляет, чем геркон.


  1. anapogo
    19.07.2024 08:29

    Молодежь переползает потихоньку с Радиокота сюда...

    Это-ж офигеть, имея достаточно крутой проц в ЕСП, и не зная как сделать, ставить еще один , на котором знаю... потом выдумывать еще интерфейс между ними...


  1. anapogo
    19.07.2024 08:29

    А с другой стороны, если молодой спец вышел сюда, что-бы получить квалифицированную критику... то молодец, что не испугался и оформил не какой-то перевод, а полноценную статью.