ESP8266 NoFreeze cz.1

Układ chroniący przed zamarzaniem.

Budowa klasy obsługującej to urządzenie.

Do budowy urządzenia chroniącego przed zamarzaniem potrzebne będą;

  1. Urządzenie WeMos D1 mini + ładowarka 5V 500mA.
  2. Moduł przekaźnika do WeMos D1 min.
  3. Dwa czujniki temperatury DS18S20.
  4. Rezystor 4.7k.
  5. Grzejnik ok. 1000W z nawiewem.

Układ ten ma zastosowanie w pomieszczeniach nieogrzewanych, gdzie temperatura nie może spaść poniżej zera. Na przykład może to być nieogrzewana łazienka na strychu, gdzie przy dużych mrozach temperatura mogłaby spaść poniżej zera. Zastosowań może być wiele.

Zasada działania polega na pomiarze temperatury wewnątrz i na zewnątrz. Gdy temperatura wewnątrz tempi spadnie poniżej tempi1, oraz temperatura na zewnątrz spadnie poniżej temperatury tempo, to zostaje włączony grzejnik na określony czas minutesOn. Gdy temperatura wewnątrz spadnie poniżej temperatury tempi2, to niezależnie od temperatury zewnętrznej też jest włączany grzejnik na czas minutesOn. Dlatego układ może pracować z jednym (wewnętrznym) czujnikiem temperatury.  Podczas pracy grzejnika temperatura nie jest kontrolowana.  Gdy brak czujnika temperatury, to wyświetlana jest temperatura -127 ºC. Wejście w trybu MANUAL po zalogowaniu się http://IP/login lub wciśnięciu tryb MANUAL.  Aby zalogować się należy podać login admin i hasło esp8266. Tryb „MANUAL” umożliwia ręczne przełączanie stanu przekaźnika. Po określonym czasie (ileM), gdy nic nie jest zmieniane –  automatycznie przechodzi w stan AUTO. Tryb MANUAL sygnalizowany jest migotaniem diody LED wmontowanej w układ ESP8266 ESP-12E,  istnieje możliwość ręcznego załączenia przekaźnika. W tryb „AUTO” – automatyczne sterowanie przekaźnikiem zależnie od temperatury, nie można sterować ręcznie. Program posiada możliwość odczytania  podłączonego jednego czujnika i przypisania go do czujnika zewnętrznego lub wewnętrznego. Aby przypisać adres drugiego czujnika, należy podłączyć tylko drugi czujnik odłączając pierwszy.

Zacznij od utworzenia klasy NoFreeze(), która ma obsłużyć całe to urządzenie. Utwórz plik NoFreeze.h i umieść w poniższą zawartość.

#ifndef NOFREEZE_H_
#define NOFREEZE_H_

#include "Relay.h"
#include <DallasTemperature.h>
// funkcja oblicza czas w ms kiedy ma się zakończyć czynność,
// która ma trwać podaną ilość minut
unsigned long fminutes( int );
//zbiór licz szesnastkowych potrzebny do zamiany
// adresu na string
char const hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B','C','D','E','F'};

class NoFreeze {
public:
 float tempout = 30.0; //temperatura na zewnątrz
 float tempinput = 31.0; // temperatura wewnątrz
 DeviceAddress AddrTemp; //adres pomocniczy czujnika temperatury
 DeviceAddress AddrTempIn; //adres wewnętrznego czujnika temperatury
 DeviceAddress AddrTempOut; //adres zewnętrznego czujnika temperatury
 int minutesOn = 10; // ile minut ma być włączony grzejnik
 int minutesOff = 3; // ile minut czekać na ponowne załączenie
 unsigned long timeOn = 0; //czas załączenia przekaźnika
 unsigned long timeOff = 0; //czas wyłączenia przekaźnika
 double long timeM = 0; //czas rozpoczęcia trybu MANUAL
 float tempo = -3; // próg temperatury zewnętrznej
 float tempi = 5; // próg pierwszy temperatury wewnętrznej
 float tempi2 = 4; // próg drugi temperatury wewnętrznej
 float temp = 0; // zmienna pomocnicza
 float tempMiniIn = 30; //osiągnięta temperatura minimalna IN
 float tempMiniOut = 30; //osiągnięta temperatura minimalna OUT
 bool bmode = true; // tryb pracy true = AUTO, false = MANUAL
 Relay relay1; // przekaźnik 1
 Relay led0; // LED wbudowany
 volatile unsigned long timeSetOn = 0; //suma czasu (minut) załączenia grzejnika

public:
 NoFreeze();//konstruktor
 virtual ~NoFreeze(); //destruktor
 void begin(); //uruchom obiekt
 void setAuto(); //ustaw tryb AUTO
 void setManual(); //ustaw tryb MANUAL
 void readTemp(); //czyta wszystkie czujniki temperatury
 float readTempIn(); //podaje temperaturę wewnętrzną
 float readTempOut(); //podaje temperaturę zewnętrzną
 void readAddressTemp(); //czyta adres czujnika na pozycji 0
 void setAddressTempIn(void); //odczytany adres przydziela czujnikowi wewnętrznemu
 void setAddressTempOut(void); //odczytany adres przydziela czujnikowi zewnętrznemu
 bool readMode(); //podaje jaki tryb ustawiony true dla AUTO lub false dla MANUAL
 void working(); //główny program
 void setTimeOn(); //czas załączenia przekaźnika
 void setTimeOff(); //czas wyłączenia przekaźnika
 String adr2str(DeviceAddress); //zamienia adres na string
 void readEEProm(void); //czyta adresy z EEPROM
 void saveEEProm(void); //zapisuje adresy do EEPROM
};
#endif /* NOFREEZE_H_ */

Opisy w pliku nagłówkowym powinny być wystarczające. Utwórz plik NoFreeze.cpp i wpisz do niego zawartość jak poniżej.

/*
 * NoFreeze.cpp
 *
 * Created on: 21.09.2016
 * Author: jant
 */

#include <DallasTemperature.h>
#include <OneWire.h>
#include "NoFreeze.h"
#include "Relay.h"
#include <EEPROM.h>

#define pin_relay1 D1 // pin z przekaźnikiem
#define pin_LED BUILTIN_LED // pin z wbudowanym LED
#define pinOW D2 // pin z szyną 1-Wire

//utwórz obiekt onrWire na pinie pinOW
OneWire oneWire(pinOW);
//utwórz obiekt sensors
DallasTemperature sensors(&oneWire);

unsigned long fminutes( int minutes)
{
 return (millis()+(60000*minutes)); //1000ms*60sek
}
//konstruktor
NoFreeze::NoFreeze() {
 led0.setPin(pin_LED);
 relay1.setPin(pin_relay1);
 EEPROM.begin(64);
}
//destruktor
NoFreeze::~NoFreeze() {
}
//ustaw tryb AUTO bmode = true
void NoFreeze::setAuto(){bmode = true;}
//ustaw trub Manual bmode = false
void NoFreeze::setManual(){bmode = false;}
//czytaj ustawiony tryb
bool NoFreeze::readMode(){return bmode;}
//oblicz czas załączenia grzejnika
void NoFreeze::setTimeOn(){
 timeOn = fminutes(minutesOn);
}
//czyta adres jednego podłączonego czujnika
//i zapamiętaj w zmiennej AddrTemp
void NoFreeze::readAddressTemp(void){
 sensors.getAddress(AddrTemp, 0);
 return ;
}
//zamień adres czujnika na string
String NoFreeze::adr2str(DeviceAddress Adr){
 String adrstr;
 for( int i = 0; i < 8; i++ )
 {
 char const byte = Adr[i];
 adrstr += hex_chars[ ( byte & 0xF0 ) >> 4 ];
 adrstr += hex_chars[ ( byte & 0x0F ) >> 0 ];
 }
 return adrstr;
}
//czytaj temperaturę wewnętrzną
void NoFreeze::setAddressTempIn(void){
 readAddressTemp();
 //przepisz dane z AddrTemp do AddrTemIn
 memcpy(AddrTempIn,AddrTemp,sizeof(AddrTemp));
 saveEEProm();//zapisz pamięć EEPROM
 return;
}
//czytaj temperaturę zewnętrzną
void NoFreeze::setAddressTempOut(void){
 readAddressTemp();
 //przepisz dane z AddrTemp do AddrTempOut
 memcpy(AddrTempOut,AddrTemp,sizeof(AddrTemp));
 saveEEProm(); //zapisz pamięć EEPROM
 return ;
}
//czytaj dane z pamięci EEPROM
void NoFreeze::readEEProm(void){
 int offset = 16;//przesunięcie w pamięci między adresami
 //przepisz z EEPROM do zmiennych
 for (int i=0; i<8; i++){
 AddrTempIn[i] = EEPROM.read(i);
 AddrTempOut[i] = EEPROM.read(i+offset);
 }
 return;
}
//zapisz adresy do EEPROM
void NoFreeze::saveEEProm(void){
 int offset = 16;
 //przepisz adresy do EEPROM
 for (int i=0; i<8; i++){
 EEPROM.write(i,AddrTempIn[i]);
 EEPROM.write(i+offset,AddrTempOut[i]);
 }
 EEPROM.commit();//zapisz EEPROM
 return;
}
//oblicz czas wyłączenia grzejnika
void NoFreeze::setTimeOff(){
 timeOff = fminutes(minutesOff);
}
//uruchom klasę
void NoFreeze::begin(){
 led0.begin();
 relay1.begin();
 readEEProm();
 readTemp();
}
//czytaj temperatury
void NoFreeze::readTemp(){
 sensors.requestTemperatures(); //uruchom odczyt czyjników temperatury
 delay(1000);
 temp = sensors.getTempC((uint8_t*)AddrTempIn); //czytaj temperaturę w ºC
 // gdy brak czujnika ustaw temperaturę dodatnią
 tempinput = (temp==-127) ? 30 : temp;
 //gdy temperatura minimalna jest większa to zapamiętaj
 if (tempinput<tempMiniIn) tempMiniIn=tempinput;
 temp = sensors.getTempC((uint8_t*)AddrTempOut); //czytaj temperaturę w ºC
 // gdy brak czujnika ustaw temperaturę dodatnią
 tempout = (temp==-127) ? 31 : temp;
 //gdy temperatura minimalna jest większa to zapamiętaj
 if (tempout<tempMiniOut) tempMiniOut=tempout;
}
//czytaj temperaturę wewnętrzną
float NoFreeze::readTempIn(){
 //uruchom czytanie temperatur
 sensors.requestTemperatures();
 delay(1000); //czekaj na zakończenie czytania
 //zwróć temperaturę wewnętrzną
 return sensors.getTempC((uint8_t*)AddrTempIn);
}
//czytaj temperaturę zewnętrzną
float NoFreeze::readTempOut(){
 //uruchom czytanie temperatur
 sensors.requestTemperatures();
 delay(1000); //czekaj na zakończenie cztania
 //zwróć temperaturę zewnętrzną
 return sensors.getTempC((uint8_t*)AddrTempOut);
}
//program główny
void NoFreeze::working(){
 if (timeM <= millis()){ setAuto();} // sprawdzaj czas trwnia MANUAL, gdy minie przełącz na AUTO
 /////// AUTO
 if (bmode) { // praca w trybie AUTO
  if (timeOn<=millis())// gdy minął czas załączenia 
  {
  readTemp();
  // gdy temperatura wewnątrz spadnie poniżej tempi2
  // lub gdy temperatura na zewnątrz spadnie poniżej tempo
  // i temperatura wewnątrz spadnie poniżej tempi
  // włącz przkaźnik i oblicz czas załączenia
   if (((tempinput <= tempi) || (tempout <= tempo)) && (tempinput <= tempi2))
   {
   timeOn = fminutes(minutesOn); // oblicz czas załączenia
   relay1.setOn(); // załącz przekaźnik 1
   timeSetOn += minutesOn;//sumuj czas załączenia
   }
   else
   { // w przeciwnym razie, gdy przekaźnik załączony, wyłącz przekaźnik
   // i oblicz czas wyłączenia
    if (relay1.read()==1){
    relay1.setOff();
    timeOff = fminutes(minutesOff); // oblicz czas wyłączenia
    }
   }
  }
 }
 ////////end AUTO
}

Analiza działania programu powinna być już zrozumiała. W dalszej części opiszę strony www dla tego urządzenia.

 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *