Ich habe hier einen Kaminofen im Wochenendhaus zu stehen. Dieser hat, wie jeder Ofen dieser Preisklasse natürlich
keine temperaturabhängige Regelung der Zuluftklappe. Dies hat zur Folge, daß beim unbeobachteten Heizen entweder
die gewollte Abgastemperatur nicht erreicht wird, bzw. das Heizgut zu schnell abbrennt und im Anschluss der Ofen
schnell wieder auskühlt, falls die Klappe zu weit offen ist. Es gibt für einige Öfen Bimetallregler. Die passen aber nicht
für jeden Ofen. Also ist eine Eigenkonstruktion angesagt.
Zuerst habe ich mir einen Stellmotor für die Luftklappe besorgt. Gut geeignet sind Motoren aus Lüftungsanlagen. Die
bekommt man in allen möglichen Ausführungn.
Mein Motor:
Betriebsspannung: 24V AC/DC
Leistungsaufnahme: 4VA / 1,5W
Lastgesteuert: Das bedeutet, er hat keine Endschalter.
Drehmoment: 10 Nm
Stellwinkel: ca. 100°
Fahrzeit für 100°: 150 s
Wichtig war mir der Betrieb ohne 230V Netzspannung. Die gesamte Steuerung wird über ein handelsübliches Stecker-Netzteil
versorgt. Damit gibt es keine Probleme bei der Gehäusegestaltung wegen Trennung von Netzspannung und Kleinspannung.
Alles andere wäre um ein Vielfaches aufwändiger, was die Sicherheit angeht. Ich bin Elektriker und weiß, wovon ich spreche.
Hier der Motor und die Ankopplung an die Klappe:
Dazu gehört der Hochtemperaturfühler PT1000 am Abgasrohr.
Temperaturfest bis 500°C:
Installiert wurde alles in Alurohr bis hin zum Steuergerät:
Das Gehäuse des Steuergerätes ist ein gekauftes Standardgehäuse. Die Steuerungsmöglichkeiten sind begrenzt und das Minidisplay
dient nur der schnellen Kontrolle der Funktionen, Messwerte und des Betriebszustandes.
Mittlerweile drucke ich mir meine Gehäuse nach Bedarf selber.
Die tägliche Bedienung erfolgt per App über Bluetooth bzw. per USB-Schnittstelle. Auf dem 3. Bild ist das USB-Kabel angeschlossen
um die Programmierung zu ändern.
Hier die App zum steuern des Ofens:
Das ist die etwas aufwendigere Anzeige. Sie dient nur zu Prüfzwecken. Die einfache Version ist wesentlich übersichtlicher.
Es ist alles sehr flexibel anpassbar. Ob Tablett oder Smartphone, alles ist in der Größe anpassbar.
Die App nennt sich "Bluetooth Electronic", ist absolut werbefrei und ist für mich das absolute Muss.
Weiter gehts mit der Steuerung:
Der gesamte Aufbau besteht aus:
Ein Arduino NANO
Ein Temperaturfühler PT1000 mit Meßwandler der Firma Pollin
Ein RTC-Baustein (misst gleichzeitig die Raumtemperatur
Ein Relaisbaustein
Ein Spannungswandler 24V/5V
Ein Display mit 4 Tasten von der Firma ELV.
Ein Bluetooth Modul HC-06
Ein Pegelwandler für das Bluetooth Modul
Und zu guter letzt ein Steckernetzteil 24V DC
Bei Interesse:
Fortsetzung folgt
Kaminofen Klappensteuerung
Moderatoren: schnurzel59, eltoro
- eltoro
- Site Admin
- Beiträge: 8
- Registriert: Di Feb 26, 2019 12:14 am
- Wohnort: Brandenburg
Re: Kaminofen Klappensteuerung
Hier schon mal zum Geniessen der mittlerweile seit mindestens 2015 laufende Code.
An 1000 Stellen optimierbar, aber : "never touch a running system"
An 1000 Stellen optimierbar, aber : "never touch a running system"
Code: Alles auswählen
#include <DS3231.h> //Uhrenmodul
#include <EEPROM.h>
#include "Wire.h"
#include "TwoWireLCD.h"
//#include "PinChangeInt.h"
#include <SoftwareSerial.h>
char progVersion[] {"13_2_BT"}; // 25.1.20
// Zeiteinstellung
//+++++++++++++++++++ Neue Auswertung PAP-designer ++++++++++++++++
SoftwareSerial BTSerial(10,11); // RX, TX (Board); TX, RX (Modul) BlueToth
// Init the DS3231 using the hardware interface
DS3231 rtc(SDA, SCL);
// Init a Time-data structure
Time t;
char TasteSer; // Taste Serielle Eingabe vom Terminal
unsigned char second = 0; //
unsigned char minute = 0;
unsigned char hour = 0;
int T1; // RohrTemperatur
// Status n=Neustart, t=Timer läuft (Klappe fährt), p=Pause
char Status = 'n';
char Folgebefehl = 'P'; // B=Blockieren, F=12s auf, S=Schließen, T=Turbo
uint8_t Anzeige = 0; // 0=Raum 1=Rohr 2=KlappeWinkel 3=Anheizenstatus 4=usw
uint8_t Heizphase = 1; // 1=Anheizen bis Rohrtempmax 0= rohrtempmax erreich 2=wenn unter
// 120 grad dann bleibt Klappe zu
int KlappeOffset = 0; // verhindert Klappe ganz zu bis unter 120°C
uint8_t RTOffset; // Klappenoffset in Abhängigkeit von Raumtemperatur
int KlappeWAkt = 0; // 0= zu 150= auf
int KlappeWNeu =0, KlappeWAktAlt=0,KlappeMittOeffnung=14,KlappeZug=18;
int KlappeWeit=19;
// [9]-eeAdRohrGrund ={18}
int eeAdresse, eeWert; // Temp Adresse zum Einzelne Daten schreiben
int eeAd[] {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40};
bool TimerStop = false; //Unerbrechung möglich j n
int8_t TastenCode = 0; // 1. oder 2. Belegung 0,4,8 oder 8= kein Befehl
int RohrTemp, RohrTempMin, RohrTempMax,RohrTempMitte,RohrTempTief=100, RohrTempAlt, RohrDiff, RohrTempFenster=50;
int RohrGrund=170, RohrDiffFakt=7; // für Berechnung RohrTempMin
char RohrTempTendenz = 'n'; // +, n (neutral), -
int RaumTemp, RaumTempAlt, RaumTempZiel=23, RaumTempKorr=4;
float RaumTempF; // für Temperaturanzeige mit Nachkommastellen
bool AuswertungFertig = 0;
int PT1000 = 0;
int PT1000Offset=0; //Offset für Rohrtemperatur
int x;
int ZStunde, ZMinute, ZSekunde;
const char KlappeZu = 8 ; // Relais Klappe zu an Pin 8
const char KlappeAuf = 7 ; // Relais Klappe auf an Pin 7
unsigned long pos; // für KlappeFahrtD
unsigned long AlteZeit5 =0 ;
unsigned long EndZeit5= 1800000; // 1/2 Stunde
unsigned long AlteZeit4=0,EndZeit4=1000; // 1 sec für schnellere Ausgaben
unsigned long AlteZeit = 0 , EndZeit=0; // Klappenlaufzeit
unsigned long AlteZeit2 = 0 , EndZeit2 = 4000; // 2 sec Displayausgabe Wiederholung
unsigned long AlteZeit3 = 0 , EndZeit3 = 40000;// 180 sec Auswertezeit Wiederholung
int ZFaktor = 0; // Zähler wie oft abgekühlt
char Text1[] = "RaumRohrKlapMaxTMinTStatZeitFaktDiffVers";
char Phase='A',PhaseAlt='A';
bool Buzzer=true;
int KlappeFahrt(unsigned long, char);
unsigned long messzeit; // Für Schleifenzeitmessung
void keyPress(); // Funktion wenn Gerätetaste gedrückt
void TimerStart(unsigned long); // Funktion Klappentimer
unsigned char keys; // Zustand der Tasten am Gerät
unsigned char keysAlt;
volatile unsigned char keyPressDetected = 0; // Anzeige, ob eine Taste am Gerät gedrückt wurde
volatile int keyanzahl=0;
void(*resetFunc)(void)=0; // Resetfunktion zu adresse 0
void sekundenBefehle(); // Funktion Ausführung jede sekunde
void HPhase(uint8_t); // Heizphase setzen und speichern
int KlappeFahrtD(unsigned long);
void eePromEinzelnWrite();
void eePromEinzelnRead();
void eePromReadZuweisen();
int eepromReadInt(int);
void Zeitanzeige();
void eepromWriteInt(int, int);
char getCommand();
//***********************************************************
void setup()
{
//eepromWriteInt(eeAd[12],19); // EINMALIG zum setzen des Grundwertes
//eepromWriteInt(eeAd[11],14); // EINMALIG zum setzen des Grundwertes
//RohrGrund=176;
// der Interrupt-Pin des I2C-LCD-Moduls liegt auf dem Pin D15=A1 (jetzt D2) des Arduino-Boards
pinMode(2, INPUT); // Gerätetastatur Funktionsaufruf bei Tastendruck.
attachInterrupt(digitalPinToInterrupt(2), keyPress, FALLING); // durch Interrupt(0) Pin D2
// BT und Terminal auch möglich: attachInterrupt(0, keyPress, FALLING) (RISING CHANGE)
BTSerial.begin(19200); // Bluetooth
Serial.begin(115200); // Terminal
// Initialisierung des I2C und des I2C-LCD-Moduls
Wire.begin();
LCD.begin();
// den Interrupt des I2C-LCD-Moduls zurücksetzen und anschließend aktiveren.
LCD.resetKeyInterrupt();
LCD.enableKeyInterrupt();
// Setup Serial connection
pinMode(KlappeZu, OUTPUT);
pinMode(KlappeAuf, OUTPUT);
rtc.begin(); // Uhrenmodul startet
digitalWrite(KlappeZu, 1); // Relais 1 aus
digitalWrite(KlappeAuf, 1); // Relais 2 aus
// Zum Uhr stellen folgende Zeilen Auskommentierung entfernen
//rtc.setDOW(SUNDAY); // Setze Wochentag
//rtc.setTime(10, 40, 00); // Setze Zeit 08:44:15 (24hr format)
//rtc.setDate(25, 01, 2020); // Setze Datum 26.11.2016
//---------------------------------------------------------------------------------
Status = 'n'; // Neustart
//Folgebefehl = 'F'; // Öffnen nach Neustart
TimerStop = false; // keine Unterbrechung möglich
TastenCode = 0; // Belegung 8=kein Tastendruck möglich
Serial.print(F("Status = n (Neustart). Startzeit millis = "));
Serial.println(millis());
LCD.setLeds(~0);
eePromReadZuweisen(); // EEPROMDATEN lesen und zuweisen
Serial.println("Aktuelle EEPROMWERTE");
RohrTempFenster=50; // ARCHTUNG FEHLER NOCH NICHT GEFUNDEN
for(x=0;x<=12;x++)
{
Serial.print(eepromReadInt(eeAd[x]));
Serial.print(" ");
}
delay(10000);
AlteZeit2 = millis(); // Anzeigetimer auf 0
AlteZeit3 = millis(); // Auswertezeit auf 0
AlteZeit4 = millis();
AlteZeit5 = millis();
RaumTemp = (rtc.getTemp());
RaumTemp = RaumTemp - RaumTempKorr; // Raumtemperatur korrigieren
RohrTempMin = RohrGrund + ((RaumTempZiel - RaumTemp) * RohrDiffFakt); // Untere Temperatur
RohrTempMax = RohrTempMin + RohrTempFenster; // obere Temperatur (+50°)
Serial.print("RohrGrund --- ");
Serial.println(RohrGrund);
T1 = ((analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000))/3)+PT1000Offset;
RohrTemp = T1;
RohrTempAlt=RohrTemp;
if (RohrTemp<RohrTempMax)
{
EndZeit3 = ((((RohrTempFenster/2+RohrTempMin) - RohrTemp) * 1000UL) + 40000UL);
}
else
{
EndZeit3=40000;
}
if ((RohrTemp > RohrTempMin) && (RohrTemp < RohrTempMax) || (RaumTemp >= RaumTempZiel))
{
HPhase (0);
}
}
//************************ Start Loop ******************************
void loop()
{
// ---------- einmal pro Stunde Klappe justieren --------------
if (millis()-AlteZeit5> EndZeit5)
{
//EndZeit3=(KlappeWAkt*2+10)*1000;
AlteZeit5=millis();
//KlappeWAktAlt=KlappeWAkt;
//Folgebefehl='G';
//KlappeFahrt(KlappeWAkt+3,'z');
if ((Heizphase==1)&&(RohrTemp<RohrTempTief)) // Wird zu langsam warm
{
Folgebefehl='B';
Heizphase=2;
KlappeFahrtD(0);
}
}
//// ----------------------- Zeitmessung loop ---------------------------------
// Serial.print(" ein loop dauert (ms) = ");
// Serial.println(millis()-messzeit);
// messzeit=millis();
//// ----------------------- Zeitmessung Ende -----------------------------------
if (millis() -AlteZeit4 > EndZeit4) // alle 1sec ausführen
{
AlteZeit4= millis();
sekundenBefehle(); // Funktion: alles was einmal pro sec läuft
}
// ----------------------- alle 2 sec ausführen----------------------------------
if (millis() - AlteZeit2 > EndZeit2)
{ AlteZeit2 = millis();
RaumTemp = (rtc.getTemp()); //Temperatur von Uhr holen
RaumTemp = RaumTemp - 4;
RohrTempMin = RohrGrund + ((RaumTempZiel - RaumTemp) * RohrDiffFakt); // bei 10° =240 bei 25° 150
RohrTempMax = RohrTempMin + RohrTempFenster;
RohrTempMitte=RohrTempFenster/2+RohrTempMin;
//------- Rohrtemperatur einlesen --------------
T1 = (analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000))/5;
RohrTemp =T1+PT1000Offset; // reelle werte errechnen
Serial.print(F("RohrSensoraKTUELL "));
Serial.print(T1);
Serial.print(" ");
Serial.println(RohrTemp);
//------------------------- Anzeige der Daten -------------------------------
//---------- Ausgabe auf Display am Gerät --------------------------
LCD.clearSegments();
++Anzeige; //--- Namme aus Array
switch (Anzeige) // auswerten
{
case 1:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 2:
RaumTempF = (rtc.getTemp());
RaumTempF = RaumTempF - 4;
LCD.print(RaumTempF * 100, NO_LEADING_ZEROS, 2);
break;
case 3:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 4:
LCD.print(RohrTemp * 1, NO_LEADING_ZEROS, 0);
break;
case 5:// Ausgabe K und Winkel KlappeWAkt
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 6:
LCD.print(KlappeWAkt, NO_LEADING_ZEROS, 0);
break;
case 7:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 8:
LCD.print(RohrTempMax, NO_LEADING_ZEROS, 0);
break;
case 9:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 10:
LCD.print(RohrTempMin, NO_LEADING_ZEROS, 0);
break;
case 11:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 12:
LCD.print(Heizphase, NO_LEADING_ZEROS, 0);
break;
case 13:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 14:
LCD.print(((millis() - AlteZeit3) / 1000), NO_LEADING_ZEROS, 0);
break;
case 15:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 16:
LCD.print(ZFaktor, NO_LEADING_ZEROS, 0);
break;
case 17:
LCD.print(&Text1[(Anzeige - 1) / 2 * 4], 4);
break;
case 18:
LCD.print(RohrDiff, NO_LEADING_ZEROS, 0);
break;
case 19:
LCD.print(&Text1[(Anzeige - 1) / 2 *4], 4);
break;
case 20:
LCD.print(progVersion, 4);
break;
case 21:// Anzeige auf 0 setzen
Anzeige = 0;
break;
default:
break;
}
//LCD.showColon(second & 0x02);
LCD.update();
//---------- Ausgabe auf Display am Gerät fertig --------------------------
//------------- Anzeige fertig ----------------------------------------
//------------- Serielle Ausgabe Terminal --------------------------------------
Serial.print(F("PROGRAMMVERSION"));
Serial.println(progVersion);
Serial.print(F("AlteZeit5 "));
Serial.println((EndZeit5/1000)-((millis()-AlteZeit5)/1000));
Serial.print(F("Raumtemperatur "));
Serial.println(RaumTempF);
Serial.print(F("Raumtemp Ziel "));
Serial.println(RaumTempZiel);
Serial.print(F("RohrTempMax "));
Serial.println(RohrTempMax);
Serial.print(F("ROHRTEMPERATUR "));
Serial.println(RohrTemp);
Serial.print(F("RohrGrund "));
Serial.println(RohrGrund);
Serial.print(F("RohrTempMin "));
Serial.println(RohrTempMin);
Serial.print(F("RohrDifferenz = "));
Serial.print(RohrDiff);
Serial.println(RohrTempTendenz);
Serial.print(F("Klappe Winkel "));
Serial.println(KlappeWAkt);
Serial.print(F("Heizphase= "));
Serial.print(Heizphase);
Serial.print(PhaseAlt);
Serial.println(Phase);
Serial.print(F("millis - AlteZeit3 = "));
Serial.println(((millis() - AlteZeit3) / 1000));
Serial.print(F("EndZeit 3 ist eingestellt auf: "));
Serial.println(EndZeit3 / 1000);
Serial.print(F("Folgebefehl: "));
Serial.println(Folgebefehl);
Serial.print(F("Zeit seit letzter Klappenbewegung: "));
Serial.println(((millis() - AlteZeit) / 1000));
Serial.print(F("ZFaktor = "));
Serial.println(ZFaktor);
Serial.print(F("Buzzer = "));
Serial.println(Buzzer);
Serial.print(F("KEYANZAHL = "));
Serial.print(keyanzahl);
if (keysAlt!=255)
{
Serial.println(keysAlt);
}
Serial.print(F("TASTENCODE = "));
Serial.println(TastenCode);
Serial.print(F("TimerStop = "));
Serial.println(TimerStop);
Serial.print(" ------- RohrtempMitte= ");
Serial.println(RohrTempFenster/2+RohrTempMin);
Serial.print("KlappeMIttOeffnung ");
Serial.println(KlappeMittOeffnung);
Serial.print("KlappeWeit");
Serial.println(KlappeWeit);
//-----------------Serielle Ausgabe Terminal fertig ---------------------------
//-----------------Serielle Ausgabe an PC -------------------------------------
//byte i; // Beispiel 100 mal Wert an Instrumente
//for (i = 0; i < 100; i++){
//SendString(1,RaumTemp); // Instrument #01
//SendString(2,RohrTemp); // Instrument #40
//SendString(41,i); // Instrument #41
//SendString(2,i); // Instrument #02
//SendString(42,i); // Instrument #42
//SendString(43,i); // Instrument #43
//SendString(90,i); // Instrument #90
//SendString(44,i); // Instrument #44
//SendString(60,i * 2); // Instrument #60
//delay(500);
//}
//----------------- Ausgabe Bluetooth-------------------------------------------
BTSerial.print("*k");
BTSerial.print(eepromReadInt(eeAd[4]));
BTSerial.print("*");
BTSerial.print("*v");
BTSerial.print(progVersion);
BTSerial.print("*");
BTSerial.print("*r");
BTSerial.print(RaumTempF);
BTSerial.print(",");
BTSerial.print(RaumTempZiel);
BTSerial.print("*");
BTSerial.print("*R");
BTSerial.print(RaumTempF);
BTSerial.print("*");
BTSerial.print("*Z");
BTSerial.print(RaumTempZiel);
BTSerial.print("*");
BTSerial.print("*O");
BTSerial.print(RohrTemp);
BTSerial.print("*");
BTSerial.print("*o");
BTSerial.print(RohrTemp);
BTSerial.print(",");
BTSerial.print(RohrTempMax);
BTSerial.print(",");
BTSerial.print(RohrTempMin);
BTSerial.print(",");
BTSerial.print(RohrTempMitte);
BTSerial.print("*");
BTSerial.print("*K");
BTSerial.print(KlappeWAkt);
BTSerial.print("*");
BTSerial.print("*N");
BTSerial.print(RohrTempMax);
BTSerial.print("*");
BTSerial.print("*n");
BTSerial.print(RohrTempMin);
BTSerial.print("*");
BTSerial.print("*z");
BTSerial.print(AlteZeit);
BTSerial.print("*");
BTSerial.print("*S");
BTSerial.print(Heizphase);
BTSerial.print("*");
BTSerial.print("*V");
BTSerial.print(RohrTempTendenz);
BTSerial.print("*");
BTSerial.print("*sR255G120B0*");
BTSerial.print("*E");
BTSerial.print(EndZeit3 / 1000);
BTSerial.print("*");
BTSerial.print("*L");
BTSerial.print((millis() - AlteZeit3) / 1000);
BTSerial.print("*");
BTSerial.print("*U");
BTSerial.print(EndZeit/1000);
BTSerial.print("*");
BTSerial.print("*F");
BTSerial.print(ZFaktor);
BTSerial.print("*");
BTSerial.print("*D");
BTSerial.print(RohrDiff);
BTSerial.print("**w");
//BTSerial.print("*w");
BTSerial.print(KlappeWeit);
BTSerial.print("**x");
//BTSerial.print("*x");
BTSerial.print(KlappeMittOeffnung);
BTSerial.print("*");
//----------- Ausgabe Bluetooth fertig-------------------------------------------------
if (Folgebefehl=='B') //-------------------Zustand blockieren für 6 min --------------
{
EndZeit3=(60000UL*480UL);
Folgebefehl='P';
}
if (Folgebefehl=='W') //-------------------in 10 sec weiter-----------------
{
EndZeit3=5000; //------------------ Endzeit neu---------------
Folgebefehl='P'; //------------------- Kein Befehl --------------
}
if (Folgebefehl=='T') //----------------- Turbo Klappe 3min auf +15
{
EndZeit3=480000;
KlappeFahrt(15,'a');
Folgebefehl='t';
}
if (Folgebefehl=='A')
{
EndZeit3=20000;
Folgebefehl='P';
KlappeFahrt(15,'z') ;
}
//----- Neue Auswertung ---------------------------------------------------------------------------------------------------
//----- Normale Auswertung ALTE VERSION -----------------------------------------------------------------------------------
if (millis() - AlteZeit3 > EndZeit3) // 3 min
{
if (Folgebefehl=='t')
{
EndZeit3=20000;
Folgebefehl='P';
//Phase='t';
KlappeFahrtD(KlappeWeit);
}
if (Folgebefehl=='B')
{
//Phase='b';
Folgebefehl='W';
}
//if (Folgebefehl=='A')
// {
// Phase='a';
// Folgebefehl='W';
// KlappeFahrt(15,'z') ;
// }
AlteZeit3 = millis();
//-------------------- Neue Auswertungsvariante siehe PAP ------------------------
//--------------------------RohrTemp einlesen Rohrdaten berechnen-----------------
T1 = (analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000)+analogRead(PT1000))/5;
RohrTemp = T1+PT1000Offset; // reelle werte errechnen
RohrDiff = RohrTemp - RohrTempAlt; // differenz alte und neue Rohrtemperatur
RohrTempMin = RohrGrund + ((RaumTempZiel - RaumTemp) * RohrDiffFakt); // bei 10° =275 bei 25° 200
RohrTempMax = RohrTempMin + RohrTempFenster;
//EndZeit3 = (((RohrTempMax - RohrTemp) * 1000UL) + 90000UL); // Zeit bis zur nächsten Auswertung
if (RohrTemp<RohrTempMax)
{
EndZeit3 = ((((RohrTempFenster/2+RohrTempMin) - RohrTemp) * 1000UL) + 40000UL);
}
else
{
EndZeit3 = ((((RohrTempFenster/2+RohrTempMin) - RohrTemp) * 500UL) + 40000UL);
}
Serial.print(F("RohrSensor "));
Serial.println(T1);
//-------------------------- Rohrberechnung fertig ------------------------------
//-------------------------RohrTempTendenz berechnen-----------------------------
if (RohrTemp> RohrTempAlt+1)
{
RohrTempTendenz = '+'; // Temp steigt Z-Faktor =0
if (ZFaktor>0)
{
ZFaktor--;
}
}
else if (((RohrTemp<RohrTempAlt)&&(RohrTemp<RohrTempMin))||(RohrTemp<30))
{
RohrTempTendenz = '-'; //---- RohrTempTendenz -----------
ZFaktor++;
}
else if (RohrTemp==RohrTempAlt)
{
RohrTempTendenz='n';
}
RohrTempAlt = RohrTemp; // aktuelle Rohrtemperatur
AuswertungFertig = 0;
//---------------------------RohrTempTendenz fertig--------------------------------
if ((RaumTemp>=RaumTempZiel)&&(Heizphase!=2))
{ //ja
Heizphase=2;
KlappeWNeu=0;
PhaseAlt=Phase;
Phase='A';
}
else
{
if (Heizphase!=1)
{
if (Heizphase==2)
{
Folgebefehl='B';
KlappeWNeu=0;
PhaseAlt=Phase;
Phase='B';
}
else
{
if (RohrTemp>=RohrTempMax)
{
Serial.println("----------Rohr> RohrMax");
Serial.print(RohrTemp);
Serial.print(" ");
Serial.println(RohrTempMax);
KlappeWNeu=5; //Test wegen Klappendifferenz bei 0
PhaseAlt=Phase;
Phase='C';
}
else
{
if (RohrTemp<(RohrTempFenster/2+RohrTempMin))
{
Heizphase=2;
KlappeWNeu=0;
PhaseAlt=Phase;
Phase='d';
}
else
{
Serial.println("----------Rohr kleiner RohrMax");
//Heizphase=1;
KlappeWNeu=KlappeMittOeffnung;
PhaseAlt=Phase;
Phase='D';
}
}
}
}
else
{
//KlappeWNeu=KlappeMittOeffnung;
if ((RohrTemp>RohrTempMin)&&(RohrTemp<(RohrTempFenster/2+RohrTempMin)))
{
KlappeWNeu=9;
PhaseAlt=Phase;
Phase='e';
}
PhaseAlt=Phase;
Phase='E';
if (RohrTemp>=(RohrTempFenster/2+RohrTempMin))
{
if (RohrTemp>=RohrTempMax)
{
Heizphase=0;
KlappeWNeu=0;
PhaseAlt=Phase;
Phase='F';
}
else
{
KlappeWNeu=KlappeMittOeffnung;
// Heizphase=1;
PhaseAlt=Phase;
Phase='G';
}
}
else
{
KlappeWNeu=KlappeWeit+ZFaktor;
PhaseAlt=Phase;
Phase='H';
}
if (RohrTempTendenz=='-')
{
//ZFaktor++;
PhaseAlt=Phase;
Phase='I';
}
else if(RohrTempTendenz=='+')
{
//if (ZFaktor>0)
//{
//ZFaktor--;
//}
PhaseAlt=Phase;
Phase='J';
}
if ((ZFaktor>=6)&&(RohrTemp<RohrTempMin) )
{
Heizphase=2;
PhaseAlt=Phase;
Phase='K';
BTSerial.print("*B*");
}
}
} // IF 1 ende
if ((RohrTemp>RohrTempTief)&&(RohrTemp<RohrTempMax+25)) // Rohrtemptief einstellen
{
KlappeOffset=2;
}
else
{
KlappeOffset=0;
}
if ((KlappeWNeu==0)&&(RohrTemp > 120) && (Heizphase < 2) && (RaumTemp <= RaumTempZiel)&&(RohrTemp<RohrTempMax+15) )
{
RTOffset = KlappeOffset + (RaumTempZiel - RaumTemp); // lässt Klappe weiter offen, wenn Raumtemp nicht erreicht ist
KlappeWNeu=RTOffset; //Offset, damit Klappe nicht ganz zu geht
}
eepromWriteInt(eeAd[2],KlappeOffset);
KlappeFahrtD(KlappeWNeu);
if ((RohrTemp< (RohrTempFenster/2+RohrTempMin))&&(Buzzer==true))
{
Buzzer=false;
BTSerial.print("*B*");
}
else if ((RohrTemp> (RohrTempFenster/2+RohrTempMin))&&(Buzzer==false))
{
Buzzer=true;
BTSerial.print("*B*");
}
eepromWriteInt(eeAd[0],Buzzer);
//++++++++++++++++++++++++++++++ ALT +++++++++++++++++++++++++++++++++++++++++++++++
//----- entfernt
// ++++++++++++++++++++++++++++++++++++++++++ ALT ++++++++++++++++++++++++
BTSerial.print("*p");
BTSerial.print("Phase ");
BTSerial.print(PhaseAlt);
BTSerial.print(Phase);
BTSerial.print("*");
} // Ende EndZeit3
} // Ende EndZeit2
// Abfrage ob Taste gedrückt. Auswertung der Tasten
//TasteSer = getCommand();//seriell eingabe Terminal
//keyPressDetected=0; //Tasten am Gerät sperren
if (keyPressDetected) //Eingabe am gerät
{
keys = (LCD.readKeys() & 240); //untere Bits ausblenden
if (keys!=255)
{
keysAlt=keys;
}
LCD.resetKeyInterrupt();
keyPressDetected = 0;
keys = keys + TastenCode;
keyanzahl++;
}
else //keine Taste gedrückt
{
keys = NO_KEY;
}
// Auswertung Tasten 1=112 2=176 3=208 4=224
switch (keys)
{
case 224: //Klappe voll auf oder zu
if (KlappeWAkt > 75)
{
LCD.setLeds(~7);
KlappeFahrt(KlappeWAkt + 5, 'z');
HPhase(1);
}
else
{
LCD.setLeds(~8);
KlappeFahrt(156 - KlappeWAkt, 'a'); // 160 sec Klappe auf
HPhase(3);
}
break;
case 208:
LCD.setLeds(~9);
KlappeFahrt(5, 'z'); // 5 sec Klappe zu
if (Heizphase < 3)
{
//Hphase(0);
}
break;
case 212:// zweite Funktion (+4)
TastenCode=0;
LCD.setLeds(~6);
break;
case 176:
TastenCode=4;
LCD.setLeds(~10);
KlappeFahrt(5, 'a'); // 5 sec Klappe auf
if (Heizphase < 3)
{
//Hphase(0);
}
break;
case 180:// zweite Funktion (+4)
TastenCode=0;
LCD.setLeds(~5);
RaumTempZiel=RaumTempZiel+1;
eepromWriteInt(eeAd[5],RaumTempZiel);
break;
case 112: // Anheizphase. heizen klappe voll zu und 20s auf
eePromReadZuweisen(); // EEPROMDATEN lesen und zuweisen
eepromWriteInt(eeAd[5],RaumTempZiel);
HPhase(1); //Anheizphase neu
LCD.setLeds(~11);
EndZeit3=40000;
EndZeit5=1800000;
AlteZeit5=millis();
Folgebefehl = 'F'; // Folgebefehl
TimerStop = false; // Timer kann nicht gestoppt werden
TastenCode = 8; // keine Tastenfunktion
ZFaktor = 0; //
RohrTempTendenz = '+';
RohrTempAlt=RohrTemp;
RohrDiff=0;
KlappeFahrt(KlappeWAkt + 5, 'z'); // Klappe voll zu
AlteZeit3 = millis();
//EndZeit3 = (((RohrTempMax - RohrTemp) * 1000UL) + 90000UL); // Endzeit3 > 90 s wenn Rohr kalt
if (RohrTemp<RohrTempMax)
{
EndZeit3 = ((((RohrTempFenster/2+RohrTempMin) - RohrTemp) * 1000UL) + 40000UL);
}
else
{
EndZeit3=30000;
}
break;
case 113:
break;
case 115:
TimerStop = true;
break;
default:
break;
}
// ---------------------------serielle Eingabe vom Terminal------------------------
TasteSer = getCommand();//seriell eingabe Terminal
switch (TasteSer)
{
case 'm':
eepromWriteInt(eeAd[11],KlappeMittOeffnung++);
KlappeFahrtD(KlappeMittOeffnung);
BTSerial.print("*x"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(KlappeMittOeffnung);
BTSerial.print("*");
break;
case 'n':
eepromWriteInt(eeAd[11],KlappeMittOeffnung--);
KlappeFahrtD(KlappeMittOeffnung);
BTSerial.print("*x"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(KlappeMittOeffnung);
BTSerial.print("*");
break;
case 'u':
eepromWriteInt(eeAd[12],KlappeWeit++);
KlappeFahrtD(KlappeWeit);
BTSerial.print("*w"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(KlappeWeit);
BTSerial.print("*");
break;
case 'v':
eepromWriteInt(eeAd[12],KlappeWeit--);
KlappeFahrtD(KlappeWeit);
BTSerial.print("*w"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(KlappeWeit);
BTSerial.print("*");
break;
case 'V':
Serial.print("-----------------------------------");
Serial.print(char(BTSerial.read()) );
Serial.print(char(BTSerial.read()) );
break;
case 'E':
EndZeit2=EndZeit2+2000;
eepromWriteInt(eeAd[10],EndZeit2);
break;
case 'F':
if (EndZeit2>2000)
{
EndZeit2=EndZeit2-2000;
eepromWriteInt(eeAd[10],EndZeit2);
}
break;
case 'J':
RohrGrund=RohrGrund+10;
HPhase(1);
eepromWriteInt(eeAd[9],RohrGrund);
break;
case 'K':
RohrGrund=RohrGrund-10;
HPhase(1);
eepromWriteInt(eeAd[9],RohrGrund);
break;
case 'L':
RohrTempFenster=RohrTempFenster+5;
HPhase(1);
eepromWriteInt(eeAd[8],RohrTempFenster);
break;
case 'M':
RohrTempFenster=RohrTempFenster-5;
HPhase(1);
eepromWriteInt(eeAd[8],RohrTempFenster);
break;
case '1':
HPhase(1); //Anheizphase neu
eePromReadZuweisen(); // EEPROMDATEN lesen und zuweisen
eepromWriteInt(eeAd[5],RaumTempZiel);
EndZeit3=40000;
EndZeit5=1800000;
AlteZeit5=millis();
Folgebefehl = 'F';
TimerStop = false;
TastenCode = 8;
ZFaktor = 0;
RohrTempTendenz = '+' ;
RohrTempAlt=RohrTemp;
RohrDiff=0;
KlappeFahrt(KlappeWAkt + 5, 'z');
AlteZeit3 = millis();
// EndZeit3 = (((RohrTempMax - RohrTemp) * 1000) + 90000); // Neu1
break;
case 'p':
HPhase(1);
break;
case 'l':
EndZeit3=600000;
KlappeFahrtD(150); //Klappe 150s auf
break;
case 't':
rtc.setTime(17, 43, 02); // Setze Zeit 08:44:15 (24hr format)
case 'h':
RaumTempZiel=RaumTempZiel+1;
eepromWriteInt(eeAd[5],RaumTempZiel);
BTSerial.print("*Z");
BTSerial.print(RaumTempZiel);
BTSerial.print("*");
break;
case 'r':
RaumTempZiel=RaumTempZiel-1;
eepromWriteInt(eeAd[5],RaumTempZiel);
BTSerial.print("*Z");
BTSerial.print(RaumTempZiel);
BTSerial.print("*");
break;
case 's':
AlteZeit3=millis();
EndZeit3=5000;
break;
case 'a':
LCD.setLeds(~10);
KlappeFahrt(3, 'a'); // 3 sec Klappe auf
break;
case 'z':
LCD.setLeds(~9);
KlappeFahrt(3, 'z'); // 3 sec Klappe zu
break;
case '2':
LCD.setLeds(~9);
KlappeFahrt(1, 'z'); // 1 sec Klappe zu
break;
case '3':
LCD.setLeds(~9);
KlappeFahrt(1, 'a'); // 1 sec Klappe auf
break;
case 'k': // komplett auf oder zu
if (KlappeWAkt > 75)
{
LCD.setLeds(~7);
KlappeFahrt(KlappeWAkt + 5, 'z'); //Klappe zu mit 4 s Reserve
HPhase(1);
}
else
{
LCD.setLeds(~8);
KlappeFahrt(156 - KlappeWAkt, 'a'); // Klappe auf mit 4s Reserve
HPhase(3);
}
break;
case 'B': // Jede weitere Auswertung blockieren
Folgebefehl='B';
break;
case 'W': // Blockierung aufheben
Folgebefehl='W';
break;
case 'T': // Turbo
Folgebefehl='T';
break;
case 'A':
{
Folgebefehl='A'; // Abbruch Turbo
}
break;
case 'b':
KlappeFahrtD(0); // Klappe Fahrt direkt Pos.0
break;
case 'c':
KlappeFahrtD(5); // Klappe Fahrt direkt Pos.5
break;
case 'd':
KlappeFahrtD(15); // Klappe Fahrt direkt Pos.15
break;
case 'j':
eePromEinzelnWrite(); // EEprom einzelnen Wert schreiben
break;
case 'e':
if (eeAdresse<100) // EEprom Adresse um 1 erhöhen
{
eeAdresse++;
}
BTSerial.print("*e"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(eeAdresse);
BTSerial.print("*");
eePromEinzelnRead(); // EEprom auslesen
BTSerial.print("*d");
BTSerial.print(eeWert); // Gespeicherten Wert ausgeben
BTSerial.print("*");
break;
//----------------------------------------------------------
case 'i': // EEpromadresse um 1 verringern
if (eeAdresse>0)
{
eeAdresse--;
}
BTSerial.print("*e"); // aktuelle EEpromAdresse ausgeben
BTSerial.print(eeAdresse);
BTSerial.print("*");
eePromEinzelnRead(); // EEprom auslesen
BTSerial.print("*d");
BTSerial.print(eeWert); // Gespeicherten Wert ausgeben
BTSerial.print("*");
break;
//----------------------------------------------------------
case 'f':
eeWert++;
BTSerial.print("*d"); // zu speichernder Wert +1
BTSerial.print(eeWert);
BTSerial.print("*");
break;
case 'g':
eeWert--;
BTSerial.print("*d"); // zu speichernder Wert -1
BTSerial.print(eeWert);
BTSerial.print("*");
break;
case 'H':
HPhase(2); // Heizphase 2 einstellen
break;
break;
case 'O': // Reset
resetFunc();
break;
case 'G': // Heizphase 1
HPhase(1);
break;
case 'I': // Heizphase 0
HPhase(0);
break;
case'X': // Heizphase 1
HPhase(1);
eepromWriteInt(eeAd[4],0); // Klappe WAkt =0
KlappeWAkt=150; // speichern
KlappeFahrt(150,'z'); // Klappe 150s zu
break;
case 'Z':
rtc.setTime(ZStunde,ZMinute,ZSekunde); // Setze Zeit 08:44:15 (24hr format)
break;
case '4':
ZStunde++;
Zeitanzeige();
break;
case '5':
ZMinute++;
Zeitanzeige();
break;
case '6':
ZSekunde++;
Zeitanzeige();
break;
case 'Y': // Heizphase 2
HPhase(2);
eepromWriteInt(eeAd[4],0); // Klappe WAkt =0
KlappeWAkt=150; // speichern
KlappeFahrt(150,'z'); // Klappe 150s zu
Folgebefehl='B' ; // Endzeit3 1 std (Blockierung)
break;
default:
break;
}
//********* Timerabfrage *******************
if (Status == 't') //Timer läuft solange Klappe läuft
{
AlteZeit3 = millis(); //Timer3 reset solange klappe fährt
if ((millis() - AlteZeit > EndZeit) || (TimerStop == true))
{ // Wenn Zeit abgelaufen
// oder Timer stop Befehl
TastenCode = 0; // Solange Klappe läuft 2. Code möglich
TimerStop = false;
Serial.print(F("Zeit ist um - Status = "));
Serial.println(Status);
Status = 'p'; //Pause Zeit ist um
LCD.setLeds(~0);
KlappeFahrt(1, 's'); // Klappe Stop
}
// Startöffnung 16s einstellen ------------------------------------------
}
if (Folgebefehl == 'F' && Status == 'p')
{ // Folgebefehl Klappe auf 16s
LCD.setLeds(~13);
Serial.print(F("Folgebefehl F Klappe öffnet 9s"));
KlappeFahrt(KlappeWeit, 'a'); // Startöffnung
TimerStop = false;
TastenCode = 8;
Folgebefehl = 'P';
}
// ----------------------------------------------------------------------
////else if ((KlappeWAkt == 0) && (Status == 'p') && (KlappeOffset > 0) && (RohrTemp > 120) && (Heizphase < 2) && (RaumTemp <= RaumTempZiel) )
//// //else if ((KlappeWAkt == 0) && (Status == 'p') && (KlappeOffset > 0) && (RohrTemp > 120) && (RohrTemp < RohrTempMax)&&(Heizphase<2)&&(RaumTemp<=RaumTempZiel) )
////{
//// LCD.setLeds(~14);
//// RTOffset = KlappeOffset + (RaumTempZiel - RaumTemp); // lässt Klappe weiter offen, wenn Raumtemp nicht erreicht ist
//// KlappeFahrt(RTOffset, 'a'); //Offset, damit Klappe nicht ganz zu geht
////}
// Tastenabfrage fertig
} //Loop Ende
//******************** Funktionen ************
void eePromReadZuweisen() // Fkt. Eepromdaten lesen und an Variablen zuweisen
{
Buzzer=eepromReadInt(eeAd[0]);
RohrTempTief=eepromReadInt(eeAd[1]);
KlappeOffset=eepromReadInt(eeAd[2]);
RohrDiffFakt=eepromReadInt(eeAd[3]);
KlappeWAkt=eepromReadInt(eeAd[4]);
RaumTempZiel=eepromReadInt(eeAd[5]);
Heizphase=eepromReadInt(eeAd[6]);
RaumTempKorr=eepromReadInt(eeAd[7]);
RohrTempFenster=eepromReadInt(eeAd[8]);
RohrGrund=eepromReadInt(eeAd[9]);
EndZeit2=eepromReadInt(eeAd[10]);
KlappeMittOeffnung=eepromReadInt(eeAd[11]);
KlappeWeit=eepromReadInt(eeAd[12]);
}
void eePromEinzelnWrite() // Fkt. Einzelnen EEpromwert schreiben
{
eepromWriteInt(eeAd[eeAdresse],eeWert);
eePromReadZuweisen(); // danach alle Wertw neu lesen und zuweisen
}
void eePromEinzelnRead() // Fkt. Einzelnen EEpromwert in eeWert auslesen
{
eeWert= eepromReadInt(eeAd [eeAdresse]);
}
// Fkt. EEprom Schreiben 2 byte
void eepromWriteInt(int adr, int wert)
{
byte low, high;
low = wert & 0xFF;
high = (wert >> 8) & 0xFF;
//EEPROM.write(adr, low); // dauert 3,3ms
EEPROM.update(adr, low); // schreiben nur bei Wertänderung
delay(50);
//EEPROM.write(adr + 1, high);
EEPROM.update(adr+1, high);
delay(50);
return;
} //Ende eepromWriteInt
//***********************************************
// Fkt. EEprom Lesen 2 byte -- Aufruf Wert=eepromReadInt(Adresse)
int eepromReadInt(int adr) {
byte low, high;
low = EEPROM.read(adr);
high = EEPROM.read(adr + 1);
return low + ((high << 8) & 0xFF00);
} //Ende eepromReadInt
//************************************************
// Fkt. Serielle Daten von Terminal lesen
char getCommand()
{
char c = '\0';
if (BTSerial.available()) // wenn BT-Eingabe
{
c = BTSerial.read(); // dann von BT lesen
}
if (Serial.available()) // wenn Serial-Eingabe
{
c = Serial.read(); // dann Serial lesen
}
return c;
}
//Serielle Daten lesen Ende
//*************************************************
// die Funktion "keyPress" wird ausgeführt sobald ein Tastendruck detektiert wurde
// (externer Interrupt)
void keyPress()
{
keyPressDetected = 1; // bei Tastendruck am Gerät
}
//***** Funktion TimerStart für Fahrt Klappe *********************
void TimerStart(unsigned long z)
{
//TimerStop=true;
EndZeit = z * 1000;
AlteZeit = millis();
Status = 't';
Serial.println(F("Status t -- Timer gestartet"));
}
//*********** KlappeFahr mit direktem Ziel *************************
int KlappeFahrtD(unsigned long p)
{
if (p> KlappeWAkt)
{
pos=p-KlappeWAkt;
KlappeFahrt(pos,'a');
}
else if (p<KlappeWAkt)
{
pos=KlappeWAkt-p;
if (p==0)
{
pos=pos+2;
}
KlappeFahrt(pos,'z');
}
KlappeWAkt=p;
}
//**** Klappe bewegen
int KlappeFahrt(unsigned long z, char r) //z=zeit r= richtung a=auf z=zu s=stop
{
switch (r) {
case 's': //stop
digitalWrite(KlappeZu, 1);
digitalWrite(KlappeAuf, 1);
LCD.setLeds(~0); //Stop alle LED aus
Serial.println(F("Klappe bleibt stehen."));
//Status = 'p';
break;
case 'a': //Auf
digitalWrite(KlappeZu, 1);
digitalWrite(KlappeAuf, 0);
TimerStart(z);
Serial.print(F(" Phase = "));
Serial.print(Phase);
Serial.print(F(" -- Klappe faehrt auf fuer "));
Serial.print(z);
Serial.println(F(" sekunden."));
KlappeWAkt = KlappeWAkt + z;
if (KlappeWAkt >= 150)
{
KlappeWAkt = 150;
}
eepromWriteInt(eeAd[4],KlappeWAkt);
break;
case 'z': //Zu
digitalWrite(KlappeAuf, 1);
digitalWrite(KlappeZu, 0);
TimerStart(z);
Serial.print(F(" Phase = "));
Serial.print(Phase);
Serial.print(F(" -- Klappe faehrt zu fuer "));
Serial.print(z);
Serial.println(F(" sekunden."));
KlappeWAkt = KlappeWAkt - z;
if (KlappeWAkt <= 0)
{
KlappeWAkt = 0;
}
eepromWriteInt(eeAd[4],KlappeWAkt);
break;
default:
break;
}
return KlappeWAkt;
}
// ---------------- Funktion Heizphase einstellen und speichern----
void HPhase(uint8_t h)
{
Heizphase=h;
eepromWriteInt(eeAd[6],h);
}
// Senden eines T elegramms anden PC
void SendString(byte InstrNr, int MWert) {
Serial.print('#');
Serial.print(InstrNr);
Serial.print('M');
Serial.print(MWert);
Serial.print('<');
}
// --------------- Zeitanzeige ----
void Zeitanzeige()
{
BTSerial.print("*Y");
BTSerial.print(ZStunde, DEC);
BTSerial.print(":");
BTSerial.print(ZMinute, DEC);
BTSerial.print(":");
BTSerial.print(ZSekunde, DEC);
BTSerial.print(" Uhr ");
}
// ---------------- Sekundenbefehle ----
void sekundenBefehle()
{
BTSerial.print("*T"); // Auswertezeiz Rest
if (((EndZeit3-(millis()-AlteZeit3))/1000)<30000)
{BTSerial.print((EndZeit3-(millis()-AlteZeit3))/1000);}
else
{BTSerial.print(" 0");}
BTSerial.print("*");
BTSerial.print("*u");
if (((EndZeit-(millis()-AlteZeit))/1000)<5000) // Klappe Restzeit
{BTSerial.print((EndZeit-(millis()-AlteZeit))/1000);}
else
{BTSerial.print(" 0");}
BTSerial.print("*");
//-----------------Zeit auslesen-----------------------------------------------
t=rtc.getTime();
// Send date over serial connection
BTSerial.print("*t");
BTSerial.print(t.date, DEC);
BTSerial.print(". ");
BTSerial.print(rtc.getMonthStr());
BTSerial.print(" ");
BTSerial.print(t.year, DEC);
BTSerial.print(" - ");
// Send Day-of-Week and time
if (t.hour<10)
{BTSerial.print("0");}
BTSerial.print(t.hour, DEC);
BTSerial.print(":");
if (t.min<10)
{BTSerial.print("0");}
BTSerial.print(t.min, DEC);
BTSerial.print(":");
if (t.sec<10)
{BTSerial.print("0");}
BTSerial.print(t.sec, DEC);
BTSerial.print("*");
}
___________________________________________________
ESP Easy Build: 20103 - Mega || GIT version: mega-20190315
ESP Easy Build: 20103 - Mega || GIT version: mega-20190315