GVL_CONFIG.rMaxAbsDiffVoltageModulesInString THEN _xBalanceOk := FALSE; END_IF // Test module 1 with module 3 IF ABS(_fbModule1.rCurrentVoltage - _fbModule3.rCurrentVoltage) > GVL_CONFIG.rMaxAbsDiffVoltageModulesInString THEN _xBalanceOk := FALSE; END_IF // Test module 2 with module 3 IF ABS(_fbModule2.rCurrentVoltage - _fbModule3.rCurrentVoltage) > GVL_CONFIG.rMaxAbsDiffVoltageModulesInString THEN _xBalanceOk := FALSE; END_IF // Signal an error if all units are ready and module is out of balance IF _xAllModulesReady AND (NOT _xBalanceOk) THEN xError := TRUE; END_IF // Raise error IF (NOT _xBalanceOk) AND (NOT _fbModulesOutOfBalanceAlarm.bRaised) THEN _fbModulesOutOfBalanceAlarm.Raise(0); END_IF // Clear error IF _xBalanceOk AND _fbModulesOutOfBalanceAlarm.bRaised THEN _fbModulesOutOfBalanceAlarm.Clear(0, FALSE); END_IF // Confirm error IF _fbModulesOutOfBalanceAlarm.eConfirmationState = TcEventConfirmationState.WaitForConfirmation AND xConfirmAlarms THEN _fbModulesOutOfBalanceAlarm.Confirm(0); END_IF // =============================== // String ready validation check // =============================== _tonResetPulseLength(); _tonErrorDCCBNotClosed(); CASE _iState OF 0: // Idle IF _xAllModulesReady AND _xBalanceOk AND xAllModulesInAutoMode THEN xCloseDCCB := TRUE; xResetSafetyDCCB := TRUE; _tonResetPulseLength.IN := TRUE; _iState := 10; END_IF 10: // Reset safety from sensors IF _tonResetPulseLength.Q THEN _tonResetPulseLength.IN := FALSE; xResetSafetyDCCB := FALSE; _tonErrorDCCBNotClosed.IN := TRUE; _iState := 20; END_IF 20: // Check if DC relais closed IF NOT xDCCBOpen THEN xReady := TRUE; _iState := 30; END_IF IF _tonErrorDCCBNotClosed.Q THEN _tonErrorDCCBNotClosed.IN := FALSE; xReady := FALSE; _iState := 1000; END_IF 30: // All modules ready // !!! ATTENTION !!! // BMS HAS TO SHUT DOWN THE INVERTER BEFORE DISSABLING THE STRING // OTHERWISE THE DC CIRCUIT BREAKERS WILL OPEN WHILE THE INVERTER IS STILL ACTIVE // THIS CAN DAMAGE THE INVERTER IF NOT xEnable THEN xCloseDCCB := FALSE; _iState := 0; ELSIF NOT _xAllModulesReady OR NOT _xBalanceOk THEN xError := TRUE; END_IF 1000: // Error state // Leave error state only if modules are deactivated IF NOT xEnable THEN _tonResetPulseLength.IN := FALSE; _tonErrorDCCBNotClosed.IN := FALSE; _iState := 0; END_IF END_CASE IF _xAllModulesReady AND _xBalanceOk AND (_iState = 30) THEN xReady := TRUE; ELSE xReady := FALSE; END_IF // =============================== // String status sum // =============================== IF xOff THEN eStatus := E_COMPONENT_STATUS.OFF; END_IF IF xReady THEN eStatus := E_COMPONENT_STATUS.ON; END_IF IF xError THEN eStatus := E_COMPONENT_STATUS.ERROR; END_IF]]>