Mit Anton Brückl habe ich 2017 eine Arduino nano (C/C++) basierte sehr günstige Lösung zur Ansteuerung von el. Kachelöfen oder Boilern zur Nutzung von "PV-Überproduktion" fertiggestellt.
fH
Stromüberschuss als Wärme nutzen, P2H
Re: Stromüberschuss als Wärme nutzen, P2H
// Arduino Uno
// Rumpfprogramm für Kacheofen V1.3
// Erstellt : 12.4.2017
// geändert : 27.4.2017 : Kuchl zusätzlich, Pinbelegung NEU
// geändert : 28.4.2017 : Leistungsdämpfung, Fehlerbehebungen(rote LEDs, Regelung)
// geändert : 30.4.2017 : Fehlerbehebungen, Timerregelung, Gelbe LED PWM
// geändert : 4.5.2017 : formale reihenfolgen
// geändet : 9.5.2017 : Fehlerbehebung. fH
//
// (C) Fritz Herzog und Anton Brückl
//------------------ Definition PINBELEGUNG ---------------------
const byte led_Kuchl_manuell = 4; // LED leuchtet wenn auf manuell
const byte led_Sonne_manuell = 10; // LED leuchtet wenn auf manuell
const byte led_Feuer_manuell = 12; // LED leuchtet wenn auf manuell
const byte led_Kuchl = 2; // LED leuchtet wenn Heizstab Kuchl heizt
const byte led_Sonne = 8; // LED leuchtet wenn Heizstab Sonne heizt
const byte led_Feuer = 9; // LED leuchtet wenn Heizstab Feuer heizt
const byte led_Regelung = 11; // LED leuchtet wenn Regelung aktiv (Überschuss)
// const byte led_MC = 13; // LED microcontroller aktiv (interne LED)
byte Taster_Kuchl = A3; // aktiviert manuell für 4h,15Minuten Heizstab Feuer (1.2 kW)
byte Taster_Sonne = A1; // aktiviert manuell für 4h,15Minuten Heizstab Sonne (1,2 kW)
byte Taster_Feuer = A2; // aktiviert manuell für 4h,15Minuten Heizstab Feuer (1,2 kW)
// HIGH = zuerst SONNE,dann FEUER EIN. LOW = zuerst FEUER,dann SONNE EIN
byte Schalter_Kuchl = A6; // aktiviert Vorrang für Heizstab Kuchl (ca 500 W)
byte Schalter_Sonne = A5; // aktiviert Vorrang für Heizstab Sonne (1,2 kW)
byte Schalter_Feuer = A4; // aktiviert Vorrang für Heizstab Feuer (1,2 kW)
const byte ADC_Eingang = A0; // Stromsignal (4-20mA) Leistung (12mA = 0, 4mA = Überschuss(ins Netz) 15kW, 20mA = Verbrauch(vom Netz) 15kW
// Bürde = 150 Ohm somit Spannung: 0,6 Volt bis 3,0 Volt, Sollspannung = 1,8 Volt (entsprich 0 kW)
// DAC-Schnittstelle
byte Pin_Leistung_Kuchl = 3; // PWM-Pin für Sollleistung
byte Pin_Leistung_Sonne = 5; // PWM-Pin für Sollleistung
byte Pin_Leistung_Feuer = 6; // PWM-Pin für Sollleistung
// RESERVE UART / Anzeige für Datenausgabe
// byte Anzeige_RX = 4; // Daten
// byte Anzeige_TX = 3; // Clock
//------------------ Definition VARIABLEN ---------------------
unsigned int Minuten_Kuchl = 0; // Restzeit Heizstab Kuchl in Minuten, 0= aus 255= 4h und 15 Minuten
unsigned int Minuten_Sonne = 0; // Restzeit Heizstab Sonne in Minuten, 0= aus 255= 4h und 15 Minuten
unsigned int Minuten_Feuer = 0; // Restzeit Heizstab Feuer in Minuten, 0= aus 255= 4h und 15 Minuten
byte T_Kuchl = 0; // Dauer wie lange Taste Kuchl gedrückt ist (zum entprellen)
byte T_Sonne = 0; // Dauer wie lange Taste Sonne gedrückt ist (zum entprellen)
byte T_Feuer = 0; // Dauer wie lange Taste Feuer gedrückt ist (zum entprellen)
boolean Prio_Kuchl; // Priorität der Kuchl (0=false=OFF)
boolean Prio_Sonne; // Priorität der Sonne (0=false=OFF)
boolean Prio_Feuer; // Priorität der Feuer (0=false=OFF)
boolean regelung = true; // nur dann true wenn Überschuss (und keine Restzeiten mehr)
boolean Kuchl_Ein = false; // <>0 wenn eingeschalten
boolean Sonne_Ein = false; // <>0 wenn eingeschalten
boolean Feuer_Ein = false; // <>0 wenn eingeschalten
// Ausgangsgrößen für Pulsweitenmodulation
// nach einigen Sekunden zu erreichende Werte
byte P_soll_Kuchl = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_soll_Sonne = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_soll_Feuer = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
// aktuell angeforderte Werte (gedämpft in Stufen)
byte P_real_Kuchl = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_real_Sonne = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_real_Feuer = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
// PWM-Helligkeit Led Regelung
byte Led_Wert1 = 0; // Helligkeitswert invertiert 0=hell, 255=aus
byte Led_Wert2 = 0; // Helligkeitswert invertiert 0=hell, 255=aus
float Leistung = 0.0; // die Summenleistung (aller Verbraucher und Erzeuger)
int IntLeistung = 0; // integer Version der Leistung
boolean debug = true; // nur true solange wir das programm testen
boolean AufAb; // zur Regelung verwendet (jeweils eine Stufe (s.u.) mehr oder weniger Leistung): AufAb = true bei Auf und false beiAb
int Zeittakt = 0; // 16 bit Taktsignal, 1 Takt= 1/10 Sekunde (mit Überlauf)
unsigned long Zeitpunkt = 0; // Millisekuden seit poweron
//------------------ Definition KONSTANTEN ---------------------
//const byte Dauer = 180; // Anzahl Minuten standard Dauer Heizbetrieb manuell
const byte Dauer = 2; // zum Testen
const byte Pause = 333; // Anzahl ms Pause bei Ledtest
const byte Stufe = 2; // ca. 2 * 4,7W = 9,4 W ( ca. 4,7 pro Stufe bei den 1200W Heizleistung)
const byte OffsetLeistung = 4; // zum genauen Einstellen des Nullpunktes der verfügbren Leistung
//------------------ Definition FUNKTIONEN ---------------------
byte Bereich ( boolean AufAb, byte Wert ) { // Funktion die innerhalb eines Bytes um Stufe hinauf oder hinunterzählt ohne 0 bzw. 255 zu überschreiten
byte x;
if ( AufAb ) { // wir erhöhen um Stufe bis max 255
if ( Wert > (255 - Stufe)) x = 255;
else x = Wert + Stufe;
}
else { // wir reduzieren um Stufe bis min 0
if ( Wert < Stufe) x = 0;
else x = Wert - Stufe;
}
return x;
}
//============================= SETUP =============================
// dieser Bereich wird nur einmal beim Start durchlaufen
void setup()
{ // alle LEDs sind fix verbunden mit +5V und werden auf Masse gezogen zum Leuchten
pinMode(led_Kuchl_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Feuer_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Sonne_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Kuchl, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Sonne, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Feuer, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Regelung, OUTPUT); // LED gelb Regelung aktiv
// 3 Taster, fix verbunden mit GND (Masse) aktivieren die Zeitsteuerung
pinMode(Taster_Kuchl, INPUT); // ein / aus
pinMode(Taster_Sonne, INPUT); // ein / aus
pinMode(Taster_Feuer, INPUT); // ein / aus
// interen Pullups aktivieren (ca. 20kOhm)
digitalWrite(Taster_Kuchl, HIGH);
digitalWrite(Taster_Sonne, HIGH);
digitalWrite(Taster_Feuer, HIGH);
// die Schalter definieren wer Vorrang hat (zuerst aufgeheizt wird)
pinMode(Schalter_Kuchl, INPUT); // ein / aus
pinMode(Schalter_Sonne, INPUT); // ein / aus
pinMode(Schalter_Feuer, INPUT); // ein / aus
// interen Pullups aktivieren (ca. 20kOhm)
digitalWrite(Schalter_Kuchl, HIGH);
digitalWrite(Schalter_Sonne, HIGH);
digitalWrite(Schalter_Feuer, HIGH);
// PWM-Ausgänge
pinMode(Pin_Leistung_Kuchl, OUTPUT); // LED rot
pinMode(Pin_Leistung_Sonne, OUTPUT); // LED rot
pinMode(Pin_Leistung_Feuer, OUTPUT); // LED rot
// ein analoger Eingang für das Signal wieviel Leistug zur Verfügung steht
pinMode(ADC_Eingang, INPUT);
// LED-Test für alle LEDs ca. 1 Sekunde
// ACHTUNG: LOW bedeutet LED leuchtet, HIGH = LED aus
digitalWrite(led_Kuchl, HIGH); // LED aus
digitalWrite(led_Sonne, HIGH); // LED aua
digitalWrite(led_Feuer, HIGH); // LED aus
digitalWrite(led_Kuchl_manuell, HIGH); // LED aus
digitalWrite(led_Sonne_manuell, HIGH); // LED aus
digitalWrite(led_Feuer_manuell, HIGH); // LED aus
digitalWrite(led_Regelung, HIGH); // LED LED aus
delay(500);
// alle LEDs ein
digitalWrite(led_Kuchl, LOW); delay(Pause); // LED ein
digitalWrite(led_Sonne, LOW); delay(Pause); // LED ein
digitalWrite(led_Feuer, LOW); delay(Pause); // LED ein
digitalWrite(led_Kuchl_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Sonne_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Feuer_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Regelung, LOW); delay(Pause); // LED ein
delay(500);
// alle LEDs aus
digitalWrite(led_Kuchl, HIGH); delay(Pause); // LED aus
digitalWrite(led_Sonne, HIGH); delay(Pause); // LED aus
digitalWrite(led_Feuer, HIGH); delay(Pause); // LED aus
digitalWrite(led_Kuchl_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Sonne_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Feuer_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Regelung, HIGH); delay(Pause); // LED aus
Serial.begin(9600); // initialize serial interface for print()
// Ausgabe Leistungssollwerte
analogWrite(Pin_Leistung_Kuchl, 0);
analogWrite(Pin_Leistung_Sonne, 0);
analogWrite(Pin_Leistung_Feuer, 0);
Zeitpunkt=millis(); // Startzeit merken
Zeittakt = 0;
}
//============================= LOOP =============================
// dieser Bereich wird laufend durchlaufen (unten angekommen wird wieder oben begonnen)
void loop() // ein Durchlauf soll ca. 10ms dauern
{
// TASTEN
// prüfe ob Tasten gedrückt sind, wenn ja Zähler erhöhen, sonst vermindern (entprellen)
if (analogRead(Taster_Kuchl) < 500) T_Kuchl ++;
else T_Kuchl --;
if (T_Kuchl > 200) T_Kuchl = 0;
if (T_Kuchl > 33) T_Kuchl = 33;
if (analogRead(Taster_Sonne) < 500) T_Sonne ++;
else T_Sonne --;
if (T_Sonne > 200) T_Sonne = 0;
if (T_Sonne > 33) T_Sonne = 33;
if (analogRead(Taster_Feuer) < 500) T_Feuer ++;
else T_Feuer --;
if (T_Feuer > 200) T_Feuer = 0;
if (T_Feuer > 33) T_Feuer = 33;
if (debug) {
// Serial.print(T_Feuer);
// Serial.print("/ ");
}
// wenn Schwelle (5) überschritten, dann ist die Taste gedrückt und Minuten_HIGH wird angepasst
if (T_Kuchl > 5) {
T_Kuchl = 0;
if (Minuten_Kuchl == 0) Minuten_Kuchl = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Kuchl = 0; }
if (T_Sonne > 5) {
T_Sonne = 0;
if (Minuten_Sonne == 0) Minuten_Sonne = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Sonne = 0; }
if (T_Feuer > 5) {
T_Feuer = 0;
if (Minuten_Feuer == 0) Minuten_Feuer = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Feuer = 0; }
if (debug) {
// Serial.print(Minuten_Feuer);
//Serial.print(" - ");
}
// Schalter auslesen und in Variablen ablegen Schalter werden nicht entprellt
// Prio_max = 0;
Prio_Kuchl = (analogRead(Schalter_Kuchl) < 500);
Prio_Sonne = (analogRead(Schalter_Sonne) < 500);
Prio_Feuer = (analogRead(Schalter_Feuer) < 500);
//if (debug) { Serial.print(" Schalter: "); Serial.print(Prio_Kuchl); Serial.print(Prio_Sonne); Serial.print(Prio_Feuer); Serial.print(analogRead(Schalter_Kuchl));}
// LEDs manuell ( 3 x grün )
if (Minuten_Kuchl == 0) digitalWrite(led_Kuchl_manuell, HIGH);
else digitalWrite(led_Kuchl_manuell, LOW);
if (Minuten_Sonne == 0) digitalWrite(led_Sonne_manuell, HIGH);
else digitalWrite(led_Sonne_manuell, LOW);
if (Minuten_Feuer == 0) digitalWrite(led_Feuer_manuell, HIGH);
else digitalWrite(led_Feuer_manuell, LOW);
// Verfügbare Leistung ermitteln
// Stromsignal (4-20mA) Leistung (12mA = 0(austariert), 4mA = Überschuss(ins Netz) 15kW, 20mA = Verbrauch(vom Netz) 15kW )
// Bürde = 150 Ohm somit Spannung: 0,6 Volt bis 3,0 Volt, Sollspannung = 1,8 Volt (entsprich 0 kW)
IntLeistung = analogRead(ADC_Eingang); // Einlesen 10 bit ADC-Wert
if (debug) { Serial.print(" IntP="); Serial.print(IntLeistung); }
// (1,8 Volt = 368 (entsprich 0 kW), (0,6V = 123 = 15kW Überschuss) , (3,0 Volt = 614 = Verbrauch 15kW)
// 245 = 15kW, 1 = 61W, Bsp: 3kW Überschuss = 319
Leistung = ( 368.0 - IntLeistung - OffsetLeistung) * 61; // Leistung in Watt (1,8V entsprich ausbalanziert = 368 von 1023)
if (debug) { Serial.print(" Leistung(verfügbar)="); Serial.print(Leistung); }
regelung = ( ( Minuten_Kuchl == 0) && ( Minuten_Sonne == 0 ) && ( Minuten_Feuer == 0 ) );
// Zeitsteuerung oder Regelung
if (regelung) { // je nach Priorität die Heizkreise ansteuern(1,8V entsprich ausbalanziert = 368 von 1023)
AufAb = ( Leistung > 120 ); // etwas Reserve lassen (1-2 * 61 W)
if (Prio_Kuchl) P_soll_Kuchl = Bereich(AufAb, P_soll_Kuchl); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Kuchl = 0; // auf 0 fahren
if (Prio_Sonne) P_soll_Sonne = Bereich(AufAb, P_soll_Sonne); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Sonne = 0; // auf 0 fahren
if (Prio_Feuer) P_soll_Feuer = Bereich(AufAb, P_soll_Feuer); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Feuer = 0; // auf 0 fahren
// Led Regelung (gelb) Ansteuerung: Led abwechselnd 1s 100% und 1s Helligkeit je nach Leistung
// Led wird gegen Masse geschalten deshalb: 255=Led aus, 0=5000W oder mehr Leistung verfügbar
Led_Wert2 = 255 - (Leistung / 20); // Je mehr Leistug verfügbar umso heller die LED
if (Leistung > 5100) Led_Wert2 = 0; // wenn Überlauf bei byte weil über 5100 Watt verfügbar, dann trotzdem auf hell
if (Leistung < 0 ) Led_Wert2 = 255; // wenn keine Leistung verfügbar, dann LED aus
//if (debug) { Serial.print(" LedWert2: "); Serial.print(Led_Wert2); }
if ( bitRead(Zeittakt, 3) == 0 ) // 4. bit wechselt alle 8 Takte,
{
if (Leistung < 0) Led_Wert1 = 255; // led ist AUS wenn keine Leistung verfügbar, ansonsten EIN
else Led_Wert1 = 0;
analogWrite(led_Regelung, Led_Wert1); // 4. bit wechselt alle 8 Takte, LED leuchtet voll
}
else analogWrite(led_Regelung, Led_Wert2) ; // LED leuchtet je nch verfügbarer Leistung
}
else { // Zeitsteuerung
// wenn manuelle Zeitvorgabe != 0 dann voll heizen
if (Minuten_Kuchl == 0 ) P_soll_Kuchl = 0;
else P_soll_Kuchl = 255;
if (Minuten_Sonne == 0 ) P_soll_Sonne = 0;
else P_soll_Sonne = 255;
if (Minuten_Feuer == 0 ) P_soll_Feuer = 0;
else P_soll_Feuer = 255;
}
// hinauszuschreibende Werte an Sollwerte anpassen und hinausschreiben
// Leistung steigern oder reduzieren (je nachdem ob soll > real oder umgekehrt)
P_real_Kuchl = Bereich((P_soll_Kuchl > P_real_Kuchl), P_real_Kuchl);
analogWrite(Pin_Leistung_Kuchl, P_real_Kuchl); // Wert hinausschreiben
P_real_Sonne = Bereich((P_soll_Sonne > P_real_Sonne), P_real_Sonne);
analogWrite(Pin_Leistung_Sonne, P_real_Sonne); // Wert hinausschreiben
P_real_Feuer = Bereich((P_soll_Feuer > P_real_Feuer), P_real_Feuer );
analogWrite(Pin_Leistung_Feuer, P_real_Feuer); // Wert hinausschreiben
// LEDs Heizung
Kuchl_Ein = ( P_real_Kuchl != 0);
Sonne_Ein = ( P_real_Sonne != 0);
Feuer_Ein = ( P_real_Feuer != 0);
// Anzeige LEDs Heizstäbe
digitalWrite(led_Kuchl, !Kuchl_Ein);
digitalWrite(led_Sonne, !Sonne_Ein);
digitalWrite(led_Feuer, !Feuer_Ein);
if (debug) {
Serial.print(" K:");
Serial.print(P_real_Kuchl);
Serial.print(" S:");
Serial.print(P_real_Sonne); }
Serial.print(" F:");
Serial.println(P_real_Feuer);
// schau ob schon 100ms vergangen sind
if (( millis()- Zeitpunkt)>99) {
Zeittakt++;
if (Zeittakt>59) {
Zeittakt=0;
// 600x100ms = 1 Minute ist erreicht, deshalb Zeit herabzählen
if (Minuten_Kuchl != 0) Minuten_Kuchl --;
if (Minuten_Sonne != 0) Minuten_Sonne --;
if (Minuten_Feuer != 0) Minuten_Feuer --;
}
Zeitpunkt = millis();
}
// Pause
delay(250); // 1/4s Zyklus
}
// -------------------ENDE
// Rumpfprogramm für Kacheofen V1.3
// Erstellt : 12.4.2017
// geändert : 27.4.2017 : Kuchl zusätzlich, Pinbelegung NEU
// geändert : 28.4.2017 : Leistungsdämpfung, Fehlerbehebungen(rote LEDs, Regelung)
// geändert : 30.4.2017 : Fehlerbehebungen, Timerregelung, Gelbe LED PWM
// geändert : 4.5.2017 : formale reihenfolgen
// geändet : 9.5.2017 : Fehlerbehebung. fH
//
// (C) Fritz Herzog und Anton Brückl
//------------------ Definition PINBELEGUNG ---------------------
const byte led_Kuchl_manuell = 4; // LED leuchtet wenn auf manuell
const byte led_Sonne_manuell = 10; // LED leuchtet wenn auf manuell
const byte led_Feuer_manuell = 12; // LED leuchtet wenn auf manuell
const byte led_Kuchl = 2; // LED leuchtet wenn Heizstab Kuchl heizt
const byte led_Sonne = 8; // LED leuchtet wenn Heizstab Sonne heizt
const byte led_Feuer = 9; // LED leuchtet wenn Heizstab Feuer heizt
const byte led_Regelung = 11; // LED leuchtet wenn Regelung aktiv (Überschuss)
// const byte led_MC = 13; // LED microcontroller aktiv (interne LED)
byte Taster_Kuchl = A3; // aktiviert manuell für 4h,15Minuten Heizstab Feuer (1.2 kW)
byte Taster_Sonne = A1; // aktiviert manuell für 4h,15Minuten Heizstab Sonne (1,2 kW)
byte Taster_Feuer = A2; // aktiviert manuell für 4h,15Minuten Heizstab Feuer (1,2 kW)
// HIGH = zuerst SONNE,dann FEUER EIN. LOW = zuerst FEUER,dann SONNE EIN
byte Schalter_Kuchl = A6; // aktiviert Vorrang für Heizstab Kuchl (ca 500 W)
byte Schalter_Sonne = A5; // aktiviert Vorrang für Heizstab Sonne (1,2 kW)
byte Schalter_Feuer = A4; // aktiviert Vorrang für Heizstab Feuer (1,2 kW)
const byte ADC_Eingang = A0; // Stromsignal (4-20mA) Leistung (12mA = 0, 4mA = Überschuss(ins Netz) 15kW, 20mA = Verbrauch(vom Netz) 15kW
// Bürde = 150 Ohm somit Spannung: 0,6 Volt bis 3,0 Volt, Sollspannung = 1,8 Volt (entsprich 0 kW)
// DAC-Schnittstelle
byte Pin_Leistung_Kuchl = 3; // PWM-Pin für Sollleistung
byte Pin_Leistung_Sonne = 5; // PWM-Pin für Sollleistung
byte Pin_Leistung_Feuer = 6; // PWM-Pin für Sollleistung
// RESERVE UART / Anzeige für Datenausgabe
// byte Anzeige_RX = 4; // Daten
// byte Anzeige_TX = 3; // Clock
//------------------ Definition VARIABLEN ---------------------
unsigned int Minuten_Kuchl = 0; // Restzeit Heizstab Kuchl in Minuten, 0= aus 255= 4h und 15 Minuten
unsigned int Minuten_Sonne = 0; // Restzeit Heizstab Sonne in Minuten, 0= aus 255= 4h und 15 Minuten
unsigned int Minuten_Feuer = 0; // Restzeit Heizstab Feuer in Minuten, 0= aus 255= 4h und 15 Minuten
byte T_Kuchl = 0; // Dauer wie lange Taste Kuchl gedrückt ist (zum entprellen)
byte T_Sonne = 0; // Dauer wie lange Taste Sonne gedrückt ist (zum entprellen)
byte T_Feuer = 0; // Dauer wie lange Taste Feuer gedrückt ist (zum entprellen)
boolean Prio_Kuchl; // Priorität der Kuchl (0=false=OFF)
boolean Prio_Sonne; // Priorität der Sonne (0=false=OFF)
boolean Prio_Feuer; // Priorität der Feuer (0=false=OFF)
boolean regelung = true; // nur dann true wenn Überschuss (und keine Restzeiten mehr)
boolean Kuchl_Ein = false; // <>0 wenn eingeschalten
boolean Sonne_Ein = false; // <>0 wenn eingeschalten
boolean Feuer_Ein = false; // <>0 wenn eingeschalten
// Ausgangsgrößen für Pulsweitenmodulation
// nach einigen Sekunden zu erreichende Werte
byte P_soll_Kuchl = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_soll_Sonne = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_soll_Feuer = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
// aktuell angeforderte Werte (gedämpft in Stufen)
byte P_real_Kuchl = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_real_Sonne = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
byte P_real_Feuer = 0; // PWM-Wert: 0 = 0% = 0kW, 255 = 100% = 1,2 kW (Maximum = 5V, Minimum = 0V)
// PWM-Helligkeit Led Regelung
byte Led_Wert1 = 0; // Helligkeitswert invertiert 0=hell, 255=aus
byte Led_Wert2 = 0; // Helligkeitswert invertiert 0=hell, 255=aus
float Leistung = 0.0; // die Summenleistung (aller Verbraucher und Erzeuger)
int IntLeistung = 0; // integer Version der Leistung
boolean debug = true; // nur true solange wir das programm testen
boolean AufAb; // zur Regelung verwendet (jeweils eine Stufe (s.u.) mehr oder weniger Leistung): AufAb = true bei Auf und false beiAb
int Zeittakt = 0; // 16 bit Taktsignal, 1 Takt= 1/10 Sekunde (mit Überlauf)
unsigned long Zeitpunkt = 0; // Millisekuden seit poweron
//------------------ Definition KONSTANTEN ---------------------
//const byte Dauer = 180; // Anzahl Minuten standard Dauer Heizbetrieb manuell
const byte Dauer = 2; // zum Testen
const byte Pause = 333; // Anzahl ms Pause bei Ledtest
const byte Stufe = 2; // ca. 2 * 4,7W = 9,4 W ( ca. 4,7 pro Stufe bei den 1200W Heizleistung)
const byte OffsetLeistung = 4; // zum genauen Einstellen des Nullpunktes der verfügbren Leistung
//------------------ Definition FUNKTIONEN ---------------------
byte Bereich ( boolean AufAb, byte Wert ) { // Funktion die innerhalb eines Bytes um Stufe hinauf oder hinunterzählt ohne 0 bzw. 255 zu überschreiten
byte x;
if ( AufAb ) { // wir erhöhen um Stufe bis max 255
if ( Wert > (255 - Stufe)) x = 255;
else x = Wert + Stufe;
}
else { // wir reduzieren um Stufe bis min 0
if ( Wert < Stufe) x = 0;
else x = Wert - Stufe;
}
return x;
}
//============================= SETUP =============================
// dieser Bereich wird nur einmal beim Start durchlaufen
void setup()
{ // alle LEDs sind fix verbunden mit +5V und werden auf Masse gezogen zum Leuchten
pinMode(led_Kuchl_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Feuer_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Sonne_manuell, OUTPUT); // LED grün Zeit läuft
pinMode(led_Kuchl, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Sonne, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Feuer, OUTPUT); // LED rot Heizung aktiv
pinMode(led_Regelung, OUTPUT); // LED gelb Regelung aktiv
// 3 Taster, fix verbunden mit GND (Masse) aktivieren die Zeitsteuerung
pinMode(Taster_Kuchl, INPUT); // ein / aus
pinMode(Taster_Sonne, INPUT); // ein / aus
pinMode(Taster_Feuer, INPUT); // ein / aus
// interen Pullups aktivieren (ca. 20kOhm)
digitalWrite(Taster_Kuchl, HIGH);
digitalWrite(Taster_Sonne, HIGH);
digitalWrite(Taster_Feuer, HIGH);
// die Schalter definieren wer Vorrang hat (zuerst aufgeheizt wird)
pinMode(Schalter_Kuchl, INPUT); // ein / aus
pinMode(Schalter_Sonne, INPUT); // ein / aus
pinMode(Schalter_Feuer, INPUT); // ein / aus
// interen Pullups aktivieren (ca. 20kOhm)
digitalWrite(Schalter_Kuchl, HIGH);
digitalWrite(Schalter_Sonne, HIGH);
digitalWrite(Schalter_Feuer, HIGH);
// PWM-Ausgänge
pinMode(Pin_Leistung_Kuchl, OUTPUT); // LED rot
pinMode(Pin_Leistung_Sonne, OUTPUT); // LED rot
pinMode(Pin_Leistung_Feuer, OUTPUT); // LED rot
// ein analoger Eingang für das Signal wieviel Leistug zur Verfügung steht
pinMode(ADC_Eingang, INPUT);
// LED-Test für alle LEDs ca. 1 Sekunde
// ACHTUNG: LOW bedeutet LED leuchtet, HIGH = LED aus
digitalWrite(led_Kuchl, HIGH); // LED aus
digitalWrite(led_Sonne, HIGH); // LED aua
digitalWrite(led_Feuer, HIGH); // LED aus
digitalWrite(led_Kuchl_manuell, HIGH); // LED aus
digitalWrite(led_Sonne_manuell, HIGH); // LED aus
digitalWrite(led_Feuer_manuell, HIGH); // LED aus
digitalWrite(led_Regelung, HIGH); // LED LED aus
delay(500);
// alle LEDs ein
digitalWrite(led_Kuchl, LOW); delay(Pause); // LED ein
digitalWrite(led_Sonne, LOW); delay(Pause); // LED ein
digitalWrite(led_Feuer, LOW); delay(Pause); // LED ein
digitalWrite(led_Kuchl_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Sonne_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Feuer_manuell, LOW); delay(Pause); // LED ein
digitalWrite(led_Regelung, LOW); delay(Pause); // LED ein
delay(500);
// alle LEDs aus
digitalWrite(led_Kuchl, HIGH); delay(Pause); // LED aus
digitalWrite(led_Sonne, HIGH); delay(Pause); // LED aus
digitalWrite(led_Feuer, HIGH); delay(Pause); // LED aus
digitalWrite(led_Kuchl_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Sonne_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Feuer_manuell, HIGH); delay(Pause); // LED aus
digitalWrite(led_Regelung, HIGH); delay(Pause); // LED aus
Serial.begin(9600); // initialize serial interface for print()
// Ausgabe Leistungssollwerte
analogWrite(Pin_Leistung_Kuchl, 0);
analogWrite(Pin_Leistung_Sonne, 0);
analogWrite(Pin_Leistung_Feuer, 0);
Zeitpunkt=millis(); // Startzeit merken
Zeittakt = 0;
}
//============================= LOOP =============================
// dieser Bereich wird laufend durchlaufen (unten angekommen wird wieder oben begonnen)
void loop() // ein Durchlauf soll ca. 10ms dauern
{
// TASTEN
// prüfe ob Tasten gedrückt sind, wenn ja Zähler erhöhen, sonst vermindern (entprellen)
if (analogRead(Taster_Kuchl) < 500) T_Kuchl ++;
else T_Kuchl --;
if (T_Kuchl > 200) T_Kuchl = 0;
if (T_Kuchl > 33) T_Kuchl = 33;
if (analogRead(Taster_Sonne) < 500) T_Sonne ++;
else T_Sonne --;
if (T_Sonne > 200) T_Sonne = 0;
if (T_Sonne > 33) T_Sonne = 33;
if (analogRead(Taster_Feuer) < 500) T_Feuer ++;
else T_Feuer --;
if (T_Feuer > 200) T_Feuer = 0;
if (T_Feuer > 33) T_Feuer = 33;
if (debug) {
// Serial.print(T_Feuer);
// Serial.print("/ ");
}
// wenn Schwelle (5) überschritten, dann ist die Taste gedrückt und Minuten_HIGH wird angepasst
if (T_Kuchl > 5) {
T_Kuchl = 0;
if (Minuten_Kuchl == 0) Minuten_Kuchl = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Kuchl = 0; }
if (T_Sonne > 5) {
T_Sonne = 0;
if (Minuten_Sonne == 0) Minuten_Sonne = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Sonne = 0; }
if (T_Feuer > 5) {
T_Feuer = 0;
if (Minuten_Feuer == 0) Minuten_Feuer = Dauer; // (180 Minuten = 3 Stunden)
else Minuten_Feuer = 0; }
if (debug) {
// Serial.print(Minuten_Feuer);
//Serial.print(" - ");
}
// Schalter auslesen und in Variablen ablegen Schalter werden nicht entprellt
// Prio_max = 0;
Prio_Kuchl = (analogRead(Schalter_Kuchl) < 500);
Prio_Sonne = (analogRead(Schalter_Sonne) < 500);
Prio_Feuer = (analogRead(Schalter_Feuer) < 500);
//if (debug) { Serial.print(" Schalter: "); Serial.print(Prio_Kuchl); Serial.print(Prio_Sonne); Serial.print(Prio_Feuer); Serial.print(analogRead(Schalter_Kuchl));}
// LEDs manuell ( 3 x grün )
if (Minuten_Kuchl == 0) digitalWrite(led_Kuchl_manuell, HIGH);
else digitalWrite(led_Kuchl_manuell, LOW);
if (Minuten_Sonne == 0) digitalWrite(led_Sonne_manuell, HIGH);
else digitalWrite(led_Sonne_manuell, LOW);
if (Minuten_Feuer == 0) digitalWrite(led_Feuer_manuell, HIGH);
else digitalWrite(led_Feuer_manuell, LOW);
// Verfügbare Leistung ermitteln
// Stromsignal (4-20mA) Leistung (12mA = 0(austariert), 4mA = Überschuss(ins Netz) 15kW, 20mA = Verbrauch(vom Netz) 15kW )
// Bürde = 150 Ohm somit Spannung: 0,6 Volt bis 3,0 Volt, Sollspannung = 1,8 Volt (entsprich 0 kW)
IntLeistung = analogRead(ADC_Eingang); // Einlesen 10 bit ADC-Wert
if (debug) { Serial.print(" IntP="); Serial.print(IntLeistung); }
// (1,8 Volt = 368 (entsprich 0 kW), (0,6V = 123 = 15kW Überschuss) , (3,0 Volt = 614 = Verbrauch 15kW)
// 245 = 15kW, 1 = 61W, Bsp: 3kW Überschuss = 319
Leistung = ( 368.0 - IntLeistung - OffsetLeistung) * 61; // Leistung in Watt (1,8V entsprich ausbalanziert = 368 von 1023)
if (debug) { Serial.print(" Leistung(verfügbar)="); Serial.print(Leistung); }
regelung = ( ( Minuten_Kuchl == 0) && ( Minuten_Sonne == 0 ) && ( Minuten_Feuer == 0 ) );
// Zeitsteuerung oder Regelung
if (regelung) { // je nach Priorität die Heizkreise ansteuern(1,8V entsprich ausbalanziert = 368 von 1023)
AufAb = ( Leistung > 120 ); // etwas Reserve lassen (1-2 * 61 W)
if (Prio_Kuchl) P_soll_Kuchl = Bereich(AufAb, P_soll_Kuchl); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Kuchl = 0; // auf 0 fahren
if (Prio_Sonne) P_soll_Sonne = Bereich(AufAb, P_soll_Sonne); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Sonne = 0; // auf 0 fahren
if (Prio_Feuer) P_soll_Feuer = Bereich(AufAb, P_soll_Feuer); // um eine Stufe (ca. 4,3% von P_max pro 0,1s) ändern
else P_soll_Feuer = 0; // auf 0 fahren
// Led Regelung (gelb) Ansteuerung: Led abwechselnd 1s 100% und 1s Helligkeit je nach Leistung
// Led wird gegen Masse geschalten deshalb: 255=Led aus, 0=5000W oder mehr Leistung verfügbar
Led_Wert2 = 255 - (Leistung / 20); // Je mehr Leistug verfügbar umso heller die LED
if (Leistung > 5100) Led_Wert2 = 0; // wenn Überlauf bei byte weil über 5100 Watt verfügbar, dann trotzdem auf hell
if (Leistung < 0 ) Led_Wert2 = 255; // wenn keine Leistung verfügbar, dann LED aus
//if (debug) { Serial.print(" LedWert2: "); Serial.print(Led_Wert2); }
if ( bitRead(Zeittakt, 3) == 0 ) // 4. bit wechselt alle 8 Takte,
{
if (Leistung < 0) Led_Wert1 = 255; // led ist AUS wenn keine Leistung verfügbar, ansonsten EIN
else Led_Wert1 = 0;
analogWrite(led_Regelung, Led_Wert1); // 4. bit wechselt alle 8 Takte, LED leuchtet voll
}
else analogWrite(led_Regelung, Led_Wert2) ; // LED leuchtet je nch verfügbarer Leistung
}
else { // Zeitsteuerung
// wenn manuelle Zeitvorgabe != 0 dann voll heizen
if (Minuten_Kuchl == 0 ) P_soll_Kuchl = 0;
else P_soll_Kuchl = 255;
if (Minuten_Sonne == 0 ) P_soll_Sonne = 0;
else P_soll_Sonne = 255;
if (Minuten_Feuer == 0 ) P_soll_Feuer = 0;
else P_soll_Feuer = 255;
}
// hinauszuschreibende Werte an Sollwerte anpassen und hinausschreiben
// Leistung steigern oder reduzieren (je nachdem ob soll > real oder umgekehrt)
P_real_Kuchl = Bereich((P_soll_Kuchl > P_real_Kuchl), P_real_Kuchl);
analogWrite(Pin_Leistung_Kuchl, P_real_Kuchl); // Wert hinausschreiben
P_real_Sonne = Bereich((P_soll_Sonne > P_real_Sonne), P_real_Sonne);
analogWrite(Pin_Leistung_Sonne, P_real_Sonne); // Wert hinausschreiben
P_real_Feuer = Bereich((P_soll_Feuer > P_real_Feuer), P_real_Feuer );
analogWrite(Pin_Leistung_Feuer, P_real_Feuer); // Wert hinausschreiben
// LEDs Heizung
Kuchl_Ein = ( P_real_Kuchl != 0);
Sonne_Ein = ( P_real_Sonne != 0);
Feuer_Ein = ( P_real_Feuer != 0);
// Anzeige LEDs Heizstäbe
digitalWrite(led_Kuchl, !Kuchl_Ein);
digitalWrite(led_Sonne, !Sonne_Ein);
digitalWrite(led_Feuer, !Feuer_Ein);
if (debug) {
Serial.print(" K:");
Serial.print(P_real_Kuchl);
Serial.print(" S:");
Serial.print(P_real_Sonne); }
Serial.print(" F:");
Serial.println(P_real_Feuer);
// schau ob schon 100ms vergangen sind
if (( millis()- Zeitpunkt)>99) {
Zeittakt++;
if (Zeittakt>59) {
Zeittakt=0;
// 600x100ms = 1 Minute ist erreicht, deshalb Zeit herabzählen
if (Minuten_Kuchl != 0) Minuten_Kuchl --;
if (Minuten_Sonne != 0) Minuten_Sonne --;
if (Minuten_Feuer != 0) Minuten_Feuer --;
}
Zeitpunkt = millis();
}
// Pause
delay(250); // 1/4s Zyklus
}
// -------------------ENDE