Stromüberschuss als Wärme nutzen, P2H

Hier werden die Threads der abgeschlossenen Projekte abgelegt.
Ein schönes Forum zum schmökern.
Antworten
Benutzeravatar
WindFritz
Beiträge: 60
Registriert: 13 Jan 2016, 11:37
Wohnort: A-2120 Wolkersdorf

Stromüberschuss als Wärme nutzen, P2H

Beitrag von WindFritz »

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
Benutzeravatar
WindFritz
Beiträge: 60
Registriert: 13 Jan 2016, 11:37
Wohnort: A-2120 Wolkersdorf

Re: Stromüberschuss als Wärme nutzen, P2H

Beitrag von WindFritz »

Arduino nano Schaltplan V1.3 klein.png
Arduino nano Schaltplan V1.3 klein.png (182.82 KiB) 4128 mal betrachtet
Benutzeravatar
WindFritz
Beiträge: 60
Registriert: 13 Jan 2016, 11:37
Wohnort: A-2120 Wolkersdorf

Re: Stromüberschuss als Wärme nutzen, P2H

Beitrag von WindFritz »

// 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
Benutzeravatar
WindFritz
Beiträge: 60
Registriert: 13 Jan 2016, 11:37
Wohnort: A-2120 Wolkersdorf

Re: Stromüberschuss als Wärme nutzen, P2H

Beitrag von WindFritz »

Ansicht Gehäuse mit LEDs und Schaltern.jpg
Ansicht Gehäuse mit LEDs und Schaltern.jpg (46.31 KiB) 4127 mal betrachtet
Antworten