mirror of
https://github.com/uhi22/pyPLC.git
synced 2024-11-10 01:05:42 +00:00
feature: prepared connector locking and safe-shutdown
This commit is contained in:
parent
837d542329
commit
6231dc5468
3 changed files with 103 additions and 21 deletions
107
fsmPev.py
107
fsmPev.py
|
@ -22,16 +22,21 @@ stateWaitForServiceDiscoveryResponse = 5
|
||||||
stateWaitForServicePaymentSelectionResponse = 6
|
stateWaitForServicePaymentSelectionResponse = 6
|
||||||
stateWaitForContractAuthenticationResponse = 7
|
stateWaitForContractAuthenticationResponse = 7
|
||||||
stateWaitForChargeParameterDiscoveryResponse = 8
|
stateWaitForChargeParameterDiscoveryResponse = 8
|
||||||
stateWaitForCableCheckResponse = 9
|
stateWaitForConnectorLock = 9
|
||||||
stateWaitForPreChargeResponse = 10
|
stateWaitForCableCheckResponse = 10
|
||||||
stateWaitForContactorsClosed = 11
|
stateWaitForPreChargeResponse = 11
|
||||||
stateWaitForPowerDeliveryResponse = 12
|
stateWaitForContactorsClosed = 12
|
||||||
stateWaitForCurrentDemandResponse = 13
|
stateWaitForPowerDeliveryResponse = 13
|
||||||
stateWaitForWeldingDetectionResponse = 14
|
stateWaitForCurrentDemandResponse = 14
|
||||||
stateWaitForSessionStopResponse = 15
|
stateWaitForWeldingDetectionResponse = 15
|
||||||
stateChargingFinished = 16
|
stateWaitForSessionStopResponse = 16
|
||||||
|
stateChargingFinished = 17
|
||||||
stateUnrecoverableError = 88
|
stateUnrecoverableError = 88
|
||||||
stateSequenceTimeout = 99
|
stateSequenceTimeout = 99
|
||||||
|
stateSafeShutDownWaitForChargerShutdown = 111
|
||||||
|
stateSafeShutDownWaitForContactorsOpen = 222
|
||||||
|
stateEnd = 1000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dinEVSEProcessingType_Finished = "0"
|
dinEVSEProcessingType_Finished = "0"
|
||||||
|
@ -79,6 +84,8 @@ class fsmPev():
|
||||||
s = "WaitForContractAuthenticationResponse"
|
s = "WaitForContractAuthenticationResponse"
|
||||||
if (statenumber == stateWaitForChargeParameterDiscoveryResponse):
|
if (statenumber == stateWaitForChargeParameterDiscoveryResponse):
|
||||||
s = "WaitForChargeParameterDiscoveryResponse"
|
s = "WaitForChargeParameterDiscoveryResponse"
|
||||||
|
if (statenumber == stateWaitForConnectorLock):
|
||||||
|
s = "WaitForConnectorLock"
|
||||||
if (statenumber == stateWaitForCableCheckResponse):
|
if (statenumber == stateWaitForCableCheckResponse):
|
||||||
s = "WaitForCableCheckResponse"
|
s = "WaitForCableCheckResponse"
|
||||||
if (statenumber == stateWaitForPreChargeResponse):
|
if (statenumber == stateWaitForPreChargeResponse):
|
||||||
|
@ -99,6 +106,12 @@ class fsmPev():
|
||||||
s = "UnrecoverableError"
|
s = "UnrecoverableError"
|
||||||
if (statenumber == stateSequenceTimeout):
|
if (statenumber == stateSequenceTimeout):
|
||||||
s = "SequenceTimeout"
|
s = "SequenceTimeout"
|
||||||
|
if (statenumber == stateSafeShutDownWaitForChargerShutdown):
|
||||||
|
s = "SafeShutDownWaitForChargerShutdown"
|
||||||
|
if (statenumber == stateSafeShutDownWaitForContactorsOpen):
|
||||||
|
s = "SafeShutDownWaitForContactorsOpen"
|
||||||
|
if (statenumber == stateEnd):
|
||||||
|
s = "End"
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def sendChargeParameterDiscoveryReq(self):
|
def sendChargeParameterDiscoveryReq(self):
|
||||||
|
@ -313,12 +326,12 @@ class fsmPev():
|
||||||
# (B) The charger finished to tell the charge parameters.
|
# (B) The charger finished to tell the charge parameters.
|
||||||
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
|
if (strConverterResult.find('"EVSEProcessing": "Finished"')>0):
|
||||||
self.publishStatus("ChargeParams discovered")
|
self.publishStatus("ChargeParams discovered")
|
||||||
self.addToTrace("Checkpoint550: It is Finished. Will change to state C and send CableCheckReq.")
|
self.addToTrace("Checkpoint550: ChargeParams are discovered. Will change to state C.")
|
||||||
# pull the CP line to state C here:
|
# pull the CP line to state C here:
|
||||||
self.hardwareInterface.setStateC()
|
self.hardwareInterface.setStateC()
|
||||||
self.sendCableCheckReq()
|
self.addToTrace("Checkpoint555: Locking the connector.")
|
||||||
self.numberOfCableCheckReq = 1 # This is the first request.
|
self.hardwareInterface.triggerConnectorLocking()
|
||||||
self.enterState(stateWaitForCableCheckResponse)
|
self.enterState(stateWaitForConnectorLock)
|
||||||
else:
|
else:
|
||||||
# Not (yet) finished.
|
# Not (yet) finished.
|
||||||
if (self.numberOfChargeParameterDiscoveryReq>=20): # approx 20 seconds, should be sufficient for the charger to find its parameters...
|
if (self.numberOfChargeParameterDiscoveryReq>=20): # approx 20 seconds, should be sufficient for the charger to find its parameters...
|
||||||
|
@ -335,6 +348,15 @@ class fsmPev():
|
||||||
if (self.isTooLong()):
|
if (self.isTooLong()):
|
||||||
self.enterState(stateSequenceTimeout)
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
|
def stateFunctionWaitForConnectorLock(self):
|
||||||
|
if (self.hardwareInterface.isConnectorLocked()):
|
||||||
|
self.addToTrace("Checkpoint560: Connector Lock confirmed. Will send CableCheckReq.")
|
||||||
|
self.sendCableCheckReq()
|
||||||
|
self.numberOfCableCheckReq = 1 # This is the first request.
|
||||||
|
self.enterState(stateWaitForCableCheckResponse)
|
||||||
|
if (self.isTooLong()):
|
||||||
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
def stateFunctionWaitForCableCheckResponse(self):
|
def stateFunctionWaitForCableCheckResponse(self):
|
||||||
if (self.cyclesInState<30): # The first second in the state just do nothing.
|
if (self.cyclesInState<30): # The first second in the state just do nothing.
|
||||||
return
|
return
|
||||||
|
@ -482,6 +504,10 @@ class fsmPev():
|
||||||
else:
|
else:
|
||||||
# We requested "OFF". So we turn-off the Relay and continue with the Welding detection.
|
# We requested "OFF". So we turn-off the Relay and continue with the Welding detection.
|
||||||
self.publishStatus("PwrDelvry OFF success")
|
self.publishStatus("PwrDelvry OFF success")
|
||||||
|
self.addToTrace("Checkpoint806: PowerDelivery Off confirmed.")
|
||||||
|
self.addToTrace("Checkpoint810: Changing CP line to State B.")
|
||||||
|
# set the CP line to B
|
||||||
|
self.hardwareInterface.setStateB()
|
||||||
self.addToTrace("Turning off the relay and starting the WeldingDetection")
|
self.addToTrace("Turning off the relay and starting the WeldingDetection")
|
||||||
self.hardwareInterface.setPowerRelayOff()
|
self.hardwareInterface.setPowerRelayOff()
|
||||||
self.hardwareInterface.setRelay2Off()
|
self.hardwareInterface.setRelay2Off()
|
||||||
|
@ -584,26 +610,63 @@ class fsmPev():
|
||||||
# Todo: close the TCP connection here.
|
# Todo: close the TCP connection here.
|
||||||
# Todo: Unlock the connector lock.
|
# Todo: Unlock the connector lock.
|
||||||
self.publishStatus("Stopped normally")
|
self.publishStatus("Stopped normally")
|
||||||
self.hardwareInterface.setStateB()
|
|
||||||
self.addToTrace("Charging is finished")
|
self.addToTrace("Charging is finished")
|
||||||
self.enterState(stateChargingFinished)
|
self.enterState(stateChargingFinished)
|
||||||
if (self.isTooLong()):
|
if (self.isTooLong()):
|
||||||
self.enterState(stateSequenceTimeout)
|
self.enterState(stateSequenceTimeout)
|
||||||
|
|
||||||
def stateFunctionChargingFinished(self):
|
def stateFunctionChargingFinished(self):
|
||||||
# charging is finished. Nothing to do. Just stay here, until we get re-initialized after a new SLAC/SDP.
|
# charging is finished.
|
||||||
pass
|
# Finally unlock the connector
|
||||||
|
self.addToTrace("Charging successfully finished. Unlocking the connector")
|
||||||
|
self.hardwareInterface.triggerConnectorUnlocking()
|
||||||
|
self.enterState(stateEnd)
|
||||||
|
|
||||||
def stateFunctionSequenceTimeout(self):
|
def stateFunctionSequenceTimeout(self):
|
||||||
# Here we end, if we run into a timeout in the state machine. This is an error case, and
|
# Here we end, if we run into a timeout in the state machine.
|
||||||
# an end of the PEV state machine. The re-initialization is performed by the
|
|
||||||
# lower layers SLAC, SDP, together with the connection manager. Nothing to do here.
|
|
||||||
self.publishStatus("ERROR Timeout")
|
self.publishStatus("ERROR Timeout")
|
||||||
|
# Initiate the safe-shutdown-sequence.
|
||||||
|
self.addToTrace("Safe-shutdown-sequence: setting state B")
|
||||||
|
self.hardwareInterface.setStateB() # setting CP line to B disables in the charger the current flow.
|
||||||
|
self.DelayCycles = 66 # 66*30ms=2s for charger shutdown
|
||||||
|
self.enterState(stateSafeShutDownWaitForChargerShutdown)
|
||||||
|
|
||||||
def stateFunctionUnrecoverableError(self):
|
def stateFunctionUnrecoverableError(self):
|
||||||
# Here we end, if the EVSE reported an error code, which terminates the charging session.
|
# Here we end, if the EVSE reported an error code, which terminates the charging session.
|
||||||
# This is an end of the PEV state machine. The re-init is performed by the lower layers. Nothing more to do here.
|
|
||||||
self.publishStatus("ERROR reported")
|
self.publishStatus("ERROR reported")
|
||||||
|
# Initiate the safe-shutdown-sequence.
|
||||||
|
self.addToTrace("Safe-shutdown-sequence: setting state B")
|
||||||
|
self.hardwareInterface.setStateB() # setting CP line to B disables in the charger the current flow.
|
||||||
|
self.DelayCycles = 66 # 66*30ms=2s for charger shutdown
|
||||||
|
self.enterState(stateSafeShutDownWaitForChargerShutdown)
|
||||||
|
|
||||||
|
def stateFunctionSafeShutDownWaitForChargerShutdown(self):
|
||||||
|
# wait state, to give the charger the time to stop the current.
|
||||||
|
if (self.DelayCycles>0):
|
||||||
|
self.DelayCycles-=1
|
||||||
|
return
|
||||||
|
# Now the current flow is stopped by the charger. We can safely open the contactors:
|
||||||
|
self.addToTrace("Safe-shutdown-sequence: opening contactors")
|
||||||
|
self.hardwareInterface.setPowerRelayOff()
|
||||||
|
self.hardwareInterface.setRelay2Off()
|
||||||
|
self.DelayCycles = 33 # 33*30ms=1s for opening the contactors
|
||||||
|
self.enterState(stateSafeShutDownWaitForContactorsOpen)
|
||||||
|
|
||||||
|
def stateFunctionSafeShutDownWaitForContactorsOpen(self):
|
||||||
|
# wait state, to give the contactors the time to open.
|
||||||
|
if (self.DelayCycles>0):
|
||||||
|
self.DelayCycles-=1
|
||||||
|
return
|
||||||
|
# Finally, when we have no current and no voltage, unlock the connector
|
||||||
|
self.addToTrace("Safe-shutdown-sequence: unlocking the connector")
|
||||||
|
self.hardwareInterface.triggerConnectorUnlocking()
|
||||||
|
# This is the end of the safe-shutdown-sequence.
|
||||||
|
self.enterState(stateEnd)
|
||||||
|
|
||||||
|
def stateFunctionEnd(self):
|
||||||
|
# Just stay here, until we get re-initialized after a new SLAC/SDP.
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
stateFunctions = {
|
stateFunctions = {
|
||||||
stateNotYetInitialized: stateFunctionNotYetInitialized,
|
stateNotYetInitialized: stateFunctionNotYetInitialized,
|
||||||
|
@ -615,6 +678,7 @@ class fsmPev():
|
||||||
stateWaitForServicePaymentSelectionResponse: stateFunctionWaitForServicePaymentSelectionResponse,
|
stateWaitForServicePaymentSelectionResponse: stateFunctionWaitForServicePaymentSelectionResponse,
|
||||||
stateWaitForContractAuthenticationResponse: stateFunctionWaitForContractAuthenticationResponse,
|
stateWaitForContractAuthenticationResponse: stateFunctionWaitForContractAuthenticationResponse,
|
||||||
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
stateWaitForChargeParameterDiscoveryResponse: stateFunctionWaitForChargeParameterDiscoveryResponse,
|
||||||
|
stateWaitForConnectorLock: stateFunctionWaitForConnectorLock,
|
||||||
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
stateWaitForCableCheckResponse: stateFunctionWaitForCableCheckResponse,
|
||||||
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
stateWaitForPreChargeResponse: stateFunctionWaitForPreChargeResponse,
|
||||||
stateWaitForContactorsClosed: stateFunctionWaitForContactorsClosed,
|
stateWaitForContactorsClosed: stateFunctionWaitForContactorsClosed,
|
||||||
|
@ -624,7 +688,10 @@ class fsmPev():
|
||||||
stateWaitForSessionStopResponse: stateFunctionWaitForSessionStopResponse,
|
stateWaitForSessionStopResponse: stateFunctionWaitForSessionStopResponse,
|
||||||
stateChargingFinished: stateFunctionChargingFinished,
|
stateChargingFinished: stateFunctionChargingFinished,
|
||||||
stateUnrecoverableError: stateFunctionUnrecoverableError,
|
stateUnrecoverableError: stateFunctionUnrecoverableError,
|
||||||
stateSequenceTimeout: stateFunctionSequenceTimeout
|
stateSequenceTimeout: stateFunctionSequenceTimeout,
|
||||||
|
stateSafeShutDownWaitForChargerShutdown: stateFunctionSafeShutDownWaitForChargerShutdown,
|
||||||
|
stateSafeShutDownWaitForContactorsOpen: stateFunctionSafeShutDownWaitForContactorsOpen,
|
||||||
|
stateEnd: stateFunctionEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
def stopCharging(self):
|
def stopCharging(self):
|
||||||
|
|
|
@ -92,6 +92,17 @@ class hardwareInterface():
|
||||||
def getPowerRelayConfirmation(self):
|
def getPowerRelayConfirmation(self):
|
||||||
return 1 # todo: self.contactor_confirmed
|
return 1 # todo: self.contactor_confirmed
|
||||||
|
|
||||||
|
def triggerConnectorLocking(self):
|
||||||
|
self.addToTrace("Locking the connector")
|
||||||
|
# todo control the lock motor into lock direction until the end (time based or current based stopping?)
|
||||||
|
|
||||||
|
def triggerConnectorUnlocking(self):
|
||||||
|
self.addToTrace("Unocking the connector")
|
||||||
|
# todo control the lock motor into unlock direction until the end (time based or current based stopping?)
|
||||||
|
|
||||||
|
def isConnectorLocked(self):
|
||||||
|
return 1 # todo: use the real connector lock feedback
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -311,6 +311,8 @@ DC or AC and which power pins are used. The car announces the maximum current li
|
||||||
* Checkpoint545: The charger confirms with ChargeParameterResponse. The contains the limits from charger side, e.g. min and max voltage,
|
* Checkpoint545: The charger confirms with ChargeParameterResponse. The contains the limits from charger side, e.g. min and max voltage,
|
||||||
min and max current. Now, the initialization phase of the charging session is finished.
|
min and max current. Now, the initialization phase of the charging session is finished.
|
||||||
* Checkpoint550: The car changes to CP State to C or D, by applying an additional resistor between CP and ground.
|
* Checkpoint550: The car changes to CP State to C or D, by applying an additional resistor between CP and ground.
|
||||||
|
* Checkpoint555: The car controls the connector lock motor into direction 'lock'.
|
||||||
|
* Checkpoint556: The car checks whether the connector lock is confirmed.
|
||||||
* Checkpoint560: The car sends CableCheckRequest. This contains the information, whether the connector is locked.
|
* Checkpoint560: The car sends CableCheckRequest. This contains the information, whether the connector is locked.
|
||||||
* Checkpoint561: The charger applies voltage to the cable and measures the isolation resistance.
|
* Checkpoint561: The charger applies voltage to the cable and measures the isolation resistance.
|
||||||
* Checkpoint565: The charger confirms with CableCheckResponse.
|
* Checkpoint565: The charger confirms with CableCheckResponse.
|
||||||
|
@ -333,6 +335,8 @@ is active (current limitation, voltage limitation, power limitation).
|
||||||
* Checkpoint710: The CurrentDemandRequest/CurrentDemandResponse are repeated during the charging.
|
* Checkpoint710: The CurrentDemandRequest/CurrentDemandResponse are repeated during the charging.
|
||||||
* Checkpoint800: When the end of charging is decided (battery full or user wish), the car sends PowerDelivery(Stop)Request.
|
* Checkpoint800: When the end of charging is decided (battery full or user wish), the car sends PowerDelivery(Stop)Request.
|
||||||
* Checkpoint805: The charger confirms with PowerDeliveryResponse.
|
* Checkpoint805: The charger confirms with PowerDeliveryResponse.
|
||||||
|
* Checkpoint806: The car receives the PowerDeliveryResponse.
|
||||||
|
* Checkpoint810: The car changes the CP line from StateC to StateB. (according to Figure 107)
|
||||||
* Checkpoint850: The car sends WeldingDetectionRequest.
|
* Checkpoint850: The car sends WeldingDetectionRequest.
|
||||||
* Checkpoint855: The charger confirms with WeldingDetectionResponse.
|
* Checkpoint855: The charger confirms with WeldingDetectionResponse.
|
||||||
* Checkpoint900: The car sends SessionStopRequest.
|
* Checkpoint900: The car sends SessionStopRequest.
|
||||||
|
|
Loading…
Reference in a new issue