Разработка модуля управления электро-отоплением дачного домика

Друг построил на дачном участке баню из бруса. Возникла необходимость отапливать ее зимой и как-то управлять этим процессом. Без узла автоматики приходилось приезжать в субботу рано утром включать котел и в лучшем случае в субботу вечером собираться компанией. После установки автоматики стало возможным поддерживать в помешивании температуру +8 градусов экономить на электроэнергии и по мире необходимости прогревать помещение за ранее. Стало возможным не собираться в субботу вечером, а к примеру, в ночь с четверга на пятницу прогреть помещение по ночному тарифу, в течении дня пятницы поддерживать в помещении температуру +22, а в пятницу сразу после работы ехать закупаться пивом рыбой и всей компанией собираться в бане. На участке из коммуникаций только свет, газа нет, центрального отопления тоже нет, вода из скважины, был установлен водяной электро-котел, смонтирован коллектор и сделан водяной теплый пол в стяжке.

Сам котел на фото:

Так как электроникой я увлекаюсь давно, делать автоматику для электро-котла было решено из того что уже есть в тумбочке и давно лежит без дела, а это были:

  • плата Arduino Nano
  • модуль GSM Neoway M590
  • датчик температуры на DS18B20
  • твердотельное реле SSR-40DA
  • блок питания 220В -> 5В 2А я воткнул что было, а вы можете поставить минвел

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

Условия: прием модулем SMS только от одного абонента (чтобы ограничиться от спама и ложных команд), получение SMS о текущем состоянии реле и температуры, установка значения поддержания температуры в помещении (+гистерезис), переключение работы с блока управления на термостат.

Схема:

Фото в собранном виде.

Основные команды SMS:

  • T=** (** — установка температуры, по умолчанию установлено +3 градуса)
  • Stat — получение состояние реле, текущей температуры и уставки.
  • On — включение модуля управления
  • Off — отключение модуля управления (модуль по умолчанию выключен)

На данный момент устройство успешно проработало один зимний сезон и с наступлением теплого времени года планируется его апгрейд. В будущем в программе будет реализована возможность подключения двух дополнительных реле, а так же отображения их состояния в SMS по запросу Stat.

Исходный код для ArduinoIDE:

 #include <SoftwareSerial.h> #include <microDS18B20.h> #include "GyverRelay.h"  //#define SETPOINT 30.0 // установка (ставим на 25 градусов) #define HYSTER 3  // ширина гистерезиса  GyverRelay regulator(REVERSE);  // установка, гистерезис, направление регулирования  MicroDS18B20<2> sensor1; //датчик на D2 SoftwareSerial mySerial(10, 11); //RX, TX пины  byte R1 = 9; //пин D9 реле 1 byte R2 = 8; //пин D8 реле 2 int val1 = 0; //переменная для хранения значения R1 int val2 = 0; //переменная для хранения значения R2 String tel = "+7**********"; //номер телефона куда будут отправляться данные String availablePhone = "+7**********"; //номер телефона только с которого будут приниматься сообщения int setTemperature = 3; //уставка температуры по умолчанию bool state = false; //состояние включено/выключено  void setup() {   delay(2000);  //задержка      regulator.setpoint = setTemperature;       regulator.hysteresis = HYSTER;      regulator.k = 0.5;  // коэффициент обратной связи (подбирается по факту)      pinMode(R1, OUTPUT);  //устанавливаем режим работы пина 8 как Выход   digitalWrite(R1, LOW); //устанавливаем низкое значение пина 1   pinMode(R2, OUTPUT);  //устанавливаем режим работы пина 9 как Выход   digitalWrite(R2, LOW); //устанавливаем низкое значение пина 2   Serial.begin(9600);  //инициируем последовательное соединение и задаем скорость передачи данных в бит/c   mySerial.begin(9600);   Serial.println("GSM NEOWAY M590");   Serial.println();   Serial.println("Turn on AOH:");   mySerial.println("AT+CLIP=1");  //включить АОН   delay(300);   Serial.println("Text format sms:");   mySerial.println("AT+CMGF=1"); // текстовый формат SMS   delay(300);   Serial.println("Mode GSM:");   mySerial.println("AT+CSCS="GSM"");  // кодировка текста - GSM   delay(300);   Serial.println("SMS to terminal:");   mySerial.println("AT+CNMI=2,2,0,0,0"); // вывод смс в консоль   delay(10000);    sms(String("GSM NEOWAY M590 ON"), String(tel)); // отправка смс о включении модема  }  void loop()  {    if(mySerial.available()) //если модуль что-то послал   { //проверка всех условий       char ch = ' ';     String val = "";          while(mySerial.available()) //получение символов для чтения из последовательного порта     {         ch = mySerial.read();       val += char(ch); //собираем принятые символы в строку       delay(3);     }      Serial.print("Neoway send> ");     Serial.println(val);          if(val.indexOf("+CMT") > -1) //если есть входящее sms     {       String phoneSend = val.substring(val.indexOf("+7"), val.indexOf("+7") + 12);       Serial.println("PhoneSend: " + phoneSend);       if (phoneSend == availablePhone){         if(val.indexOf("On") > -1 || val.indexOf("on") > -1 || val.indexOf("ON") > -1) //если есть входящее sms         {            state = true;           Serial.println("State ON");         }                  if(val.indexOf("Off") > -1 || val.indexOf("off") > -1 || val.indexOf("OFF") > -1) //если есть входящее sms         {            state = false;           Serial.println("State OFF");         }                    if(val.indexOf("T=") > -1) // смотрим, что за команда         {           setTemperature = val.substring(val.indexOf("T=")+2).toInt();           regulator.setpoint = setTemperature;           Serial.println("Set TEMP: " + setTemperature);         }          if(val.indexOf("Stat") > -1) // смотрим, что за команда         {            Serial.println("Stat1");           val1 = digitalRead(R1);  //чтение значения пина на реле R1           val2 = digitalRead(R2);  //чтение значения пина на реле R2           Serial.println("Stat2");           sensor1.requestTemp(); // запрос температуры                     Serial.println("Stat3");           String val1Str, val2Str;           if (val1 == 0){             val1Str = "Off";           }           else{             val1Str = "On";           }            if (val2 == 0){             val2Str = "Off";           }           else{             val2Str = "On";           }            Serial.println("Stat4");           String result = "R1:" + String (val1Str) + " " + "R2:" + String (val2Str) + " " + "Temp:" + String (sensor1.getTemp()) + " SetTemp: " + String(setTemperature);           Serial.println("Stat5");           sms(result, String(tel));          }       }     }   }   regul();   debug(); }  void sms(String text, String phone)  // отправка СМС {   Serial.println("Start SMS send");   mySerial.println("AT+CMGS="" + phone + """);   delay(500);   mySerial.print(text);   delay(500);   mySerial.print((char)26);   delay(500);   Serial.println("SMS send OK");   delay(2000); }  void regul() {   static uint32_t tmr;   if (millis() - tmr > 500) {     if (state){       Serial.println(sensor1.getTemp());       Serial.println(regulator.getResult());       tmr = millis();       sensor1.requestTemp(); // запрос температуры       regulator.input = sensor1.getTemp(); // сообщаем регулятору текущую температуру       digitalWrite(R1, regulator.getResult());   // отправляем на реле (ОС работает по своему таймеру)     }     else{       digitalWrite(R1, LOW);     }   } } void debug() {   static uint32_t tmr;   if (millis() - tmr > 50) {     tmr = millis();     /*Serial.print(regulator.input);    // фактическая     Serial.print(',');     Serial.print(setTemperature);  // гистерезис     Serial.print(',');     Serial.print(setTemperature + HYSTER);  // гистерезис     Serial.print(',');     Serial.print(setTemperature - HYSTER);  // гистерезис     Serial.print(',');     Serial.println(regulator.output * 2 + 30); // сост. реле*/   } }