Снятие показаний счетчика расхода воды на Arduino

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

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

Программа для подсчета расхода воды состоит из нескольких частей:

  • Снятие данных расхода воды с импульсного выхода счетчика.
  • Индикация снятых показаний.
  • Передача телеметрической информации на сервер.

Снятие данных с импульсного выхода водосчетчика

Геркон, по сути — это механическая кнопка, управляемая магнитом. Поэтому может быть использована схема коммутации для обычной кнопки. Это медленное механическое устройство. Бытовой счетчик воды после коммутации геркона в течении нескольких секунд «держит» геркон в замкнутом состоянии.

Подключение геркона
импульсного выхода водосчетчика

В некоторых схемах в Интернет для подключения кнопки/геркона используют дополнительный «подвешивающий» резистор. Смысла в этом нет, поскольку в самом чипе есть резистр соединенный с +5V. Он активируется кодом: pinMode(PULSE_PIN, INPUT_PULLUP).

Однако геркон нужно подключить через резистор на 1 кОм к входу GPIO. Он нужен, чтобы не «спалить» порт микроконтроллера если прошивка случайно выставит единицу на пине, а геркон в этот момент закоротит эту линию на землю. При наличии резистора через микроконтроллер потечет ток I = 3.3В/1000 Ом = 3.3 мА при том, что ток выхода из строя GPIO ESP8266 — 12 мА, а ESP32 — 20 мА.

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

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

 Код Arduino для подсчета расхода воды:

#include "Bounce2.h";

int LED_PIN = 13;
int PULSE_PIN = 2;
int water_counter = 0; 
bool last_PULSE_PIN_State = false;

// Initiate Debouncer 
Bounce debouncer = Bounce();

void setup() {
  // Initialize digital pin 2 as an input with the internal pull-up (+5V) resistor enabled
  pinMode(PULSE_PIN, INPUT_PULLUP);

  // Attach PULSE_PIN for debouncing
  debouncer.attach(PULSE_PIN);
  debouncer.interval(50); // Ignore interval
  
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(9600, SERIAL_8N1);
}

void loop() {  
  debouncer.update();
 
  // Read Reed Switch state
  int value = debouncer.read();
 
  // Now all processes are finished and we know exactly the state of the Reed Switch
  if ( value == LOW ) {
    digitalWrite(LED_PIN, HIGH );
    if (last_PULSE_PIN_State == false)
    {
      water_counter++;
      Serial.println("Water consumption: " + (String)(water_counter*10) + " l.");
    }
    last_PULSE_PIN_State = true;
  }
  else {
    digitalWrite(LED_PIN, LOW);
    last_PULSE_PIN_State = false;
  }
}

Код был оттестирован на счетчике расхода воды Valtec VLF-U-I. Схема импульсного выхода водосчетчика:

Схема импульсного выхода водосчетчика
Valtec VLF-U-I
  • PIN 2 Arduino подключен к 1 выходу водосчетчика.
  • GND Arduino подключен к 4 выходу водосчетчика.
  • В случае с герконом контакты 1 и 4 можно менять местами. 🙂

Другой вариант реализации кода — с использованием прерываний.

int LED_PIN = 13;
int PULSE_PIN = 2;
int water_counter = 0; 

long lastDebounce = 0;
long debounceDelay = 500;  // Ignore bounces less than 500 ms. Need to calibrate with water meter!!! A too large value will conduct missing increment. 

void setup() {
  Serial.begin(9600);
  pinMode(PULSE_PIN, INPUT_PULLUP); //Pullup internal resister
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(PULSE_PIN, HIGH);
  attachInterrupt(digitalPinToInterrupt(PULSE_PIN), trigger, FALLING);
}

void loop() {
  int state = digitalRead(PULSE_PIN);
  digitalWrite(LED_PIN, !state );
}

void trigger() {
  if ((millis() - lastDebounce) > debounceDelay) 
  { 
    water_counter++;
    Serial.println("Water consumption: " + (String)(water_counter*10) + " l.");
    lastDebounce = millis();
  }
}

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

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

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

Литература

Информации по разработке счетчиков воды в Интернет множество. Вот некоторые из статей:

Продолжение следует…

Spread the love
Запись опубликована в рубрике IT tools, IT рецепты с метками , . Добавьте в закладки постоянную ссылку.