Умный дом: контроль электросети.

Мониторим состояние электросети прямо в браузере.

Очень уж захотелось взять под контроль мониторинг электросети в квартире. При том, бегать каждый раз к электрощитку – совсем не админский подход. Админы – народ ленивый, по этому вся информация должна быть доступна прямо с рабочего места. Ну а потом, будет чем похвастаться своим друзьям.

И так, ближе к делу… Я решил не описывать в этой статье процесс установки mosquitto и node red, потому как моя статья больше частью касается аппаратной составляющей данного проекта. Спешу отметить тот факт, что стабилизировать работу устройства мне удалось только спустя несколько недель тестирования и отладки, по этому считаю очень важным поделиться с вами этим выстраданным скетчем. ;)

Для мониторинга я решил использовать следующие компоненты:

Цифровой мультиметр \ счётчик PZEM-004T – данное умеет снимать показания напряжения и потребляемой мощности с сети 220в. Имеет гальваническую развязку, что позволяет избежать пробоев. Так же, имеет встроенный счётчик, работающий независимо от снятия показаний с устройства.

ESP8266 ESP01s – самая простая и дешёвая платка из устройств на чипе esp8266. Представляет собой микроконтроллер с Wi-Fi. Т.к. это устройство работает на логическом уровне 3.3в, в комплекте к нему идёт мост – преобразователь. С этим мостом можно питать устройство 5-вольтовым источником и подключаться к UART с уровнем 5в.

Так же, понадобится блок питания 5в, коих полно в любом магазине радиодеталей. Рекомендуется использовать блок с мощностью не менее 0.5 ампер.

К слову, в качестве сервера умного дома на текущий момент я использую Orange Pi PC Plus. В принципе, тянет нормально, но хотелось бы прикрутить SSD хард и я решил раскошелиться на самую мощную железку этого производителя: Orange Pi RK3399. На момент написания статьи, железка ещё в пути, так что обзор по ней я сделаю в следующий раз. К сожалению, на данный момент реально полезной информации по этому устройству в сети практически не нашлось.

Соединяем компоненты вот таким образом.

Так как мы имеем дело с гальванической развязкой, опрашивать PZEM-004t без подключения к 220в не получится, потому как она питается с двух сторон…

Ну а теперь самое главное. Скетч для esp01s.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include <PZEM004T.h>
double sens[4];
int pred;

PZEM004T pzem(3,1);  // RX,TX пины
IPAddress ip(192,168,1,1);

const char* ssid = "WIFI-SSID";
const char* password = "password";

#define MQTT_SERVER "192.168.1.254"  // Адрес MQTT брокера
#define mqtt_port  1883 // Порт
const char* mqtt_user="smart"; // Логин для MQTT
const char* mqtt_pass="password"; // Пароль


void callback(char* topic, byte* payload, unsigned int length) {

}
WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);


#define BUFFER_SIZE 100

String macToStr(const uint8_t* mac){
  String result;
  for (int i = 0; i < 6; ++i) {
    result += String(mac[i], 16);}
  return result;
}

void re_connect() {
  if(WiFi.status() != WL_CONNECTED){
    WiFi.begin(ssid, password);
  } else {
      delay(7000);
  }
}

void setup() {
  ESP.wdtDisable();
  pzem.setAddress(ip);
  
  pinMode(2, OUTPUT);    
  digitalWrite(2, LOW);    // выключаем светодиод
  re_connect();
  delay(100);
}

void loop(){
  if(WiFi.status() == WL_CONNECTED){
    client.connect("esp8266-AD14C5",mqtt_user,mqtt_pass);
    ESP.wdtFeed();
  } else {
    re_connect();
  }
  sens[0] = pzem.voltage(ip);
  if (sens[0] < 0.0) {
    sens[0] = 0.0; 
  }
  if (sens[0] > 0){
    client.publish("home/sensors/electro/v",String(sens[0]).c_str());
  }
  if (sens[0] == 0.0 && pred == 0) {
    client.publish("home/sensors/electro/v",String(sens[0]).c_str());
  }
  pred = sens[0];
  delay(1000);  
  sens[1] = pzem.current(ip);

  if(sens[1] >= 0.0){ 
     client.publish("home/sensors/electro/i",String(sens[1]).c_str());
   }
  delay(1000); 
  sens[2]= pzem.power(ip);

  if(sens[2] >= 0.0){ 
    client.publish("home/sensors/electro/w",String(sens[2]).c_str());
  }
  
  delay(1000); 
  sens[3] = pzem.energy(ip);

  if(sens[3] >= 0.0){ 
    client.publish("home/sensors/electro/wh",String(sens[3]).c_str());
  }
  delay(1000); 
  client.loop();
}

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