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.