Ich habe ein Skript für die Ladesteuerung einer Batterie geschrieben (bitte keine DIskussion über den Sinn dahinter... es ist für mich erstmal ein Weg in ein Thema reinzukommen), das grundsätzliche Prinzip sieht folgendermaßen aus: Ich habe eine Ladeplatine, die ich mit einem Raspberry Pi (im Folgenden "Steuerungspi") via CAN anspreche. Je nach Nachricht, die ich der Ladeplatine schicke, setzt diese etwa eine Spannung an um die Batterie zu laden, sendet einen Heartbeat (wichtig, weil sonst die Ladeplatine nach einer gewissen Zeit "aus geht" ) oder beendet den Ladevorgang.
Weiterhin habe ich einen zweiten RasPi mit einem Pilogger (im Folgenden MessPi) der den Ladevorgang überwacht, also Spannung und Strom misst und abspeichert.
Nun möchte ich den Ladevorgang beenden und ein Relais schalten sobald der Messpi die Ladeschlussspannung misst. Dafür habe ich mich dazu entschieden einen Socketserver herzustellen, der solange wartet, bis der Messpi den Befehl sendet, dass die Ladeschlussspannung erreicht wurde. Da ich erst seit etwa 2 Monaten lerne zu Programmieren und auch vorher nie mit einem Raspberry in Berührung kam bitte ich um Nachsicht. Ich habe mir folgendes Tutorial für meinen Anwendungsfall zurechtgeschnitten. Wenn ich "nur" die Skripte für die Übertragung von Daten und daraus resultierenden Aktionen laufen lasse klappt eigentlich alles. Doch jetzt möchte ich das ganze in mein Ladeskript implementieren und bin dadurch leicht überfordert....
zunächst einmal mein Ladeskript auf dem Steuerpi (dem Sever):
Code: Alles auswählen
import can
from colorama import Fore
import socket
from Relais import closeRelais
STOP_CHARGE = 0x00200039
START_CHARGE = 0x00200038
HEARTBEAT_REQUEST = 0x0FE00000 #Can-Nachrichten für die Ladeplatine
host = ''
port = 5560
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
def setupConnection():
s.listen(1) # Allows one connection at a time.
conn, address = s.accept()
print("Connected to: " + address[0] + ":" + str(address[1]))
return conn
def dataTransfer(conn):
# A big loop that sends/receives data until told not to.
while True:
data = conn.recv(1024) # receive the data
data = data.decode('utf-8')
# Split the data such that you separate the command from the rest of the data.
dataMessage = data.split(' ', 1)
command = dataMessage[0]
if command == 'RELAIS_OFF':
closeRelais()
print("Relais geschlossen")
reply = 'Relais closed'
s.close()
elif command == 'KILL':
print("Our server is shutting down.")
s.close()
break
else:
reply = 'Unknown Command'
# Send the reply back to the client
conn.sendall(str.encode(reply))
print("Data has been sent!")
conn.close()
def send_message(bus, id, periodic=None):
msg = can.Message(arbitration_id=id, data=[], extended_id=True)
if periodic is None:
bus.send(msg)
else:
bus.send_periodic(msg, periodic)
def start_charge(bus):
send_message(bus, START_CHARGE)
print(Fore.BLUE + "\n" "Charging initiated" "\n")
print(Fore.RESET)
def stop_charge(bus):
send_message(bus, STOP_CHARGE)
print("Charging stopped. Battery full. Stop program")
def heartbeat(bus):
send_message(bus, HEARTBEAT_REQUEST, periodic=10)
def main():
try:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native') # Bus-channel aufbauen
except OSError:
print('Cannot find PiCAN board.')
return
try:
start_charge(bus)
heartbeat(bus)
s = setupServer() #Socket herstellen und daten empfangen
while True:
try:
print("1")
conn = setupConnection()
print("2")
dataTransfer(conn)
print("connected")
except:
print("broken")
break
except KeyboardInterrupt:
print(Fore.RED + '\n\r keyboard interrupted\n')
print(Fore.RESET)
finally:
stop_charge(bus)
if __name__ == '__main__':
main()
Main
Code: Alles auswählen
from time import sleep
from Client import transmit
from Get_Data import getVolt
import sys
TRIGGER_VOLT = 41
SLEEP_TIME = 3
def voltMonitor():
print("About to take a reading.")
volt = float(getVolt())
print("Our volt is: " + str(volt))
if volt > float(TRIGGER_VOLT):
message = 'RELAIS_OFF'
print("Transmitting data.")
response = transmit(message)
print(response)
sys.exit()
while True:
voltMonitor()
sleep(SLEEP_TIME)
Code: Alles auswählen
import socket
from time import sleep
host = '192.168.1.187'
port = 5560
def setupSocket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s
def sendReceive(s, message):
s.send(str.encode(message))
reply = s.recv(1024)
print("We have received a reply")
print("Send KILL message.")
s.send(str.encode("KILL"))
s.close()
reply = reply.decode('utf-8')
return reply
def transmit(message):
s = setupSocket()
response = sendReceive(s, message)
return response
Code: Alles auswählen
import smbus
pilogger = smbus.SMBus(1)
def getVolt():
volt_raw = pilogger.read_word_data(0x48, 0x50)
volt = volt_raw * 0.000915541
return volt
def getAmp():
ampere_raw = pilogger.read_word_data(0x48, 0x60)
if ampere_raw >= 32768:
ampere_raw = ampere_raw - 65536
ampere = ampere_raw / 2141.634
return ampere
Die Skripte auf dem Messpi machen soweit was sie tun sollen, jede Sekunde wird die Spannung aus dem Meßwertregister gezogen und umgewandelt.
Das Problem was ich habe ist, dass das Ladeskript auf dem Steuerpi nicht in dem dataTransfer-Loop bleibt und dort solange wartet, bis die "Relais-OFF" Nachricht vom Messpi kommt. Wenn ich das Ladeskript starte erhalte ich Folgendes:
Socket created.
Socket bind complete.
1
broken
Charging initiated
Charging stopped. Battery full. Stop program
scheinbar stimmt irgendwas mit der Connection nicht.. Da dieses Youtube tutorial auch dauernd irgendwelche Zeilen verändert und anpasst scheint da irgendwas verloren gegangen zu sein. Wenn ich nur das "Server" Skript auf dem Steuerpi laufen lasse, dann ist es so, dass der Steuerpi nach "socket bind complete" wartet.
Server
Code: Alles auswählen
import socket
from Relais import closeRelais
host = ''
port = 5560
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
def setupConnection():
s.listen(1) # Allows one connection at a time.
conn, address = s.accept()
print("Connected to: " + address[0] + ":" + str(address[1]))
return conn
def dataTransfer(conn):
# A big loop that sends/receives data until told not to.
while True:
# Receive the data
data = conn.recv(1024) # receive the data
data = data.decode('utf-8')
# Split the data such that you separate the command
# from the rest of the data.
dataMessage = data.split(' ', 1)
command = dataMessage[0]
if command == 'RELAIS_OFF':
closeRelais()
print("Relais geschlossen")
reply = 'Relais closed'
s.close()
elif command == 'KILL':
print("Our server is shutting down.")
s.close()
break
else:
reply = 'Unknown Command'
# Send the reply back to the client
conn.sendall(str.encode(reply))
print("Data has been sent!")
conn.close()
s = setupServer()
while True:
try:
conn = setupConnection()
dataTransfer(conn)
except:
print("broken")
break
Socket created
Socket bind complete.
(an dieser stelle wird gewartet, bis Triggervolt erreicht wird, dann:)
Connected to: 192.168.1.161:41886
Relais geschlossen
Data has been sent!
Our server is shutting down.
broken
Wie gesagt schaffe ich es nicht, die Skripte für die Ladesteuerung und dieses Socketskript zu vereinen... Ich hoffe ihr könnt mir vielleicht weiterhelfen.
Grüße
Minzent