Сигнализация потопа с датчиком воды

Публикация 15.02.2017

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

Сигнализация потопа с датчиком воды

Для реализации проекта по защите от потопа в квартире я заказа у китайцев два электрических крана под резьбу 1/2 '' (DN15) схемой подключения DC3 и питанием 5 вольт.
Можно было заказать и на 12 вольт (они почему-то дешевле), но у меня не было подходящего блока питания. Для 5-и вольт подойдет любая зарядка от старого телефона.

Сигнализация потопа с датчиком воды

Электрический кран

Кран имеет 3 провода:

  • Красный - плюс 5 вольт
  • Зеленый - минус
  • Желтый - управляющий (плюс - закрыт, разрыв - открыт)
Сигнализация потопа с датчиком воды

Электрическая схема

Управлять этими кранами будет ESP8266-01. Это очень удобное и дешевое решение, но требующее подключения стабилизатора на 3.3 вольта. Управление мы будем осуществлять по протоколу MQTT с мобильного телефона на android.
Подробно о том как подготовить ESP к прошивке скетчем из Arduino IDE и настройке брокер-сервера cloudmqtt.com для обмена данными между устройствами я описывал в статье "ESP + MQTT как основа умного дома" и по тому повторяться не буду.

Управлять нашими электрическими кранами будет микроконтроллер ESP8266. Порт RxD будет управлять открытием/закрытием крана. Порт GPIO0 будет измерять сопротивление между ним и землей - датчик воды. Краны подключены не напрямую, а через транзистор КТ316. Ток для этих кранов не большой и этого маломощного транзистора хватает. Принципиальная схема устройства:

Сигнализация потопа с датчиком воды

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

Принцип работы

При включении устройства оно проверяет сопротивление на датчике. Если оно мало - включает тревогу и отключает подачу воды, если в норме - работает в следящем режиме.
Параллельно с этим устройство соединяется к домашнему роутеру и через интернет находит подключение к брокер серверу. Подписывается на топики "valve/1", "valve/alarm". Если на брокер сервер с мобильного клиента приходит топик "valve/alarm" = true - кран открывается, false - закрывается. Топик "valve/alarm" = true искусственно вызывает срабатывание тревоги и краны закрываются. "valve/alarm" = false отключает тревогу, если датчик не касается воды.

Скетч программы для Arduino IDE

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "xxxxxx"; // Имя роутера
const char *pass = "xxxxxx"; // Пароль роутера

const char *mqtt_server = "m13.cloudmqtt.com"; // Имя сервера MQTT
const int mqtt_port = 14483; // Порт для подключения к серверу MQTT
const char *mqtt_user = "xxxxxx"; // Логи для подключения к серверу MQTT
const char *mqtt_pass = "xxxxxx"; // Пароль для подключения к серверу MQTT

const int sensor = 0; // датчик воды
const int drive1 = 3; // кран
const int led = 5; // диод на плате

#define BUFFER_SIZE 100

int tm = 300;
float temp = 0;
bool sensor_is_alarm = false;
bool drive1_is_close = false;

WiFiClient wclient;
PubSubClient client(wclient);


// Функция получения данных от сервера
void callback(char* topic, byte* bpayload, unsigned int length)
{
  // конвертируем byte в sting
  String payload = "";
  for (int i = 0; i < length; i++) {
    payload = payload + (char)bpayload[i];
  }
  
  Serial.print(topic); // выводим в сериал порт название топика
  Serial.print(" => ");
  Serial.println(payload); // выводим в сериал порт значение полученных данных

  // проверяем из нужного ли нам топика пришли данные 
  if(topic == "valve/1" && sensor_is_alarm == false)
  {
    int value = payload.toInt();
    if (value == 0) drive1_is_close = true;
    else drive1_is_close = false;
  }
  if(topic == "valve/alarm")
  {
    int value = payload.toInt();
    if (value == 0) {
      sensor_is_alarm = false;
    }
    else {
      sensor_is_alarm = true;
      drive1_is_close = true;
    }
  }
}

void setup() {
  Serial.begin(115200);
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
  
  delay(10);

  Serial.println();
  Serial.println();

  pinMode(led, OUTPUT);
  pinMode(sensor, INPUT_PULLUP);
  pinMode(drive1, OUTPUT);

  digitalWrite(drive1, LOW);
}

// Функция проверка датчика воды
void readSensor() {
  int sensorValue = analogRead(sensor);
  if (sensorValue < 1023 && sensor_is_alarm == false) {
    // сработал датчик потопа
    sensor_is_alarm =  true;
    drive1_is_close = true;
    Serial.println("Alarm on");    
  }

  if (drive1_is_close == true) digitalWrite(drive1, HIGH);
  else digitalWrite(drive1, LOW);

  digitalWrite(led, sensor_is_alarm);
}

// Функция отправки показаний
void sendCurrentValue() {
  if (tm == 0) {
    // отсылаем текущий статус
    //client.publish("valve/alarm", String(sensor_is_alarm));
    //client.publish("valve/1", String(!drive1_is_close));
    tm = 3000; // пауза меду отправками 3 секунды
  }
  tm--;
}

void loop() {
  // подключаемся к wi-fi
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("Connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, pass);
    
    if (WiFi.waitForConnectResult() != WL_CONNECTED) return;
    Serial.println("WiFi connected");
  }
  
  // подключаемся к MQTT серверу
  if (WiFi.status() == WL_CONNECTED) {
    if (!client.connected()) {
      Serial.print("Connecting to MQTT server ");
      Serial.print(mqtt_server);
      Serial.println("...");
      if (client.connect("arduinoClient", mqtt_user, mqtt_pass)) {
        Serial.println("Connected to MQTT server");
        // подписываемся по топики
        client.subscribe("valve/1");
        client.subscribe("valve/alarm");
      } else {
        Serial.println("Could not connect to MQTT server"); 
      }
    }
    
    readSensor();
    
    if (client.connected()){
      client.loop();
      sendCurrentValue();
      delay(1); 
    }
  
  }
}

Управление на телефона

Скачал на свой Android программу - IoT MQTT Dashboard. В ней настроил отображение значения топиков "valve/1", "valve/alarm", которые присылаются раз в 3 секунды. Для управления кранами создал два переключателя "valve/1" и "valve/alarm", которые отсылают строки "true" и "false" при переключении.
Теперь остается спаять схемку и подключить. Тратить время на печатную плату было лень и сделал все по простому.

Сигнализация потопа с датчиком воды

Устройство закрепил в техническом шкафу санузла. Подвел питание 5 вольт от блока питания, что бы лишний раз не светить фазой возле водяных труб.

Сигнализация потопа с датчиком воды

Модернизация

В планах на доработку системы - отказ от проводных датчиков и использовать радио модули 433 МГц датчиков охраны двери с герконом. Геркон выпаивается и подпаивается самопальный сенсор воды (Контакты на плате уже есть. Такой же датчик для воды стоит вдвое дороже но практически ничем не отличается.)

Сигнализация потопа с датчиком воды

На плату нужно будет добавить приемник 433 МГц и доработать код.

Сигнализация потопа с датчиком воды

Библиотека pubsubclient.h в приложении. Она используются в скетче. Если выйдет более свежая версия библиотеки - может потеряться обратная совместимость с кодом и тогда можно использовать pubsubclient.h из архива.

Файлы для скачивания:
* комментарии публикуются после модерации
18.02.2021 13:39
Я что то не понимаю, как GPIO цифровой выход работает как АЦП ? Какое сопротивление он измеряет ?
Он же вроде способен только быть либо 0 либо 1.
17.12.2019 22:04
1) На схеме указаны номер ноги микросхемы, а в коде номер логического выхода. У них разная нумирация. На всех ардуионаплатах выводы подписаны именно как в коде...
2) true/false и LOW/HIGH на логических выводах работает одинаково.
16.12.2019 01:22
что то я не пойму...
1)const int sensor = 0; // датчик воды
а на схеме указано что датчик подключен к выводу 5!?
2)разве можно там где LOW/HIGH присваивать true/false?
Если да, то почему так:
digitalWrite(drive1, drive1_is_close );
не сделать тут:
if (drive1_is_close == true) digitalWrite(drive1, HIGH);
else digitalWrite(drive1, LOW);
если нельзя то почему тут сделано так:
digitalWrite(led, sensor_is_alarm);
01.06.2017 22:02
Я вижу, что вы обновили код для последней версии библиотеки - спасибо! Я дважды пытался разобраться с этим и у меня не получилось - ошибки какие-то были. Похоже, что на компе была другая версия pubsubclient.h
25.05.2017 13:37
Спасибо.
Вы правы. Внес исправление в код. Если есть какие-то другие замечания - с удовольствием выслушаю.
25.05.2017 13:37
Добрый день.
В вашей Скетч программе есть одна не точность. Если соединение не установлено то и проверка датчика на протекание не происходит и кран не закроется.