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ą;
- Urządzenie WeMos D1 mini + ładowarka 5V 500mA.
- Moduł przekaźnika do WeMos D1 min.
- Dwa czujniki temperatury DS18S20.
- Rezystor 4.7k.
- 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.

