Guten Tag
Mein Name Udo , bin noch recht neu hier im Forum
und möchte über mein neues Projekt schreiben.
"Röhren-Kollektor-Beschattungs-Projekt"
? Wer braucht denn sowas und warum ?
Vor 21 Jahren wurde ein Zweifamilienhaus für 6 Personen
mit Fußbodenheizung und Solarer Thermieunterstützung geplant.
Der Betrieb in den vergangen Jahren zeigte, daß sich der Mehraufwand
bei der Installation bezahlt hat.
Nur hat zu Beginn keiner mit unserem nun spührbaren Umweltveränderungen
gerechnet .
Es wurden 3 x Paradigma CPC20 Röhren Kolletoren verbaut,
welche in meinem Fall, (PLZ88271) das gesamte Haus von April bis
in den späten Oktober ausschließlich mit "Solarwärme" mit Warmwasser
und zeitweise mit Heizung versorgt.
Die 2 Enkel-Kinder ( ein maßgeblicher Warmwasser Verbraucher)
sind flüge und ausgeflogen, das heißt weniger Warmwasserverbrauch
plus seigende Sommertemperaturen treiben die Thermianlage in die Stagnation.
Das ist absolut nicht gut und schädigt die Anlagenstruktur.
Das ist also der Grund des Projekts das diesen Sommer bereits
seine Funktion bewiesen hat.
Das ganze aber mit manueller Bedienung.
Die Hälfte der Röhren-Kollektoren werden mit einer quasi Markise beschattet
und verhindern die Stagnation der "Thermie - Solar -Anlage".
Stagnation ==> die gesammte Transportflüssigkeit ( Kühlmittel) wird in den
Ausgleichsbehälter im Keller gedrückt und bei abkühlen entstehen Gasblasen
im System . Passiert das öfter findet auf Grund der Gasblasen kein Umwälzung
mehr statt und das Sytem ist ausgefallen.
Soweit die Vorgeschichte; Hoffe ist nicht zu lang ausgefallen .
Vor geraumer Zeit bin ich durch ein Youtube video
"Wie geht die Scripting-Funktion der neuen Shelly PRO
und Shelly PLUS und was kann man damit machen?";
auf die Möglichkeit gestossen meine sehr geringen Erfahrungen
mit Shelly-Produkten zu erweitern.
So bin ich dann auch, auf dieses sehr interessante und gute
Forum gestossen.
Bisher habe ich den Shelly 2.5 als "switch ( Beleuchtung) & auch als cover"
an einer Markise eingesetzt. Die Anlagen laufen problemlos seit ca 2 Jahren.
Die Markisensteuerung unter Anwendung des Shelly 2PM brachten mich
bei meinem " Röhren-Kollektor-Beschattungs-Projekt " auf die Idee,
die deutlich anspruchsvollere Steuerung der Anlage damit duchzuführen.
In der Zwischenzeit wurde das ADD-ON für den 2PM eingeführt und so
erübrigte das den Einsatz eines Arduino für die Meßwerterfassung.
Das Pflichtenheft:
1. Keine Beschattung bei: T-Sensor Temp <= 25 Grad
2. Volle Beschattung bei: T-Sensor Temp >= 75 Grad
3. Entfernen der Beschattung : wenn Spannung >= 4 V = & > 4 Bf Wind
am Schelly Add-On Spannungeingang anliegen
===> zu viel Wind ( Messung mit Flügelrad )
4. Beschattung nicht notwendig wenn Uhrzeit >= 18:00
( Abends ist zu wenig Strahlung am Kollektor
5. Anlage in den Winterschlaf legen (Okt. Bis Mai.) manuel per Netzschalter
Meine Programmierkenntnisse sind sehr rudimentär in C , Basic & Arduino
und so nahm ich mir Zeit die Grundlagen für Java Script zu studieren
und die Zahlreichen Muster-Scripts in diesem Forum zu analysieren.
Mit reinem copy & paste ist man in dieser Sache aber sehr schnell am
Ende und die Reihe der Error's wird immer länger.
In diesem Fall hilft nur Beharrlichkeit und so blieb ich meinem
Wahlspruch treu !!! " Geht nicht gibts nicht "
Die Hardware:
1 Stck. Markise 3,5m x 1,6m Rohrmotor mit Endschaltern justierbar
1 Stck Shelly ADD-ON
1 Stck Shelly 2PM
1 Stück Steckernetzteil 220AC/12v 1A DC Schaltnetzteil
(Spannungsversorgung des Flügelrads)
1 Stck Flügelrad (https://de.aliexpress.com/item/1005005500304078.html)
hier die 0-10V Version verwenden
1 Stck Temeratursensor DS18b20
Herausgekommen ist dabei ein scetch der für meine Ansprüche funktioniert!
Echte Programmierer werde sagen das geht besser ( ich kann es nicht )
Für all diejenigen die etwas ähnliches brauchen können hier ohne Gewähr
und nur für den eigenen Bedarf !!!
der Code.
Der Name: Rollo_Temp_Wind_Time
/*
Versuch die Beschattung der Roehren-Kollecktoren per Script zu steuern. Rev 3.0 UB
Das läuft soweit seit 6.11.2023
In der Config:
temp_min = minimale Innentemperatur(z.B. meine 35°C)
id_inside = Id des Innentemperaturfühlers (Solar_Kollektor_Ruecklauf_Temp)
rollo == auf 100% (voll abgedeckt) ; auf 0% ( voll eingefahren)
interval = Messen, Auswerten und Schalten alle z.B 10 Sekunden
Für unteren code:
1a. roller/0?go= 4% bei inside-Temp <= 25 Grad // das waren Werte zu testen
2a. roller/0?go=90% bei outside-Temp >= 45 Grad
3. roller/0?go= 4% wenn Spannung >= 4 V am Schelly Add-On Spannungeingang anliegen ===> zu viel Wind ( Messung mit Flügelrad )
4. roller/0?go= 0% wenn Uhrzeit >= 18:00 ( Abends ist zu wenig Strahlung am Kollektor
*/
function TsKonverter(ts, timeZone, yOff) {
let a =[ts,timeZone,yOff],k =true,b =86400,d =0,e =0,f =0,g =0,h =0,j =[31,28,31,30,31,30,31,31,30,31,30,31];
function fa(va,vb,vg,vd){return va +Math.floor((vb -vg) /vd);}
function fb(ve,vf,vg){for (let y =ve; y <vf; y++){if ((y %4 === 0 && y %100 !== 0) y %400 === 0)vg +=1;}return vg;}
if (typeof(a[2]) === 'undefined')a[2] =1970;
for (let i in a){let t =typeof(a[i]); if (t === 'undefined' (t !== 'number' && t !== 'bigint')){print("Error_TsKonverter, Input",i, " wrong Datatype: ",t); a[i] =0; k =false;}}
g =Math.floor(a[0] /b); f =fa(a[2],g,0,366); d =fb(a[2],f,0); f =fa(a[2],g,d,365); d =fb(a[2],f,0); f =fa(a[2],g,d,365);
if ((f %4 === 0 && f %100 !== 0) f %400 === 0)j[1] =29;
h =(g -d) %365;
for (let i =0; i <j.length; i++){if (h >j[i]){h -=j[i];}else {e =i +1; if (a[2] === 0) e -=1; break;}}
if (a[2] >0)h +=1;
let values ={aa:h,ab:e,ac:f,ad:Math.floor((a[0] %b) /3600) +a[1],ae:Math.floor((a[0] %3600) /60),af:Math.floor(a[0] %60)};
if (values.ad === 24){values.aa +=1; values.ad =0;}
let number ={Tag:values.aa,Monat:values.ab,Jahr:values.ac,Stunde:values.ad,Minute:values.ae,Sekunde:values.af};
let string ={Tag:JSON.stringify(values.aa),Monat:JSON.stringify(values.ab),Jahr:JSON.stringify(values.ac),Stunde:JSON.stringify(values.ad),Minute:JSON.stringify(values.ae),Sekunde:JSON.stringify(values.af)};
let sa ={Tag:JSON.stringify(values.aa),Monat:JSON.stringify(values.ab),Jahr:JSON.stringify(values.ac),Stunde:JSON.stringify(values.ad),Minute:JSON.stringify(values.ae),Sekunde:JSON.stringify(values.af)};
string.Datum =(string.Tag +':' +string.Monat +':' +string.Jahr);
string.Zeit =(string.Stunde +':' +string.Minute +':' +string.Sekunde);
for (let v in sa){if (sa[v].length < 2){sa[v] ='0' +sa[v];}}
let twoDigits ={Tag:sa.Tag,Monat:sa.Monat,Jahr:sa.Jahr,Stunde:sa.Stunde,Minute:sa.Minute,Sekunde:sa.Sekunde};
twoDigits.Datum =(twoDigits.Tag +':' +twoDigits.Monat +':' +twoDigits.Jahr);
twoDigits.Zeit =(twoDigits.Stunde +':' +twoDigits.Minute +':' +twoDigits.Sekunde);
let ausgabe ={Valid:k,Number:number,String:string,TwoDigits:twoDigits};
return ausgabe;
}
//############################## Config ############################
let Config = {
temp_min : 25, // Minimale Temperatur Testwerte
temp_max : 45, // Maximale Kollektor Temperatur
id_inside : 100, // Sensor Id (Solar_Kollektor_Ruecklauf_Temp)
id_input : 100, // Wind Sensor 0 - 100%
W_max : 40, // Zu viel Wind
speed_real : 0, // Wahrer Wind
w_speed : 0,
w_temp : 0,
roller : 0,
Abend : 728, //18h==>1080 + 45 minuten == 1125
interval : 10 // 2 seconds is the minimum interval
}
//############################## Config end ############################
function watch()
{
try
{
let shellyTime = Shelly.getComponentStatus("sys").unixtime;
let newDate = TsKonverter(shellyTime, +1);
if(newDate.Valid)
{
print(newDate.TwoDigits.Zeit);
// h:m in Minuten umrechnen
let h =(newDate.Number.Stunde);
let m = (newDate.Number.Minute);
let minuten = (( h * 60 ) + m );
print('Minuten = ',minuten);
}
//else {
temp_inside = Shelly.getComponentStatus('Temperature', Config.id_inside).tC; //temperature:100":{"id": 100,"tC":20.9, "tF":69.6}
print('Temp. Kollektor Ruecklauf =',temp_inside); // (Solar_Kollektor_Ruecklauf_Temp)
let w_temp = Math.floor(temp_inside);
print ('Kollektor Ruecklauf_integer =' ,w_temp);
//----------------- das Läuft ------------------------------------------------
speed_real = Shelly.getComponentStatus('input',Config.id_input).percent; //"input:100":{"id":100,"percent":0.0}
print('Wind_real =', speed_real);
let w_speed = Math.floor(speed_real);
print ('Wind_integer =' ,w_speed);
// --------------- Info wird ausgegeben ------------------------------------------------
if (minuten >= Config. Abend) {
Shelly.call("http.get",{url:'http://127.0.0.1/roller/' + JSON.stringify(Config.roller) + '?go=to_pos&roller_pos=4'});
print('Rollo(',Config.roller, ') Rollo geschlossen Abend >= ', Config.minuten);
}
else {
// tu nix
if (w_speed >= Config. W_max) {
Shelly.call("http.get",{url:'http://127.0.0.1/roller/' + JSON.stringify(Config.roller) + '?go=to_pos&roller_pos=4'});
print('Rollo(',Config.roller, ') geschlossen. Wind_speed to high >= ', w_speed);
} //
else { //
if (w_temp <= Config.temp_min) {
Shelly.call("http.get",{url:'http://127.0.0.1/roller/' + JSON.stringify(Config.roller) + '?go=to_pos&roller_pos=4'});
print('Rollo(',Config.roller, ') geschlossen. Inside temp <= ', Config.temp_min);
}
else {
if (w_temp >= Config.temp_max) {
Shelly.call("http.get",{url:'http://127.0.0.1/roller/' + JSON.stringify(Config.roller) + '?go=to_pos&roller_pos=90'});
print('Rollo(',Config.roller, ') beschattet. Outside temp >= ', Config.temp_max);
}
else {
}
}
}
//}
}
}
// print('\n')
catch (err) {
Shelly.call("http.get", {192.168.178.57 + JSON.stringify(Config.rollo) +'?go=to_pos&roller_pos=90'});
print(err);
}
}
function start() {
// do a first shot
watch();
// set watch timer to configured value
Timer.set(Config.interval * 1000,true,watch);
}
// schedule script start for 1 second
Timer.set(1000,false,start); // alle 10 Secunden prüfen & reagieren
Das war es dann , viel Spaß beim testen .
Bin gespannt auf die Reaktionen
Der Udo