Logger für Solarladeregler
Verfasst: Samstag 2. August 2014, 14:41
Ich habe vor, für einen Solarladeregler der Marke epsolar die aktuellen Messdaten, welche über eine Fernbedienungsschnittstelle auf Basis von RS232 übertragen werden, mit Hilfe eines Raspberry Pis zu loggen. Durch die native Unterstützung von Python habe ich nun mein erstes Projekt versucht mit Python zu realisieren. Der skriptbasierte Ansatz machte es mir natürlich leicht schnell eine Lösung zusammenzuschustern. Leider habe ich nun das Problem, dass das Skript nicht sonderlich robust zu sein scheint - sprich irgendwann hört er einfach auf zu loggen. Die erzeugte Datei soll eigentlich nur ein CSV Format haben, damit ich die einzelnen Messwerte auf dem PC weiterverarbeiten kann. Mein Problem ist jetzt, dass ich den Grund für das Anhalten des Loggens nicht erkenne, da ich dachte, dass er mir wenigstens in meinen Ausnahmebehandlungen (catch-Blöcke) einen Eintrag macht, was das Problem ist.
Der Programmablauf ist folgender:
1. Initialisieren der Logdatei, der seriellen Schnittstelle und einem zyklischen Timer
2. Senden einer Requestbotschaft über RS232 an den Laderegler (zyklisch alle 10 Sekunden für 24h)
3. Empfangen der Antwort und Schreiben der Werte in eine Zeile der CSV-Datei (Logdatei) / (genau wie 2. auch zyklisch in gleicher Funktion)
4. Schließen der Logdatei
So sieht die von Python erzeugte Logdatei aus:
Logging start: 20 04 24, Logging period: 10, Logging time: 86400
Time,Time since Start,ID,Command,Number of Bytes,Battery Voltage,PV Voltage,Load Current,Overdischarge Voltage,Full Voltage,Load detected?,Overloaded?,Short circuit?,Overcharged?,Battery voltage too low?,Batter voltage full?,Charging?,Temperature,Charging current
Thu Jul 17 20:04:24 2014,0.05801510810852051,0,160,24,12.7,18.17,0.0,11.22,14.35,1,0,0,0,0,0,1,31,0.29
... alle 10 sekunden ein Eintrag
Thu Jul 17 22:03:26 2014,7142.438544988632,0,160,24,12.59,1.87,0.03,11.17,14.46,1,0,0,0,0,0,0,28,0.0
das war der letzte Eintrag
Und so sieht es aus wenn ich die Ausgabe in der Bash in Linux umleite auf eine Datei:
Serial port /dev/ttyAMA0 opened
Starting cyclic request of data
Cyclic timer started (period = 10s). Logging for 86400s ...
Request from logger @ 0.003033161163330078s
Response from charger @ 0.05801510810852051s, Response Length: 36, Response: b'\xeb\x90\xeb\x90\xeb\x90\x00\xa0\x18\xf6\x04\x19\x07\x00\x00\x00\x00b\x04\x9b\x05\x01\x00\x00/\x00\x00\x00\x01=\x1d\x00\x00\xf9i\x7f'
Request from logger @ 10.00679898262024s
... und so weiter....
Request from logger @ 7582.3808760643005s
Response from charger @ 7582.4358241558075s, Response Length: 36, Response: b'\xeb\x90\xeb\x90\xeb\x90\x00\xa0\x18\xe9\x04;\x00\x00\x00\x03\x00]\x04\xa6\x05\x01\x00\x00*\x00\x00\x00\x00:\x00\x00\x00D\xc8\x7f'
Das war die letzte Zeile
Der Programmablauf ist folgender:
1. Initialisieren der Logdatei, der seriellen Schnittstelle und einem zyklischen Timer
2. Senden einer Requestbotschaft über RS232 an den Laderegler (zyklisch alle 10 Sekunden für 24h)
3. Empfangen der Antwort und Schreiben der Werte in eine Zeile der CSV-Datei (Logdatei) / (genau wie 2. auch zyklisch in gleicher Funktion)
4. Schließen der Logdatei
Code: Alles auswählen
#!/usr/bin/env python3
import serial
import repeat_timer
import csv
import time
import sys
import random
import array
import socket
#Example for response: eb90eb90eb9000a0180102030405060708090a0b0c0d0e0f101112131415161718ffff7f
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udphost = "xxx.no-ip.biz"
udpport = 50000
log_filename = "Log_Solarlogger_" + time.strftime("Date_%d_%m_%y_Time_%H_%M_%S_number")+ str(random.randint(1, 10000)) + ".csv"
timer_period = 10
period_counter = 0
time_to_complete = 86400
if sys.platform == "linux2":
directory = "//home//pi//"
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
GPIO.output(12, GPIO.HIGH)
if sys.platform == "win32":
directory = "C://Python34//"
request_cmd = array.array('B',[0xEB,0x90,0xEB,0x90,0xEB,0x90,0x01,0xA0,0x01,0x03,0xbd,0xbb,0x7f]).tostring()
response_no_of_bytes = 36
try:
csv_file = open(directory + log_filename,'w', newline='')
csv_handler = csv.writer(csv_file)
except:
print ("Error: Can not open file for write access. File may be open")
print (sys.exc_info())
csv_file.close()
exit(-1)
if sys.platform == "linux2":
si = serial.Serial()
si.port = "/dev/ttyAMA0"
if sys.platform == "win32":
si = serial.Win32Serial()
si.port = 2
si.baudrate = 9600
si.dsrdtr = False
si.parity = 'N'
si.timeout = 5
def request_data(req,response_no_of_bytes):
global s, udphost, udpport, si, time_start, csv_handler, csv_file, period_counter
try:
period_counter += 1
if (period_counter%2==0):
GPIO.output(12, GPIO.LOW)
else:
GPIO.output(12, GPIO.HIGH)
si.write(req)
time_since_start = time.time() - time_start
print("Request from logger @ " + str(time_since_start) + "s")
resp = si.read(response_no_of_bytes)
si.flush()
time_since_start = time.time() - time_start
if (len(resp)== response_no_of_bytes):
print("Response from charger @ " + str(time_since_start) + "s, Response Length: " + str(len(resp)) + ", Response: " + str(resp))
try:
s.sendto(resp, (udphost, udpport))
except socket.error:
print("No network connection")
csv_handler.writerow([time.asctime(),time_since_start,resp[6],resp[7],resp[8],(resp[9] + resp[10]*256)/100,(resp[11] + resp[12]*256)/100,(resp[15] + resp[16]*256)/100,(resp[17] + resp[18]*256)/100,(resp[19] + resp[20]*256)/100,resp[21],resp[22],resp[23],resp[25],resp[26],resp[27],resp[28],resp[29]-30,(resp[30] + resp[31]*256)/100])
else:
print("No response from charger @ "+ str(time_since_start) +"s, Response length: " + str(len(resp)) + " !")
try:
s.sendto(b"hallo", (udphost, udpport))
except socket.error:
print("No network connection")
csv_handler.writerow([time.asctime(),time_since_start,"","","","","","","","","","","","","","","","",""])
except:
print("Error @ " + str(time_since_start) + "s ,Reason: " + sys.exc_info())
csv_handler.writerow(["Error @ "+ str(time_since_start) + "s", "Period " + str(period_counter)])
csv_file.close()
try:
si.open()
print("Serial port " + si.name + " opened")
except serial.serialutil.SerialException:
print ("Error: Can not open serial port. Serial port may be open already")
exit(-2)
except:
print(sys.exc_info())
exit(-2)
try:
if (si.isOpen()):
print("Starting cyclic request of data")
csv_handler.writerow(["Logging start: " + time.strftime("%H %M %S")," Logging period: " + str(timer_period)," Logging time: " + str(time_to_complete)])
csv_handler.writerow(["Time","Time since Start","ID","Command","Number of Bytes","Battery Voltage","PV Voltage","Load Current","Overdischarge Voltage","Full Voltage","Load detected?","Overloaded?","Short circuit?","Overcharged?","Battery voltage too low?","Batter voltage full?","Charging?","Temperature","Charging current"])
print("Cyclic timer started (period = "+ str(timer_period) + "s). Logging for " + str(time_to_complete) +"s ...")
time_start = time.time()
cyclic_timer = repeat_timer.RepeatedTimer(timer_period,True,request_data,request_cmd,response_no_of_bytes)
time.sleep(time_to_complete)
cyclic_timer.stop()
time.sleep(1) #wait for cyclic timer thread to stop
print("Cyclic timer stopped. Logging finished")
print("Finished cyclic request of data")
except:
print("Error 1")
print(sys.exc_info())
finally:
if (si.isOpen()):
print("Closed serial port")
si.close()
if (csv_file.closed == False):
print("Closing file")
csv_file.close()
if sys.platform == "linux2":
GPIO.output(12, GPIO.LOW)
GPIO.cleanup()
print("End")
exit(0)
Logging start: 20 04 24, Logging period: 10, Logging time: 86400
Time,Time since Start,ID,Command,Number of Bytes,Battery Voltage,PV Voltage,Load Current,Overdischarge Voltage,Full Voltage,Load detected?,Overloaded?,Short circuit?,Overcharged?,Battery voltage too low?,Batter voltage full?,Charging?,Temperature,Charging current
Thu Jul 17 20:04:24 2014,0.05801510810852051,0,160,24,12.7,18.17,0.0,11.22,14.35,1,0,0,0,0,0,1,31,0.29
... alle 10 sekunden ein Eintrag
Thu Jul 17 22:03:26 2014,7142.438544988632,0,160,24,12.59,1.87,0.03,11.17,14.46,1,0,0,0,0,0,0,28,0.0
das war der letzte Eintrag
Und so sieht es aus wenn ich die Ausgabe in der Bash in Linux umleite auf eine Datei:
Serial port /dev/ttyAMA0 opened
Starting cyclic request of data
Cyclic timer started (period = 10s). Logging for 86400s ...
Request from logger @ 0.003033161163330078s
Response from charger @ 0.05801510810852051s, Response Length: 36, Response: b'\xeb\x90\xeb\x90\xeb\x90\x00\xa0\x18\xf6\x04\x19\x07\x00\x00\x00\x00b\x04\x9b\x05\x01\x00\x00/\x00\x00\x00\x01=\x1d\x00\x00\xf9i\x7f'
Request from logger @ 10.00679898262024s
... und so weiter....
Request from logger @ 7582.3808760643005s
Response from charger @ 7582.4358241558075s, Response Length: 36, Response: b'\xeb\x90\xeb\x90\xeb\x90\x00\xa0\x18\xe9\x04;\x00\x00\x00\x03\x00]\x04\xa6\x05\x01\x00\x00*\x00\x00\x00\x00:\x00\x00\x00D\xc8\x7f'
Das war die letzte Zeile