Hallo Leute,
ich suche einen Programmierer für ein Pi3 Projekt.
Was soll umgesetzt werden (grober Überblick):
.) Überschussverwertung, aufheizen eines Warmwasserspeicher mittels Photovoltaik.
.) Je nach verfügbarer PV Leistung stufenweises zuschalten (oder wieder wegschalten) von bis zu sechs Heizstäben
.) Kriterien fürs Zu- wegschalten der Lasten sind z.B.
Batterie Ladezustand SOC
Batteriespannung
Batteriestrom
Status Laderegler (OFF, Bulk, ABS, Float.... )
Status Wechselrichter (Durchleiten, Invert...)
Aktuelle Last der Wechselrichter
.) Die Werte für oben angeführte Kriterien sind über Modbus TCP aus einer Victron Color Control
auszulesen. Detailierte Adressliste der entsprechenden Register ist vorhanden.
https://www.victronenergy.de/panel-syst ... or-control
Aufwandsentschädigung nach Abstimmung.
Bei Interesse oder Fragen bitte PN.
Danke
Grüße
Peter
Programmierer gesucht....
Sieht im Moment so aus und das Zu und Wegschalten der Heizstäbe funktioniert.
Die "print" sind derzeit nur zum Testen.
Ein paar Dinge gehören noch angepasst: z.B. Fehlerbehandlung #assert(rr.function_code < 0x80) # test that we are not an error
Assert is da glaube ich falsch am Platz.
Aber eins nach dem Anderen....
Die "print" sind derzeit nur zum Testen.
Ein paar Dinge gehören noch angepasst: z.B. Fehlerbehandlung #assert(rr.function_code < 0x80) # test that we are not an error
Assert is da glaube ich falsch am Platz.
Aber eins nach dem Anderen....
Code: Alles auswählen
from pymodbus.client.sync import ModbusTcpClient
import time
import RPi.GPIO as GPIO
#Victron Color Control IP Adresse
host = '192.168.0.214'
port = 502
#GPIO Pins init
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.OUT)
GPIO.output(22, GPIO.LOW)
GPIO.setup(23, GPIO.OUT)
GPIO.output(23, GPIO.LOW)
GPIO.setup(24, GPIO.OUT)
GPIO.output(24, GPIO.LOW)
GPIO.setup(25, GPIO.OUT)
GPIO.output(25, GPIO.LOW)
GPIO.setup(26, GPIO.OUT)
GPIO.output(26, GPIO.LOW)
GPIO.setup(27, GPIO.OUT)
GPIO.output(27, GPIO.LOW)
# Unit IDs
UID_BATT = 245 #Color Control VE.Direkt port2
UID_SOLARCHARGER = 100 #VE CAN inst 0
UID_VEBUS = 246 #Color Control VE.Bus port
# Batteriemonitor
ADR_BMON_TEMP = 262
ADR_BMON_VOLTAGE = 259
ADR_BMON_CURRENT = 261
ADR_BMON_SOC = 266
#Solarcharger
ADR_SOLARCHARGER_BATTEMP = 773
#Solarcharger ON/OFF
# 1=On 4=Off
ADR_SOLARCHARGER_ONOFF = 774
#Solarcharger state
# 0=Off 2=Fault 3=Bulk 4=Absorption 5=Float 6=Storage
# 7=Equalize 11=Other(Hub-1) 252=Hub-1
SCS_OFF = 0
SCS_FAULT = 2
SCS_BULK = 3
SCS_ABS = 4
SCS_FLOAT = 5
SCS_STORAGE = 6
SCS_EQUALIZE = 7
SCS_OTHER = 11
SCS_HUB1 = 252
ADR_SOLARCHARGER_STATE = 775
#Solarcharger error
# 0=No error
# 1=Battery temperature too high
# 2=Battery voltage too high
# 3=Battery temperature sensor miswired (+)
# 4=Battery temperature sensor miswired (-)
# 5=Battery temperature sensor disconnected
# 6=Battery voltage sense miswired (+)
# 7=Battery voltage sense miswired (-)
# 8=Battery voltage sense disconnected
# 9=Battery voltage wire losses too high
# 17=Charger temperature too high
# 18=Charger over-current
# 19=Charger current polarity reversed
# 20=Bulk time limit reached
# 22=Charger temperature sensor miswired
# 23=Charger temperature sensor disconnected
# 34=Input current too high
ADR_SOLARCHARGER_ERR = 788
#Wechselrichter Load Phase L1, L2, L3
ADR_WR_POWER_L1 = 23
ADR_WR_POWER_L2 = 24
ADR_WR_POWER_L3 = 25
# Wechselrichter overload alarm L1, L2. L3
# 0=Ok 1=Warning 2=Alarm
ADR_WR_OLALARM_L1 = 46
ADR_WR_OLALARM_L2 = 50
ADR_WR_OLALARM_L3 = 54
# Vebus (Wechselrichter) state
# 0=OFF 1=Low Power 2=Fault 3=Bulk 4=Absorption 5=Float 6=Storage 7=Equalize
# 8=Passthru 9=Inverting 10=Power assist 11=Power supply 252=Bulk protection
VE_INVERTING = 9
ADR_VEBUS_STATE = 31
#Vebus (Wechselrichter) error
# 0=No error;
# 1=VE.Bus Error 1: Device is switched off because one of the other phases in the system has switched off;
# 2=VE.Bus Error 2: New and old types MK2 are mixed in the system;
# 3=VE.Bus Error 3: Not all- or more than- the expected devices were found in the system;
# 4=VE.Bus Error 4: No other device whatsoever detected;
# 5=VE.Bus Error 5: Overvoltage on AC-out;
# 6=VE.Bus Error 6: Error in DDC Program;
# 7=VE.Bus BMS connected- which requires an Assistant- but no assistant found;
# 10=VE.Bus Error 10: System time synchronisation problem occurred;
# 14=VE.Bus Error 14: Device cannot transmit data;
# 16=VE.Bus Error 16: Dongle missing;
# 17=VE.Bus Error 17: One of the devices assumed master status because the original master failed;
# 18=VE.Bus Error 18: AC Overvoltage on the output of a slave has occurred while already switched off;
# 22=VE.Bus Error 22: This device cannot function as slave;
# 24=VE.Bus Error 24: Switch-over system protection initiated;
# 25=VE.Bus Error 25: Firmware incompatibility. The firmware of one of the connected device is not
# sufficiently up to date to operate in conjunction with this device;
# 26=VE.Bus Error 26: Internal error
VE_ERROR_0 = 0
ADR_VEBUS_ERROR = 32
def main():
client = ModbusTcpClient(host, port)
client.connect()
heizung_an = False
abs_ok = 0
abs_nok = 0
ABS_OK_MAX = 900 #ABS Phase muss 15min UNUNTERBROCHEN stabil sein um einen Heizstab zuzuschalten
ABS_NOK_MAX = 60 #ABS Phase muss 1min UNUNTERBROCHEN stabil sein um Heizstab wegzuschalten
heizung_cnt = 0 # Zähler für aktiven Heizstab. Bei 0 ist kein Heistab aktiv
heizung_cnt_max = 6 # Anzahl Heistäbe
heizung_cnt_min = 0
while True:
# Auslesen der relevanten Werte
rr = client.read_holding_registers(ADR_BMON_VOLTAGE,1,unit = UID_BATT)
#assert(rr.function_code < 0x80) # test that we are not an error
batt_voltage = (rr.registers[0]) / 100
rr = client.read_holding_registers(ADR_BMON_CURRENT,1,unit = UID_BATT)
#assert(rr.function_code < 0x80) # test that we are not an error
batt_current = (rr.registers[0])
if batt_current > 32767: #Strom im Format sint16
batt_current = (batt_current - 65535) / 10
else:
batt_current = batt_current / 10
rr = client.read_holding_registers(ADR_BMON_SOC,1,unit = UID_BATT)
#assert(rr.function_code < 0x80) # test that we are not an error
batt_soc = (rr.registers[0]) / 10
rr = client.read_holding_registers(ADR_VEBUS_STATE,1,unit = UID_VEBUS)
#assert(rr.function_code < 0x80) # test that we are not an error
vebus_state = (rr.registers[0])
rr = client.read_holding_registers(ADR_SOLARCHARGER_STATE,1,unit = UID_SOLARCHARGER)
#assert(rr.function_code < 0x80) # test that we are not an error
solarcharger_state = (rr.registers[0])
print("--------------------------------------------")
print ("Batteriespannung: ", batt_voltage, "V")
print ("Batteriestrom: ", batt_current, "A")
print ("Ladezustand: ", batt_soc,"%")
print ("Solarcharger State: ", solarcharger_state)
print("--------------------------------------------")
if solarcharger_state == SCS_OFF or solarcharger_state == SCS_FAULT:
if heizung_an: # ALLE Heizungstäbe ausschalten wenn Laderegler Status "OFF" oder "FAULT"
abs_ok = 0
abs_nok = 0
ABS_OK_MAX = 900
ABS_NOK_MAX = 30
heizung_cnt = 0
HEIZUNG_CNT_MAX = 6
HEIZUNG_CNT_MIN = 0
for heizung_cnt in range(1,heizung_cnt_max + 1):
time.sleep(1)
GPIO.output(heizung_cnt + 22, GPIO.LOW) # Alle Heizstäbe ausschalten
heizung_cnt = 0
heizung_an = False
else:
if vebus_state == VE_INVERTING: # Heizung nur aktiv wenn Wechselrichter im Inverterbetrieb
if solarcharger_state == SCS_ABS or solarcharger_state == SCS_FLOAT:
abs_ok = abs_ok + 1
abs_nok = 0
if abs_ok == ABS_OK_MAX:
abs_ok = 0
if heizung_cnt < HEIZUNG_CNT_MAX:
heizung_cnt = heizung_cnt + 1
heizung_an = True
GPIO.output(heizung_cnt + 22 - 1, GPIO.HIGH)
else:
abs_nok = abs_nok + 1
abs_ok = 0
if abs_nok == ABS_NOK_MAX:
abs_nok = 0
if heizung_cnt > HEIZUNG_CNT_MIN:
GPIO.output(heizung_cnt + 22 - 1, GPIO.LOW)
heizung_cnt = heizung_cnt - 1
if heizung_cnt == 0:
heizung_an = False
else:
if heizung_an: # ALLE Heizungstäbe ausschalten wenn Wechselrichter nicht im Inverterbetrieb
abs_ok = 0
abs_nok = 0
ABS_OK_MAX = 600
ABS_NOK_MAX = 30
heizung_cnt = 0
HEIZUNG_CNT_MAX = 6
HEIZUNG_CNT_MIN = 0
for heizung_cnt in range(1,heizung_cnt_max + 1):
time.sleep(1)
GPIO.output(heizung_cnt + 22, GPIO.LOW) # Alle Heizstäbe ausschalten
heizung_cnt = 0
heizung_an = False
print ("Heizung An: ", heizung_an)
print ("Aktiver Heizstab: ", heizung_cnt)
print ("Sekunden über ABS Phase: ", abs_ok)
print ("Sekunden unter ABS Phase: ", abs_nok)
time.sleep(1)
client.close()
if __name__ == "__main__":
main()
@Pete60: Warnungen sind dazu da, dass man sie behebt und nicht einfach ignoriert. Die main-Funktion ist viel zu lang und sollte in mehrere Funktionen aufgeteilt werden. Es werden Konstanten innerhalb von if-Blöcken definiert und in anderen verwendet. Das ist ein Fehler. Konstanten sollten am Anfang des Programms stehen. Die if-Blöcke sind doppelt und sollten in Funktionen ausgegliedert werden.
Hallo Sirius3
Hatte ich mir gedacht und werde ich berücksichtigen.Sirius3 hat geschrieben:Warnungen sind dazu da, dass man sie behebt und nicht einfach ignoriert.
Ok, wird geändert.Sirius3 hat geschrieben:. Es werden Konstanten innerhalb von if-Blöcken definiert und in anderen verwendet. Das ist ein Fehler. Konstanten sollten am Anfang des Programms stehen.
Leuchtet mir ein und wird ebenso geändert....wenn ich weiß wie ich das umsetze.Sirius3 hat geschrieben: Die if-Blöcke sind doppelt und sollten in Funktionen ausgegliedert werden.