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

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

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

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

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

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

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

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

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

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

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

Поскольку устройство очень медленное, нет необходимости использовать аппаратные решения, вроде триггера Шмидта или 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();
  }
}

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

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

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

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

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