Arduino Majordomo Умный дом

Термостат для котла на esp8266 (Часть 1)

• 11-04-2019 •

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

Все я запланировал делать на контроллере ESP8266, управлять на платформе Majordomo, а передавать информацию по протоколу MQTT.

Что я использовал

  • Контроллер ESP8266
  • Водостойкий датчик температуры Dallas 2x
  • Ультразвуковой датчик расстояния HC-SR04P 3v
  • Макетная плата для тестов

Мои ошибки

1. Первое что я посоветую, так это не паять на прямую все датчики к контроллеру, а присоединять все через штепсели.

Было так, что написал код, припаял, пошел в котельную, все установил, прошла неделя тестов и тут я понял, что хочу доработать код, а так как все припаяно на прямую, пришлось контроллер тащить со всеми проводами, что не очень удобно.

2. Не пичкать лишнего!

Решил изначально добавить светодиодов, чтобы можно было видеть, работает ли контроллер, есть ли связь с wi-fi, и т.д. Оказалось обсалютно бесполезной идеей, только лишняя пайка (Это на мой взгляд).

3. Купить коробку, куда положить контроллер.

Лучше сразу заморочиться и сделать красивенько в коробочке и не откладывать на потом!

Проблемы в коде, с которыми я столкнулся

1. Не правильные показания с сенсоров

Первое что нужно учесть:

Датчики температуры, могут дать сбой и выдать заоблачную температуру, такую как -127 или любую другую. Стоит сразу создать функцию, которая будет проверять приблизительно реальную цифру, скажем, если это бойлер, то температура может быть от 10 до 70 градусов.

2. Mqtt отключает клиента, если нету цикла в течении 15 секунд

Чтобы отправлять команды на контроллер с Majordomo, нужно, чтобы контроллер всегда имел связь с сервером MQTT, иначе вы не сможете управлять реле. Так как мне не нужно получать данные каждую секунду, а к примеру раз в минуту, то я использовал delay, для паузы цикла. Но проблема в том, что тогда сервер MQTT разрывает связь с клиентом esp8266. Тогда я решил использовать другой метод тайминга.

В итоге, что у меня получилось

Код:


#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
//#include <ArduinoJson.h>

//SR-04
const int trigPin = 13;  //D7
const int echoPin = 12;  //D6

//DALLAS
#define PIN_DS18B20 5 //D1
int countDallasSensors;

//VARIABLES
long SR_Duration;
int SR_Distance;
float tempBoiler;
float tempPot;

//NETWORK
byte mqtt_server[] = { 192, 168, 1, 231 };
char buffer[10];
// WiFi credentials.
const char* WIFI_SSID = "#";
const char* WIFI_PASS = "#";

const char* MQTT_SSID = "#";
const char* MQTT_PASS = "#";


OneWire oneWire(PIN_DS18B20);
DallasTemperature dallasSensors(&oneWire);

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

}

WiFiClient wifiClient;
PubSubClient client(mqtt_server, 1883, MQTTMessage, wifiClient);

void connectWIFI() {
  WiFi.persistent(false);
  WiFi.mode(WIFI_OFF);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  unsigned long wifiConnectStart = millis();

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);

    // Only try for 5 seconds.
    if (millis() - wifiConnectStart > 5000) {
      return;
    }
  }
}

void reconnectMQTT() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.println("Reconnect to MQTT");
    client.connect("ESP8266 Thermostate", MQTT_SSID, MQTT_PASS);
    client.publish("outTopic", "connecting..");
    delay(5000);
  }
}

void getDistance() {
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // Reads the echoPin, returns the sound wave travel time in microseconds
  SR_Duration = pulseIn(echoPin, HIGH);

  // Calculating the distance
  SR_Distance = SR_Duration * 0.034 / 2;
}

void getTemperature(){
  dallasSensors.requestTemperatures(); 
  delay(1000);
  tempBoiler = dallasSensors.getTempCByIndex(0);
  tempPot = dallasSensors.getTempCByIndex(1);
}

void sendToServer(int distance, double tempBoiler, double tempPot, int countDallasSensors) {
  client.publish("outTopic", "connected");
  if(distance < 150 && distance > 0){
    client.publish("ESP/ToHome/distance", String(distance).c_str());
  }
  if(tempBoiler < 150 && tempBoiler > 0){
    client.publish("ESP/ToHome/tempBoiler", String(tempBoiler).c_str());
  }
  if(tempPot < 150 && tempPot > 0){
    client.publish("ESP/ToHome/tempPot", String(tempPot).c_str());
  }

  client.publish("ESP/ToHome/countDallasSensors", String(countDallasSensors).c_str());
  Serial.println("Reported!");
  delay(1000);
}

void toDeepSleep(){
    client.disconnect();
    WiFi.disconnect();
    delay(1000);
    Serial.println("Sleeping..");
    delay(20);
    ESP.deepSleep(60e6);
    
}

void setup() {
  Serial.begin(9600);

  // Wait for serial to initialize.
  while (!Serial) { }
  
  dallasSensors.begin();
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  countDallasSensors = dallasSensors.getDeviceCount();
  connectWIFI();
  
  Serial.println("Device Started");
  Serial.println("-------------------------------------");
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    connectWIFI();
  }

  if (!client.connected()) {
    reconnectMQTT();
  }

  if (client.connected()) {
    getDistance();
    getTemperature();
    sendToServer(SR_Distance, tempBoiler, tempPot, countDallasSensors);
    toDeepSleep();
  }
  client.loop();
}

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

Настройка в majordomo

Первое, что нужно сделать, так это настроить mqtt, про сам mqtt я уже писал в статье «MQTT«. В самом majordomo нужно скачать модуль и заполнить все необходимые поля во вкладке «настройки».

Дальше нужно создать соответствующие объекты, проще всего создать в «простые устройства«, один будет, датчик процентное значение, а другой термостат.

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


$min = 10;
$max = 70;
$val = 30; // Это значение которое пришло с датчика

$percent = (100 - ((($val - $min) * 100) / ($max - $min)));
$percent = number_format((float)$percent, 0, '.', '');
sg('Sensor_percentage01.value', $percent);

Стоит ли заморачиваться?

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

Так же, если бойлер греется от котла, как в моем случае, то в весеннее и осеннее время, когда котел работает не постоянно, перед тем как сходить в душ, теперь можно посмотреть температуру воды, чтобы не было фиаско )).

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

Плюсов много, но вполне возможно, что все это дело можно оптимизировать еще лучше, так что всегда рад комментариям снизу!

Перед тем как полностью переходить на управление котлом через Majordomo, обязательно к прочтению статьи «Majordomo, защита от взлома«

One thought on “Термостат для котла на esp8266 (Часть 1)

  1. Ничего не ясно, а где код для реле и собственно «оно» само?
    В чем термостатность?
    Или вы просто сделали датчик на еспешке с отправкой на сервер данных о температуре и все?

Добавить комментарий