mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-10 01:05:42 +00:00
fix: pevmode: wait for contactors closed (in work). feature: more config options
This commit is contained in:
parent
893ade2e9f
commit
14b1cdb2ff
5 changed files with 141 additions and 15 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,7 @@
|
||||||
|
.*
|
||||||
/__pycache__/
|
/__pycache__/
|
||||||
/doc/*.jar
|
/doc/*.jar
|
||||||
*.bat
|
*.bat
|
||||||
PevExiLog*.txt
|
PevExiLog*.txt
|
||||||
|
pyPlc.ini
|
||||||
|
/log
|
||||||
|
|
77
doc/pyPlc.ini.template
Normal file
77
doc/pyPlc.ini.template
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
# This is the template file pyPlc.ini.template.
|
||||||
|
# Copy this file in the same folder like the pyPlc.py, and rename it to pyPlc.ini
|
||||||
|
|
||||||
|
[general]
|
||||||
|
# mode can be either PevMode to use as car, or EvseMode to use as charger
|
||||||
|
mode = PevMode
|
||||||
|
|
||||||
|
# Simulation without modem
|
||||||
|
# For development purposes, make it possible to run two instances (pev and evse) on one machine, without
|
||||||
|
# a modem connected. This feature is not tested since a long time, most likely does not work as intended.
|
||||||
|
# todo: replace isSimulationMode by this setting
|
||||||
|
is_simulation_without_modems = false
|
||||||
|
|
||||||
|
# The Ethernet interface. Usually eth0 on Raspberry.
|
||||||
|
# Todo: This setting is considered only on linux. Find a clean solution for windows is to be done.
|
||||||
|
eth_interface = eth0
|
||||||
|
|
||||||
|
# If a display is connected via serial line, e.g. an WIFI-KIT-32 running the software from https://github.com/uhi22/SerialToOLED
|
||||||
|
display_via_serial = yes
|
||||||
|
|
||||||
|
# LightBulbDemo turns on the relay with a short delay in the charging loop, to stabilize the voltage
|
||||||
|
# before the resistive load is connected.
|
||||||
|
light_bulb_demo = no
|
||||||
|
|
||||||
|
# SOC simulation.
|
||||||
|
# In PevMode, simulate a rising SOC while charging.
|
||||||
|
soc_simulation = yes
|
||||||
|
|
||||||
|
# Device selection for the digital outputs, for CP state and power relays
|
||||||
|
# Possible options:
|
||||||
|
# dieter: Serial controlled device, which controls the digital outputs. E.g. arduino from https://github.com/uhi22/dieter
|
||||||
|
# beaglebone: GPIO pins of the beagleBone, as used in https://github.com/jsphuebner/pyPLC/tree/beaglebone
|
||||||
|
# celeron55device: Serial controlled device as used in https://openinverter.org/forum/viewtopic.php?p=56192#p56192
|
||||||
|
digital_output_device = dieter
|
||||||
|
#digital_output_device = beaglebone
|
||||||
|
#digital_output_device = celeron55device
|
||||||
|
|
||||||
|
|
||||||
|
# Device to read the physically measured inlet voltage in PevMode
|
||||||
|
# Possible options:
|
||||||
|
# dieter: The high-voltage dieter from https://github.com/uhi22/dieter, which is connected on serial port.
|
||||||
|
# none: if no measurement is intended.
|
||||||
|
# celeron55device: as used in https://openinverter.org/forum/viewtopic.php?p=56192#p56192
|
||||||
|
#analog_input_device = dieter
|
||||||
|
analog_input_device = none
|
||||||
|
#analog_input_device = celeron55device
|
||||||
|
|
||||||
|
|
||||||
|
# Criteria for ending the PreCharge phase in PevMode
|
||||||
|
# Possible options:
|
||||||
|
# yes: use the EVSEPresentVoltage which is reported by the charger, to decide the end of the precharge
|
||||||
|
# no: use the physically measured inlet voltage to decide the end of the precharge
|
||||||
|
use_evsepresentvoltage_for_precharge_end = yes
|
||||||
|
|
||||||
|
# Use the physically measured inlet voltage to show on display during the charge loop.
|
||||||
|
# If false, we are showing the EVSEPresentVoltage which is reported by the charger.
|
||||||
|
use_physical_inlet_voltage_during_chargeloop = no
|
||||||
|
|
||||||
|
# Voltage threshold for the end-of-precharge decision
|
||||||
|
# This is the maximum difference voltage between the charger voltage and the accu voltage. If the actual voltage
|
||||||
|
# difference is lower than this threshold, we will close the power relay, to connect the accu to the charger.
|
||||||
|
# Unit: volt
|
||||||
|
u_delta_max_for_end_of_precharge = 10
|
||||||
|
|
||||||
|
# Added by celeron55
|
||||||
|
# The serial port and baud rate used for communication. Used
|
||||||
|
# for serial devices like Dieter, OLED-Display and
|
||||||
|
# celeron55's measuring and switching device
|
||||||
|
serial_port = /dev/ttyS1
|
||||||
|
serial_baud = 115200
|
||||||
|
|
||||||
|
# The target voltage used in the CurrentDemandRequest.
|
||||||
|
# This is a value for first try-outs. Better would
|
||||||
|
# be if the BMS would provide the value.
|
||||||
|
# 11 * 6 * 4.1V = 66 * 4.1V = 270V
|
||||||
|
charge_target_voltage = 270
|
||||||
|
|
47
fsmPev.py
47
fsmPev.py
|
@ -24,11 +24,12 @@ stateWaitForContractAuthenticationResponse = 7
|
||||||
stateWaitForChargeParameterDiscoveryResponse = 8
|
stateWaitForChargeParameterDiscoveryResponse = 8
|
||||||
stateWaitForCableCheckResponse = 9
|
stateWaitForCableCheckResponse = 9
|
||||||
stateWaitForPreChargeResponse = 10
|
stateWaitForPreChargeResponse = 10
|
||||||
stateWaitForPowerDeliveryResponse = 11
|
stateWaitForContactorsClosed = 11
|
||||||
stateWaitForCurrentDemandResponse = 12
|
stateWaitForPowerDeliveryResponse = 12
|
||||||
stateWaitForWeldingDetectionResponse = 13
|
stateWaitForCurrentDemandResponse = 13
|
||||||
stateWaitForSessionStopResponse = 14
|
stateWaitForWeldingDetectionResponse = 14
|
||||||
stateChargingFinished = 15
|
stateWaitForSessionStopResponse = 15
|
||||||
|
stateChargingFinished = 16
|
||||||
stateSequenceTimeout = 99
|
stateSequenceTimeout = 99
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,6 +82,8 @@ class fsmPev():
|
||||||
s = "WaitForCableCheckResponse"
|
s = "WaitForCableCheckResponse"
|
||||||
if (statenumber == stateWaitForPreChargeResponse):
|
if (statenumber == stateWaitForPreChargeResponse):
|
||||||
s = "WaitForPreChargeResponse"
|
s = "WaitForPreChargeResponse"
|
||||||
|
if (statenumber == stateWaitForContactorsClosed):
|
||||||
|
s = "WaitForContactorsClosed"
|
||||||
if (statenumber == stateWaitForPowerDeliveryResponse):
|
if (statenumber == stateWaitForPowerDeliveryResponse):
|
||||||
s = "WaitForPowerDeliveryResponse"
|
s = "WaitForPowerDeliveryResponse"
|
||||||
if (statenumber == stateWaitForCurrentDemandResponse):
|
if (statenumber == stateWaitForCurrentDemandResponse):
|
||||||
|
@ -408,20 +411,17 @@ class fsmPev():
|
||||||
s= s + "U_Accu " + str(self.hardwareInterface.getAccuVoltage()) + "V"
|
s= s + "U_Accu " + str(self.hardwareInterface.getAccuVoltage()) + "V"
|
||||||
self.addToTrace(s)
|
self.addToTrace(s)
|
||||||
if (abs(u-self.hardwareInterface.getAccuVoltage()) < float(getConfigValue("u_delta_max_for_end_of_precharge"))):
|
if (abs(u-self.hardwareInterface.getAccuVoltage()) < float(getConfigValue("u_delta_max_for_end_of_precharge"))):
|
||||||
self.addToTrace("Difference between accu voltage and inlet voltage is small. Sending PowerDeliveryReq.")
|
self.addToTrace("Difference between accu voltage and inlet voltage is small.")
|
||||||
self.publishStatus("PreCharge done")
|
self.publishStatus("PreCharge done")
|
||||||
if (self.isLightBulbDemo):
|
if (self.isLightBulbDemo):
|
||||||
# For light-bulb-demo, nothing to do here.
|
# For light-bulb-demo, nothing to do here.
|
||||||
self.addToTrace("This is a light bulb demo. Do not turn-on the relay at end of precharge.")
|
self.addToTrace("This is a light bulb demo. Do not turn-on the relay at end of precharge.")
|
||||||
else:
|
else:
|
||||||
# In real-world-case, turn the power relay on.
|
# In real-world-case, turn the power relay on.
|
||||||
|
self.addToTrace("Checkpoint590: Turning the contactors on.")
|
||||||
self.hardwareInterface.setPowerRelayOn()
|
self.hardwareInterface.setPowerRelayOn()
|
||||||
soc = self.hardwareInterface.getSoc()
|
self.DelayCycles = 10 # 10*33ms = 330ms waiting for contactors
|
||||||
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "1")) # EDH for Encode, Din, PowerDeliveryReq, ON
|
self.enterState(stateWaitForContactorsClosed)
|
||||||
self.wasPowerDeliveryRequestedOn=True
|
|
||||||
self.addToTrace("responding " + prettyHexMessage(msg))
|
|
||||||
self.Tcp.transmit(msg)
|
|
||||||
self.enterState(stateWaitForPowerDeliveryResponse)
|
|
||||||
else:
|
else:
|
||||||
self.publishStatus("PreChrge ongoing", format(u, ".0f") + "V")
|
self.publishStatus("PreChrge ongoing", format(u, ".0f") + "V")
|
||||||
self.addToTrace("Difference too big. Continuing PreCharge.")
|
self.addToTrace("Difference too big. Continuing PreCharge.")
|
||||||
|
@ -434,6 +434,28 @@ class fsmPev():
|
||||||
if (self.isTooLong()):
|
if (self.isTooLong()):
|
||||||
self.enterState(stateSequenceTimeout)
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
|
def stateFunctionWaitForContactorsClosed(self):
|
||||||
|
if (self.DelayCycles>0):
|
||||||
|
self.DelayCycles-=1
|
||||||
|
return
|
||||||
|
if (self.isLightBulbDemo):
|
||||||
|
readyForNextState=1 # if it's just a bulb demo, we do not wait for contactor, because it is not switched in this moment.
|
||||||
|
else:
|
||||||
|
readyForNextState = self.hardwareInterface.getPowerRelayConfirmation() # check if the contactor is closed
|
||||||
|
if (readyForNextState):
|
||||||
|
self.addToTrace("Contactors are confirmed to be closed.")
|
||||||
|
self.publishStatus("Contactors ON")
|
||||||
|
if (readyForNextState):
|
||||||
|
self.addToTrace("Sending PowerDeliveryReq.")
|
||||||
|
soc = self.hardwareInterface.getSoc()
|
||||||
|
msg = addV2GTPHeader(self.exiEncode("EDH_"+self.sessionId+"_"+ str(soc) + "_" + "1")) # EDH for Encode, Din, PowerDeliveryReq, ON
|
||||||
|
self.wasPowerDeliveryRequestedOn=True
|
||||||
|
self.addToTrace("responding " + prettyHexMessage(msg))
|
||||||
|
self.Tcp.transmit(msg)
|
||||||
|
self.enterState(stateWaitForPowerDeliveryResponse)
|
||||||
|
if (self.isTooLong()):
|
||||||
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
def stateFunctionWaitForPowerDeliveryResponse(self):
|
def stateFunctionWaitForPowerDeliveryResponse(self):
|
||||||
if (len(self.rxData)>0):
|
if (len(self.rxData)>0):
|
||||||
self.addToTrace("In state WaitForPowerDeliveryRes, received " + prettyHexMessage(self.rxData))
|
self.addToTrace("In state WaitForPowerDeliveryRes, received " + prettyHexMessage(self.rxData))
|
||||||
|
@ -568,6 +590,7 @@ class fsmPev():
|
||||||
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
||||||
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
||||||
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
||||||
|
stateWaitForContactorsClosed: stateFunctionWaitForContactorsClosed,
|
||||||
stateWaitForPowerDeliveryResponse: stateFunctionWaitForPowerDeliveryResponse,
|
stateWaitForPowerDeliveryResponse: stateFunctionWaitForPowerDeliveryResponse,
|
||||||
stateWaitForCurrentDemandResponse: stateFunctionWaitForCurrentDemandResponse,
|
stateWaitForCurrentDemandResponse: stateFunctionWaitForCurrentDemandResponse,
|
||||||
stateWaitForWeldingDetectionResponse: stateFunctionWaitForWeldingDetectionResponse,
|
stateWaitForWeldingDetectionResponse: stateFunctionWaitForWeldingDetectionResponse,
|
||||||
|
|
|
@ -89,6 +89,9 @@ class hardwareInterface():
|
||||||
self.addToTrace("Switching Relay2 OFF.")
|
self.addToTrace("Switching Relay2 OFF.")
|
||||||
self.outvalue &= ~4
|
self.outvalue &= ~4
|
||||||
|
|
||||||
|
def getPowerRelayConfirmation(self):
|
||||||
|
return 1 # todo: self.contactor_confirmed
|
||||||
|
|
||||||
def getInletVoltage(self):
|
def getInletVoltage(self):
|
||||||
# uncomment this line, to take the simulated inlet voltage instead of the really measured
|
# uncomment this line, to take the simulated inlet voltage instead of the really measured
|
||||||
# self.inletVoltage = self.simulatedInletVoltage
|
# self.inletVoltage = self.simulatedInletVoltage
|
||||||
|
|
26
pyPlc.ini
26
pyPlc.ini
|
@ -18,7 +18,7 @@ display_via_serial = yes
|
||||||
|
|
||||||
# LightBulbDemo turns on the relay with a short delay in the charging loop, to stabilize the voltage
|
# LightBulbDemo turns on the relay with a short delay in the charging loop, to stabilize the voltage
|
||||||
# before the resistive load is connected.
|
# before the resistive load is connected.
|
||||||
light_bulb_demo = yes
|
light_bulb_demo = no
|
||||||
|
|
||||||
# SOC simulation.
|
# SOC simulation.
|
||||||
# In PevMode, simulate a rising SOC while charging.
|
# In PevMode, simulate a rising SOC while charging.
|
||||||
|
@ -28,14 +28,21 @@ soc_simulation = yes
|
||||||
# Possible options:
|
# Possible options:
|
||||||
# dieter: Serial controlled device, which controls the digital outputs. E.g. arduino from https://github.com/uhi22/dieter
|
# dieter: Serial controlled device, which controls the digital outputs. E.g. arduino from https://github.com/uhi22/dieter
|
||||||
# beaglebone: GPIO pins of the beagleBone, as used in https://github.com/jsphuebner/pyPLC/tree/beaglebone
|
# beaglebone: GPIO pins of the beagleBone, as used in https://github.com/jsphuebner/pyPLC/tree/beaglebone
|
||||||
|
# celeron55device: Serial controlled device as used in https://openinverter.org/forum/viewtopic.php?p=56192#p56192
|
||||||
digital_output_device = dieter
|
digital_output_device = dieter
|
||||||
#digital_output_device = beaglebone
|
#digital_output_device = beaglebone
|
||||||
|
#digital_output_device = celeron55device
|
||||||
|
|
||||||
|
|
||||||
# Device to read the physically measured inlet voltage in PevMode
|
# Device to read the physically measured inlet voltage in PevMode
|
||||||
# Either the high-voltage dieter from https://github.com/uhi22/dieter, which is connected on serial port.
|
# Possible options:
|
||||||
# Or "none", if no measurement is intended.
|
# dieter: The high-voltage dieter from https://github.com/uhi22/dieter, which is connected on serial port.
|
||||||
|
# none: if no measurement is intended.
|
||||||
|
# celeron55device: as used in https://openinverter.org/forum/viewtopic.php?p=56192#p56192
|
||||||
#analog_input_device = dieter
|
#analog_input_device = dieter
|
||||||
analog_input_device = none
|
analog_input_device = none
|
||||||
|
#analog_input_device = celeron55device
|
||||||
|
|
||||||
|
|
||||||
# Criteria for ending the PreCharge phase in PevMode
|
# Criteria for ending the PreCharge phase in PevMode
|
||||||
# Possible options:
|
# Possible options:
|
||||||
|
@ -53,3 +60,16 @@ use_physical_inlet_voltage_during_chargeloop = no
|
||||||
# Unit: volt
|
# Unit: volt
|
||||||
u_delta_max_for_end_of_precharge = 10
|
u_delta_max_for_end_of_precharge = 10
|
||||||
|
|
||||||
|
# Added by celeron55
|
||||||
|
# The serial port and baud rate used for communication. Used
|
||||||
|
# for serial devices like Dieter, OLED-Display and
|
||||||
|
# celeron55's measuring and switching device
|
||||||
|
serial_port = /dev/ttyS1
|
||||||
|
serial_baud = 115200
|
||||||
|
|
||||||
|
# The target voltage used in the CurrentDemandRequest.
|
||||||
|
# This is a value for first try-outs. Better would
|
||||||
|
# be if the BMS would provide the value.
|
||||||
|
# 11 * 6 * 4.1V = 66 * 4.1V = 270V
|
||||||
|
charge_target_voltage = 270
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue