Я электрик, не программист, но как и многие здесь увлеченно внедряю у себя МД.
Первая проблема для меня это мое неумение быстро настраивать или восстанавливать МД
несколько раз я переустанавливал сервер по разным на то причинам и это занимало у меня
около 2х дней. Соответственно сидеть два дня без освещения не интересно. В моем варианте
используются проходные переключатели (которые позволят включить свет если полетит сервер
или плата ардуино), роль второго переключателя выполняет ардуиновское механическое реле
которое как и переключатель имеет нормально замкнутый и нормально разомкнутый контакт.
за состоянием освещения следит датчик холла ACS712 он измеряет ток в цепи освещения
и отправляет брокеру MQTT информацию о состоянии освещения (ВКЛ=1, ВЫКЛ=0).
В моем проекте я использовал Ардуино NANO, езернет шилд W5100, датчик холла ACS712
и модуль реле для ардуино можно все сделать и на ESP8266 но надо немного переписать скетч.
Единственная проблема при переделке освещения это необходимость прокладки трех жильных
проводов к выключателям, ну и к реле соответственно. Если у вас дома провода уложены в гофре,
то думаю это возможно.
Настройка которую надо будет сделать в МД после запуска ардуинки: зайти
в панель управления МД во вкладке Устройства модуль MQTT найти строчки типа
(home/data/status/relay(X)) где (X) номер реле, и привязать их к простым устройствам
Switch(X) где (X) номер выключателя.
извиняюсь за плохое оформление, не умею пользоваться программами для рисования схем.
слева на рисунке обычная типовая схема, справа мой вариант с возможностью управления из МД
скетч для краткости обрезал на три выключателя которые есть в МД сразу после установки,
у меня дома работают пять точек, в длинном коридоре стоит три переключателя + реле
Код: Выделить всё
#include <Ethernet.h>
#include <SPI.h>
#include <PubSubClient.h>
byte mac[] = { 0x00, 0x2A, 0xF6, 0x13, 0x69, 0x55 }; // MAC-адрес устройства
// ххх, ххх, ххх, ххх, поменять на адреса в вашей сети
byte ip[] = { ххх, ххх, ххх, ххх }; // ip-адрес устройства
byte server[] = { ххх, ххх, ххх, ххх }; // IP компьютера на котором установлен MQTT сервер
// здесь надо дописать логин и пароль к серверу MQTT если он установлен
byte gateway[] = { xxx, xxx, xxx, xxx }; // шлюз
byte subnet[] = { 255, 255, 255, 0 }; // маска сети
char buf[120];
#define RELAY_1 9 // пин реле 1
#define RELAY_2 8 // пин реле 2
#define RELAY_3 7 // пин реле 3
void callback(char* topic, byte* payload, unsigned int length); // Шапка Функции Callback (обратный вызов)
EthernetClient ethClient; //Инициализируем Ethernet клиент
PubSubClient client(server, 1883, callback, ethClient); //Инициализируем MQTT клиент дописать строку если установлен логин пароль
//===========================================================
int d = 150; // время задержки delay для того чтобы сервер успеел получить команду по сети
float AmpRMS1;
float AmpRMS2;
float AmpRMS3;
long last_mls = millis(); // время проверки перезагрузки
//------------
boolean rState1 = true; // сост реле1 true на моем модуле выключено если включается false
boolean lastBroker1 = false; // бывшее сост MQTT
boolean broker1 = false; // сост MQTT
boolean lamp1 = false; // сост лампы
boolean lastLamp1 = false; // бывшее сост лампы была
//------------
boolean rState2 = true;
boolean lastBroker2 = false;
boolean broker2 = false;
boolean lamp2 = false;
boolean lastLamp2 = false;
//------------
boolean rState3 = true;
boolean lastBroker3 = false;
boolean broker3 = false;
boolean lamp3 = false;
boolean lastLamp3 = false;
//==============================================
void setup() {
pinMode(RELAY_1, OUTPUT);
pinMode(RELAY_2, OUTPUT);
pinMode(RELAY_3, OUTPUT);
Serial.begin(9600);
digitalWrite(RELAY_1, rState1);
digitalWrite(RELAY_2, rState2);
digitalWrite(RELAY_3, rState3);
Ethernet.begin(mac, ip, gateway, subnet); // Инициализируем Ethernet
delay(5000); // задержка для подключения к езернет
client.connect("RELAYClient"); // Соединяемся и подписываемся на топики в MQTT
client.subscribe("home/data/status/relay1");
client.subscribe("home/data/status/relay2");
client.subscribe("home/data/status/relay3");
}
//=====функция reset для реконнект================
void(* resetFunc) (void) = 0; // функция для перезагрузки контроллера
//===реконект LAN и MQTT=================================
void reconnect_server() {
if (ethClient.connected()) {Serial.println("============LAN OK");} //Если есть езернет
else if (!ethClient.connected()) {Serial.println("============LAN NO"); //Если нет езернета
resetFunc(); }
if (client.connected()) {Serial.println("============MQTT OK");} //Если есть связь с MQTT
else if (!client.connected()) {Serial.println("============MQTT NO"); //Если нет связи с MQTT
resetFunc(); }
}
//=======CALLBACK-3========= Получаем информацию от брокера
void callback(char* topic, byte* payload, unsigned int length) {
//преобразуем тему(topic) и значение (payload) в строку
payload[length] = '\0';
String strTopic = String(topic);
String strPayload = String((char*)payload);
if (strTopic == "home/data/status/relay1") {
broker1 = strPayload.toInt();
Serial.print(" ----------BROKER-1 - "); Serial.println(broker1);
}
else if (strTopic == "home/data/status/relay2") {
broker2 = strPayload.toInt();
Serial.print(" ----------BROKER-2 - "); Serial.println(broker2);
}
else if (strTopic == "home/data/status/relay3") {
broker3 = strPayload.toInt();
Serial.print(" ----------BROKER-3 - "); Serial.println(broker3);
}
}
//=================================================================
void loop() {
client.loop(); //запуск функции проверки инфы от брокера
//================ЛАМПА-1===
if (lampa(A1)) {
AmpRMS1 = lampa(A1);
Serial.print(AmpRMS1); Serial.println(" Amp RMS-1");
if (AmpRMS1 > 0.12) lamp1 = 1; // Если показания датчика (Amp RMS) больше 0,12 А свет горит
else lamp1 = 0; // 0.12 можно менять по своим факт показаниям
if ((lastBroker1 == 0)&&(broker1 == 1)&&(lastLamp1 == 0)&&(lamp1 == 0)) { //если из брокера (1)
rState1 = !rState1;
digitalWrite(RELAY_1, rState1);
lastBroker1 = broker1;
lastLamp1 = true;
lamp1 = lastLamp1;
client.publish("home/data/status/relay1", String(lamp1).c_str(), false);
delay(d); }
else if ((lastBroker1 == 1)&&(broker1 == 0)&&(lastLamp1 == 1)&&(lamp1 == 1)) { //если из брокера (0)
rState1 = !rState1;
digitalWrite(RELAY_1, rState1);
lastBroker1 = broker1;
lastLamp1 = false;
lamp1 = lastLamp1;
client.publish("home/data/status/relay1", String(lamp1).c_str(), false);
delay(d);}
else if ((lastBroker1 == 0)&&(broker1 == 0)&&(lastLamp1 == 0)&&(lamp1 == 1)) { //если ВКЛ лампу
client.publish("home/data/status/relay1", String(lamp1).c_str(), false); delay(d);}
else if ((lastBroker1 == 0)&&(broker1 == 1)&&(lastLamp1 == 0)&&(lamp1 == 1)) { //промежуточный вар ВКЛ лампа и из брокера(1)
lastBroker1 = broker1;
lastLamp1 = lamp1; delay(d); }
else if ((lastBroker1 == 1)&&(broker1 == 1)&&(lastLamp1 == 1)&&(lamp1 == 0)) { //если ВЫКЛ лампу
client.publish("home/data/status/relay1", String(lamp1).c_str(), false); delay(d);}
else if ((lastBroker1 == 1)&&(broker1 == 0)&&(lastLamp1 == 1)&&(lamp1 == 0)) { //промежуточный вар ВЫКЛ лампа и из брокера(0)
lastBroker1 = broker1;
lastLamp1 = lamp1; delay(d); }
}
/* //======================ДЛЯ ОТЛАДКИ - 1===
Serial.print(" lamp-1 = "); Serial.println(lamp1);
Serial.print(" LASTlamp-1= "); Serial.println(lastLamp1);
Serial.println ("-------1---------");
Serial.print(" broker-1 = "); Serial.println(broker1);
Serial.print(" LASTbrok-1= "); Serial.println(lastBroker1);
Serial.print(" RStat-1 = "); Serial.println(rState1);
Serial.println ("=======================");
*/
client.loop();
//=================ЛАМПА-2===
if (lampa(A2)) {
AmpRMS2 = lampa(A2);
Serial.print(AmpRMS2); Serial.println(" Amp RMS-2");
if (AmpRMS2 > 0.12) lamp2 = 1;
else lamp2 = 0;
if ((lastBroker2 == 0)&&(broker2 == 1)&&(lastLamp2 == 0)&&(lamp2 == 0)) {
rState2 = !rState2;
digitalWrite(RELAY_2, rState2);
lastBroker2 = broker2;
lastLamp2 = true;
lamp2 = lastLamp2;
client.publish("home/data/status/relay2", String(lamp2).c_str(), false);
delay(d); }
else if ((lastBroker2 == 1)&&(broker2 == 0)&&(lastLamp2 == 1)&&(lamp2 == 1)) {
rState2 = !rState2;
digitalWrite(RELAY_2, rState2);
lastBroker2 = broker2;
lastLamp2 = false;
lamp2 = lastLamp2;
client.publish("home/data/status/relay2", String(lamp2).c_str(), false);
delay(d);}
else if ((lastBroker2 == 0)&&(broker2 == 0)&&(lastLamp2 == 0)&&(lamp2 == 1)) {
client.publish("home/data/status/relay2", String(lamp2).c_str(), false); delay(d);}
else if ((lastBroker2 == 0)&&(broker2 == 1)&&(lastLamp2 == 0)&&(lamp2 == 1)) {
lastBroker2 = broker2;
lastLamp2 = lamp2; delay(d); }
else if ((lastBroker2 == 1)&&(broker2 == 1)&&(lastLamp2 == 1)&&(lamp2 == 0)) {
client.publish("home/data/status/relay2", String(lamp2).c_str(), false); delay(d);}
else if ((lastBroker2 == 1)&&(broker2 == 0)&&(lastLamp2 == 1)&&(lamp2 == 0)) {
lastBroker2 = broker2;
lastLamp2 = lamp2; delay(d); }
}
/* //======================ДЛЯ ОТЛАДКИ - 2===
Serial.print(" lamp-2 = "); Serial.println(lamp2);
Serial.print(" LASTlamp-2= "); Serial.println(lastLamp2);
Serial.println ("------2----------");
Serial.print(" broker-2 = "); Serial.println(broker2);
Serial.print(" LASTbrok-2= "); Serial.println(lastBroker2);
Serial.print(" RStat-2 = "); Serial.println(rState2);
Serial.println ("=======================");
*/
client.loop();
//=================ЛАМПА-3===
if (lampa(A3)) {
AmpRMS3 = lampa(A3);
Serial.print(AmpRMS3); Serial.println(" Amp RMS-3");
if (AmpRMS3 > 0.12) lamp3 = 1;
else lamp3 = 0;
if ((lastBroker3 == 0)&&(broker3 == 1)&&(lastLamp3 == 0)&&(lamp3 == 0)) {
rState3 = !rState3;
digitalWrite(RELAY_3, rState3);
lastBroker3 = broker3;
lastLamp3 = true;
lamp3 = lastLamp3;
client.publish("home/data/status/relay3", String(lamp3).c_str(), false);
delay(d); }
else if ((lastBroker3 == 1)&&(broker3 == 0)&&(lastLamp3 == 1)&&(lamp3 == 1)) {
rState3 = !rState3;
digitalWrite(RELAY_3, rState3);
lastBroker3 = broker3;
lastLamp3 = false;
lamp3 = lastLamp3;
client.publish("home/data/status/relay3", String(lamp3).c_str(), false);
delay(d);}
else if ((lastBroker3 == 0)&&(broker3 == 0)&&(lastLamp3 == 0)&&(lamp3 == 1)) {
client.publish("home/data/status/relay3", String(lamp3).c_str(), false); delay(d);}
else if ((lastBroker3 == 0)&&(broker3 == 1)&&(lastLamp3 == 0)&&(lamp3 == 1)) {
lastBroker3 = broker3;
lastLamp3 = lamp3; delay(d); }
else if ((lastBroker3 == 1)&&(broker3 == 1)&&(lastLamp3 == 1)&&(lamp3 == 0)) {
client.publish("home/data/status/relay3", String(lamp3).c_str(), false); delay(d);}
else if ((lastBroker3 == 1)&&(broker3 == 0)&&(lastLamp3 == 1)&&(lamp3 == 0)) {
lastBroker3 = broker3;
lastLamp3 = lamp3; delay(d); }
}
/* //======================ДЛЯ ОТЛАДКИ - 3===
Serial.print(" lamp-3 = "); Serial.println(lamp3);
Serial.print(" LASTlamp-3= "); Serial.println(lastLamp3);
Serial.println ("------3----------");
Serial.print(" broker-3 = "); Serial.println(broker3);
Serial.print(" LASTbrok-3= "); Serial.println(lastBroker3);
Serial.print(" RStat-3 = "); Serial.println(rState3);
Serial.println ("=======================");
*/
//===== 120 секунд периодичность проверки и переподключения===
if (millis() - last_mls > 120000) {
last_mls = millis();
reconnect_server();
}
}
//====2 функции для чтения датчика холла ACS712======
float lampa(byte Pin)
{
float AmpRMS;
int readValue; //value read from the sensor
int maxValue = 0; // store max value here
int minValue = 1024; // store min value here
uint32_t start_time = millis();
while((millis()-start_time) < 200) //sample for 0,2 Sec
{
readValue = analogRead(Pin);
if (readValue > maxValue)
{ maxValue = readValue; }
if (readValue < minValue)
{ minValue = readValue; }
}
AmpRMS=((maxValue - minValue)/115.5);
return AmpRMS;
}