Farbcode Wand Farbe

Bauhaus

  • Weiß Swingcolor Arktisweiß
  • Blau EG Arbeitszimmer: Farbcode 21.054 SwingColor 6239 SC Arktisweiß B2/4
  • Hellblau Farbcode: 01.013.02 Sch Wohnen SwingColor 6239 SC Arktisweiß B2/3/4

Obi

  • Beige EG Badezimmer Farbcode: E 10.6 Obi Color 2.0 Basis M1 DesignColor Matt
  • Braun EG Schlafzimmer Farbcode: 03.028.03 Sch Wohnen Studio Basis M1 Designcolor Matt

Elektroinstallation Garten

Sicherung an Starkstrom Keller. Strom kommt von BEKU Keller bis neben Wendeltreppe. Dort Verteilerdose für

  • Terassenverteiler (nicht angeschlossen)
  • Weiß Schuppen (nicht angeschlossen)
  • Schwarz (angeschlossen)

Schwarz und weiß führt in den Verteiler beim Schuppen. Von dort einmal zur Lampe, und einmal an der Grundstücksgrenze bis zum Ahorn. Verteilerdose auf Höhe Hochbeet noch nicht angeschlossen (Steckdose im Hochbeet noch nicht angeschlossen.)

Achtung: Sicherung hat auch Waschkeller dabei, wenn also die Sicherung fällt ist auch der Strom für Tiefkühler und Kühlschrank weg.

Heizung Python Code

ESP32 Leonding mixer board version @ 29.11.2022 hmanfred

vers. main-Oct18-2023 for new heatpump setup

#
import os
from machine import I2C,Pin,RTC,Timer # RTC built-in
from eeprom_i2c import EEPROM,T24C512
import sh1106 # oled display Treiber
import time
from time import sleep
import onewire # fuer 1-wire
import ds18x20 # fuer 1-wire temp
import network
import ntptime # ntp PTBtime
import ftplib
#
monat=
[„“,“Jan“,“Feb“,“Mar“,“Apr“,“Mai“,“Jun“,“Jul“,“Aug“,“Sep“,“Okt“,“Nov“,“Dez
„]

definition und setup von System-Konstanten

const_kessel_is_off = 25.0 # wenn kaelter als ..
var_mixer_is_closed=False # zu bei HotWater
const_aussen_limit_summer=18.0
const_aussen_min_cold=8.0 # Hzg wieder an
const_T_aussen_avg=6 # no. of average readings
const_sensor_count=3
const_eeprom_dir = „/eeprom/“ # directory of ext memory
var_eeprom_ok = False # eeprom operational
const_daytime_start=5 # begin der warm phase early
const_daytime_stop=22 # begin of cold phase
var_is_daytime=True # hot day phase
var_current_time=“ # current time as str
const_T_offset_gen=0.0 # offset of T_sollw
const_T_offset_night=-2.0 # in daily cold phase
var_display_on=True
const_display_on_start=8 # 10 Uhr an
const_display_on_stop=23 # 22 Uhr aus
var_display_loop = 1 # partial display counter
const_display_loop = 6 # partial display num
var_is_summer = False
const_steilheit=0.39 # Hzg Steilheit
const_room_temp=20.0 # first guess
const_linear_range=4.0 # linear control range
const_motor_time=2.0 # move x longer than diff
var_ssid = „BEHAKU“
var_password = „dasisteinkeyderrockt“
var_Wifi_on=False # status WLan
const_ntp_host = „ptbtime2.ptb.de“
var_timeframe_ok = False # rtc time about correct n/ok
var_log_filename=““ # name of daily logfile
var_once_daily=True # do it only once daily
const_sleeptime = 0.2 # Sleeptime in seconds per perm loop
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 2
var_ftp_dir = ‚2023‘ # /home/** dir on ftp server

ESP32 pins for line power switches

PwrRelay1_enable=Pin(26,Pin.OUT)
PwrRelay2_enable=Pin(25,Pin.OUT)
PwrRelay1_enable.value(0)
PwrRelay2_enable.value(0)
#

frontpanel blue indicator LED

blueLED=Pin(27,Pin.OUT) # „1“ eq. off
blueLED.value(1) # off
#

pointer fuer OLED display SW

ds=0
display=0
#

Zeile mit logfile Werten

logtextline = “
var_current_time = “ # as str
#

init temperature variables

Tvalue_new = [] # list of new 18×20 readings
Tvalue_kessel = 0
Tvalue_sollw = 0
Tvalue_vorl = 0
Tvalue_aussen = 0
Tvalue_diff = 0
Tvalue_aussen_list = [10.5,10.5,10.5,10.5,10.5,10.5] # init
motor_time = 0.0 # motor activity time

scheduler: flags and timings

ntp_flag = False
tim_count_ntp_max = 15000 # 4h
tim_count_ntp = tim_count_ntp_max
meas_flag = False
tim_count_meas_max = 60 # 1min
tim_count_meas = tim_count_meas_max
display_flag = False
tim_count_display_max = 20 # 3x /min
tim_count_display = tim_count_display_max
eep_flag = False
tim_count_eep_max = 603 # 11min
tim_count_eep = tim_count_eep_max
control_flag = False
tim_count_control_max = 300 # 5min
tim_count_control = tim_count_control_max
ftp_flag = False
tim_count_ftp_max = 1203 # 20min
tim_count_ftp = tim_count_ftp_max
blink_flag = False
tim_count_blink = 1 # 1sec

#

def handler_0(tim_0):
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 3

task scheduler with 1 sec loop

global tim_count_ntp
global tim_count_meas
global tim_count_ftp
global tim_count_eep
global tim_count_display
global tim_count_control
global ntp_flag
global meas_flag
global ftp_flag
global display_flag
global eep_flag
global control_flag
global blink_flag
tim_count_ntp -=1 # decrement
if tim_count_ntp == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
ntp_flag = True
tim_count_ntp = tim_count_ntp_max
tim_count_meas -=1 # decrement
if tim_count_meas == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
meas_flag = True
tim_count_meas = tim_count_meas_max
tim_count_display -=1 # decrement
if tim_count_display == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
display_flag = True
tim_count_display = tim_count_display_max
tim_count_eep -=1 # decrement
if tim_count_eep == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
eep_flag = True
tim_count_eep = tim_count_eep_max
tim_count_control -=1 # decrement
if tim_count_control == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
control_flag = True
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 4
tim_count_control = tim_count_control_max
tim_count_ftp -=1 # decrement
if tim_count_ftp == 0:
blueLED.value(0)
sleep(0.2)
blueLED.value(1)
ftp_flag = True
tim_count_ftp = tim_count_ftp_max
blink_flag = True
#
tim0 = Timer(0)
tim0.init(period=1000,mode=Timer.PERIODIC,callback=handler_0)

#

def init_sys():
global ds
global display
global var_eeprom_ok

initialisieren OLED sh1106 display

i2c = I2C(0, scl=Pin(22), sda = Pin(21),freq=100000)
display = sh1106.SH1106_I2C(128,64,i2c,None,0x3c,0)
display.sleep(False)
display.contrast(60)
showtext1 = “ ESP32 Mixer „
showtext2 = “ …starting.“
display.fill(0)
display.text(showtext1,0,10)
display.text(showtext2,0,20)
display.show()
#

initialisieren serielle Temp.-Sensoren

ow=onewire.OneWire(Pin(33))
ow.reset()
ds=ds18x20.DS18X20(ow)

init eeprom log Speicher 128k -> boot.py

eep = EEPROM(I2C(0,scl=Pin(22),sda=Pin(21)),T24C512)
sleep(0.1)
try:
os.mount(eep,’/eeprom‘)
var_eeprom_ok = True
except:
var_eeprom_ok = False
#
if var_eeprom_ok == True:
print(„eeprom mem ok: „, os.listdir(„/eeprom“))
return
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 5

#

def meas_temps():

aktualisieren von measurements, average, update globals

global Tvalue_aussen_list
global Tvalue_aussen
global Tvalue_kessel
global Tvalue_vorl
global Tvalue_new

read temp sensors data set at every timer flag

Tvalue_new = read_ds18x20(Tvalue_new)

build average over last … readings of T_aussen temp

Tvalue_aussen_tmp = Tvalue_new[2]
print(‚Taussen_raw: ‚,Tvalue_aussen_tmp)
Tvalue_aussen_list.append(Tvalue_aussen_tmp)
del Tvalue_aussen_list[0] # pop the oldest
len_tmp = len(Tvalue_aussen_list)
Tvalue_aussen = sum(Tvalue_aussen_list)/float(len_tmp)
Tvalue_aussen = round(Tvalue_aussen,2)

read the temp of FB vorlauf water and kessel

Tvalue_vorl = round(Tvalue_new[1],2)
Tvalue_kessel = round(Tvalue_new[0],2)
#
return

#

def find_daytime():

define display on/off period from hours field in .datetime()

global var_display_on
global var_is_daytime
global display
global var_ftp_dir
if (RTC().datetime()[4] > const_display_on_start) and \
(RTC().datetime()[4] <= const_display_on_stop):
var_display_on=True
display.sleep(False)
else:
var_display_on = False # normally False
display.sleep(True)
#

define warm daytime or cold nighttime period

if (RTC().datetime()[4] > const_daytime_start) and \
(RTC().datetime()[4] < const_daytime_stop):
var_is_daytime = True
else:
var_is_daytime = False
#

define the current year for ftp storage dir

var_ftp_dir = str(RTC().datetime()[0])
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 6
return

#

def find_filename():

define new logfile name for every new day

global var_log_filename
month_tmp = monat[RTC().datetime()[1]]
date_tmp = str(RTC().datetime()[2])
new_filename=“logfile-„+month_tmp+date_tmp+“.txt“
var_log_filename = new_filename # global var
return new_filename

#

def calc_Tsoll(T_aussen):

calculation of FB Vorlauf target

always add const_T_offset_gen

new_temp = const_steilheit * (const_room_temp – T_aussen) +
const_room_temp
new_temp = new_temp + const_T_offset_gen
new_temp = round(new_temp,2)
return new_temp
#

#

def display_oled(linecnt):

collect data and display on oled display 15char/line

dynamic 8 values in 4 steps shifted by 2 lines

global display
global var_display_on
global var_current_time
if var_display_on :
textline1 = „*ESP32 „+var_current_time
textline2 = „T-aussen “ +str(Tvalue_aussen)
textline3 = „T-kessel “ +str(Tvalue_kessel)
textline4 = „T-vorl “ +str(Tvalue_vorl)
textline5 = „T-sollw “ +str(Tvalue_sollw)
textline6 = „motor-tm “ +str(motor_time)
textline7 = „daytime “ +str(var_is_daytime)
textline8 = „systime “ +var_current_time
textline9 = „Wifi on “ +str(var_Wifi_on)
textline10 = „RTC ok “ +str(var_timeframe_ok)
#
if linecnt == 1:
showtext1 = textline1
showtext2 = textline2
showtext3 = textline3
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 7
showtext4 = textline4
showtext5 = textline5
showtext6 = textline6
elif linecnt == 2:
showtext1 = textline3
showtext2 = textline4
showtext3 = textline5
showtext4 = textline6
showtext5 = textline7
showtext6 = textline8
elif linecnt == 3:
showtext1 = textline5
showtext2 = textline6
showtext3 = textline7
showtext4 = textline8
showtext5 = textline9
showtext6 = textline10
elif linecnt == 4:
showtext1 = textline7
showtext2 = textline8
showtext3 = textline9
showtext4 = textline10
showtext5 = textline1
showtext6 = textline2
elif linecnt == 5:
showtext1 = textline3
showtext2 = textline4
showtext3 = textline5
showtext4 = textline6
showtext5 = textline7
showtext6 = textline8
#
display.sleep(False)
display.fill(0)
display.text(showtext1,0,0)
display.text(showtext2,0,10)
display.text(showtext3,0,20)
display.text(showtext4,0,30)
display.text(showtext5,0,40)
display.text(showtext6,0,50)
display.show()
else:
display.sleep(True)
return
#

#

def store_logdata():

form the log data line and store on eeprom

global logtextline
global var_is_daytime
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 8
global var_eeprom_ok
global var_current_time
logtextline = var_current_time
logtextline = logtextline +“;“+str(Tvalue_aussen)
logtextline = logtextline +“;“+str(Tvalue_kessel)
logtextline = logtextline +“;“+str(Tvalue_vorl)
logtextline = logtextline +“;“+str(Tvalue_sollw)
diff_tmp = round(Tvalue_diff,2)
logtextline = logtextline +“;“+str(diff_tmp)
logtextline = logtextline +“;“+str(round(motor_time,2))
if var_is_daytime:
day_tmp = „day „
else:
day_tmp = „night“
logtextline = logtextline +“;“+day_tmp
logtextline = logtextline + „\n“
print(„log: „,logtextline)
if var_eeprom_ok:
try:
filename_tmp = const_eeprom_dir + find_filename()
with open(filename_tmp,“a“) as file:
file.write(logtextline)
print(‚eeprom mem: log data stored‘)
except:
print(„I/O error on file write“)
return

#

def read_ds18x20(readings):

subroutine to measure 18×20 sensors and return list of values

global var_Wifi_on
global ds
readings.clear()
roms = ds.scan()
cnt_sens = len(roms)
sleep(0.9)

print(„found“, str(cnt_sens),“sensors.“)

try:
ds.convert_temp()
sleep(3.0)
except:
print(„found“,str(cnt_sens),“sensors – error in DS18x20 convert
access“)
for rom in roms:
ds18x20_temp = ds.read_temp(rom)
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 9
readings.append(ds18x20_temp)
#
return readings

#

def connect_wifi():

connect built-in WLAN to local access point

global var_Wifi_on
global blueLED
station = network.WLAN(network.STA_IF)
station.active(True)
if station.isconnected() == True:
print(„Wifi already connected.“)
blueLED.value(0) # blink 1x on
sleep(0.4)
blueLED.value(1)
else:
station.connect(var_ssid,var_password)
while station.isconnected() == False:
pass
print(„Wifi connection successful.“)
#
blueLED.value(0) # blink 2x on
sleep(0.3)
blueLED.value(1) # off
if station.isconnected() == True:
var_Wifi_on = True
return

#

def update_ntp_time():
global var_timeframe_ok
global var_Wifi_on
if var_Wifi_on:
ntptime.host = const_ntp_host
MEZ_sec = ntptime.time() +3600 # always winter time
print(‚Wifi on: ntp service: ‚,MEZ_sec)
rtc = RTC()
(year,month,day,hours,minutes,seconds,weekday,yearday) =
time.localtime(MEZ_sec)
rtc.datetime((year,month,day,0,hours,minutes,seconds,0))

rtc time newer than Oct 2023

if time.time() > 750262800:
var_timeframe_ok = True
else:
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 10
var_timeframe_ok = False
else:
print(„Time/RTC: set error – no Wifi.“)
return

#

def move_mixer(mtime):

activate the relais to move the mixer valve

do nothing if time < 1 sec

global PwrRelay1_enable
global PwrRelay2_enable
if (mtime > 1.0) :
PwrRelay1_enable.value(1)
sleep(mtime)
PwrRelay1_enable.value(0)
elif (mtime < -1.0) :
mtime = abs(mtime)
PwrRelay2_enable.value(1)
sleep(mtime)
PwrRelay2_enable.value(0)
return

#

def control_func():

compute movem. and control the 3way valve

global Tvalue_sollw
global Tvalue_kessel
global Tvalue_aussen
global Tvalue_vorl
global Tvalue_diff
global motor_time
find_daytime()
Tvalue_sollw = calc_Tsoll(Tvalue_aussen)
if not var_is_daytime:
Tvalue_sollw = Tvalue_sollw + const_T_offset_night
Tvalue_diff = Tvalue_sollw – Tvalue_vorl

limit active diff temp max to +/- linear range

if (Tvalue_diff > const_linear_range) :
Tvalue_diff = const_linear_range
elif (Tvalue_diff < -const_linear_range) :
Tvalue_diff = -const_linear_range

command mixer motor movement + -> open, – -> close

motor_time = round((const_motor_time * Tvalue_diff),2)
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 11
move_mixer(motor_time)
Tvalue_kessel = round((Tvalue_kessel),2)
Tvalue_aussen = round((Tvalue_aussen),2)
Tvalue_vorl = round((Tvalue_vorl),2)
Tvalue_diff = round(Tvalue_diff,2)
print(„actual time: „,var_current_time)
print(„1: T-aussen „, Tvalue_aussen)
print(„2: T-Kessel „, Tvalue_kessel)
print(„3: T-FB-Vorl.“, Tvalue_vorl)
print(„4: T-FB-Soll.“, Tvalue_sollw)
print(„5. Tval-diff: „, Tvalue_diff)
print(„6: Motor-time: „, motor_time)
return

#

def ftp_store():
#
global var_log_filename
global var_ftp_dir
session=ftplib.FTP
(„192.168.3.215″,21,“heizung“,“Lambergstrasse4060!“,““)
file_tmp=const_eeprom_dir + var_log_filename
print(‚ftp file to transfer: ‚,file_tmp)
ftpcmd = „/home/“+var_ftp_dir
session.cwd(ftpcmd)
file=open(file_tmp,“rb“)
ftpcmd=“STOR „+ var_log_filename
print(‚ftp target file: ‚,var_log_filename)
session.storbinary(ftpcmd,file)
file.close()
session.close()
print(„…tried ftp upload to leonding@nas“)
date_limit=time.time() – 150000 # 41h old
dir_len=len(os.listdir(‚/eeprom‘))
loop=dir_len -1
print(‚files loop: ‚, str(loop))
while loop >= 0:
file1=os.listdir(‚/eeprom‘)[loop]
filename1=’/eeprom/’+str(file1)
print(‚filename1: ‚,filename1)
filedate_raw=os.stat(filename1)[7]
if (filedate_raw < date_limit) and timeframe_ok == True:
os.remove(filename1)
print(’now deleted: ‚,filename1)
loop -=1
C:\Users\manfr\Desktop\ESP32-DEV\main-Okt19-Leo.py 12
return

#

main

#
init_sys() # i2c,display,eeprom
#
connect_wifi() # to local Wifi BEHAKU
#
update_ntp_time()
#
find_daytime()
#
while True: # continuous loop
if meas_flag:
meas_temps()
meas_flag = False
if control_flag:
find_daytime()
control_func()
control_flag = False
if eep_flag:
var_log_filename = find_filename()
store_logdata()
eep_flag = False
if display_flag:
var_current_time = str(time.localtime()[3])+“:“ \
+str(time.localtime()[4])+“:“+str(time.localtime()[5])
display_oled(var_display_loop)
var_display_loop +=1 # increm. screen loop
if var_display_loop == const_display_loop:
var_display_loop = 1
display_flag = False
if ftp_flag:
ftp_store()
ftp_flag = False
if blink_flag:
blueLED.value(0) # on
sleep(0.1)
blueLED.value(1)
blink_flag = False
sleep(const_sleeptime)
#
#

######################end

FuBoHeizung Mischersteuerung

Steuerungsmethoden

  • Außentemperatur (Heizungsraum zum Fenster raus)
  • Vorlauf Mischersteuerung (hinter Mischer)
  • Kesselausgangstemperatur (unter Regelkreis2)

Python Scripting nimmt Werte von Kessel und steuert Vorlauf Mischer abhängig von Außentemperatur alle 5 Minuten Mischer mehr auf oder mehr zu. Alle 20 Sekunden schreibt Python das Log-File Richtung BEKU NAS in das Homeverzeichnis von user „heizung“

Stromanschluss außen

Neuer Stromanschluss außen Richtung Einfahrt und Richtung Garten/Karin

Anschluss 1 „Einfahrt“

Absicherung über Starkstromsicherung Keller, Stromführung in BEHA Keller hinten links hinter dem Schrank Verteilerdose, (3×1,5) dann Führung nach außen unter der Einfahrt Richtung Grundstücksgrenze (3×1,5), dort 1 Phase (1×1,5)ausgelegt und Stromführung bis Feuertonne.

Anschluss 2 „Garten“

Absicherung über Starkstromsicherung Keller, Stromführung von Sicherungskasten über Verteilerdose Treppenhaus in BEKU Keller (1×1,5) und dort gemeinsam mit Wasseranschluss nach außen und dort in Verteilerdose neben Wendeltreppe.