OSCAT Forum

Home Automation => SPS-Programmierung => Thema gestartet von: dawrut am 28. April 2021, 22:44:27

Titel: Save blind position in case of power failure
Beitrag von: dawrut am 28. April 2021, 22:44:27
How are you saving the position of the blind in case of a power failure?

Function BLIND_CONTROL_S has built-in automatic calibration which is needed to know the position of the blind in case of power failure or PLC restart. In such a case, the blind goes up. Is there a way to store the current position so that after the power failure the blind won't go up?
I was trying to add the whole BLIND_CONTROL_S  function block to the VAR RETAIN PERSISTENT memory area but this didn't help. I was also trying to store the POS output of the BLIND_CONTROL_S (which is the input for the POS of the BLIND_INPUT) but this also doesn't stop blinds to go up in case of power failure.

Any ideas?
Titel: Re: Save blind position in case of power failure
Beitrag von: dawrut am 30. April 2021, 09:50:31
I started to do small POC, I almost finish coding and what I have is:

The code looks like this (without sunset and sunrise calculation code):

FUNCTION_BLOCK Blind
VAR_INPUT
    xBlindDown: BOOL;
    xBlindUp: BOOL;
    xAutoSunset: BOOL := FALSE;
    xAutoSunrise: BOOL := FALSE;
    tMaxRuntime: TIME := T#32S;
    tTimeUp: TIME := T#30S;
    tTimeDown: TIME := T#30S;


END_VAR
VAR_OUTPUT
    xBlindControlUp: BOOL;
    xBlindControlDown: BOOL;
END_VAR
VAR_IN_OUT
    PersistentData: BlindData; //this data is stored in VAR RETAIN PERSISTENT in the PLC_PRG
END_VAR
VAR
    _oBlindInput: OSCAT_BUILDING.BLIND_INPUT := (MAX_RUNTIME := tMaxRuntime, MANUAL_TIMEOUT := T#2M);
    _oBlindNight: OSCAT_BUILDING.BLIND_NIGHT;
    _oBlindSecurity: OSCAT_BUILDING.BLIND_SECURITY;
    _oBlindControl: OSCAT_BUILDING.BLIND_CONTROL_S;   
    _xInitPosition: BOOL := FALSE;
    _byBlindControlPosition: BYTE;
    _calibrationBlocker: TON;
    _xMasterMode: BOOL := FALSE;       
END_VAR

_calibrationBlocker(IN := TRUE, PT := T#90S);


_oBlindInput(
    POS:= PersistentData.byCurrentPosition,
    S1:= xBlindUp,
    S2:= xBlindDown,
    MASTER_MODE := _xMasterMode
);


_oBlindNight(
    UP := _oBlindInput.QU,
    DN := _oBlindInput.QD,
    S_IN := _oBlindInput.STATUS,
    PI := _oBlindInput.PO,
    DTIN := _dtCurrentDateTimeUTC,
    SUNRISE := _oSunTime.SUN_RISE,
    SUNSET := _oSunTime.SUN_SET,
    E_NIGHT := xAutoSunset,
    E_DAY := xAutoSunrise
);


_oBlindSecurity(
    UP := _oBlindNight.QU,
    DN := _oBlindNight.QD,
    S_IN := _oBlindNight.STATUS,
    PI := _oBlindNight.PO,
);


IF (NOT _xInitPosition) THEN
    // in the first cycle lets read last position saved before the power failure and set it to _oBlindControl PI input
    // this will casue the _oBlindControl to move to last position after calibration
    // we are reading the position only onece - in the first cycle after the power is back
    _byBlindControlPosition := PersistentData.byCurrentPosition;
END_IF


IF (_calibrationBlocker.Q) THEN
    // then, after calibration, just read the position from previous block (standard behaviour)
    _byBlindControlPosition := _oBlindSecurity.PO;
   
    // switch master mode back to true, initially it is false because we need to transfer PersistentData.byCurrentPosition change to all
    // the block (when the _oBlindControl is calibrating)   
    _xMasterMode := TRUE;
END_IF


_xInitPosition := TRUE;


_oBlindControl(
    T_UP := tTimeUp,
    T_DN := tTimeDown,
    UP := _oBlindSecurity.QU,
    DN := _oBlindSecurity.QD,
    S_IN := _oBlindSecurity.STATUS,
    PI := _byBlindControlPosition,
    POS => PersistentData.byCurrentPosition
);


// set outputs after the calibration (when _calibrationBlocker.Q is TRUE after 90 seconds)
// we don't need real calibration as we are saving last know position (before the power failure/full download) in PersistentData.byCurrentPosition
xBlindControlDown := _oBlindControl.MD AND _calibrationBlocker.Q;
xBlindControlUp := _oBlindControl.MU AND _calibrationBlocker.Q;

What I have is:

I Will be doing some real testing today but so far it looks good in the simulation model.

Is the MASTER_MODE := TRUE actually needed in the BLIND_INPUT? What it actually does?


Any other ideas? Other approaches?