Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Raspberry retain variables

switcher
2014-04-22
2022-10-22
1 2 3 > >> (Page 1 of 3)
  • switcher - 2014-04-22

    Hi,

    Is it possible to configure some variables to keep their values also within the power failure?
    I tried with RETAIN var declaration, but it seems that not working.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-04-22

    Hi Zdenko,
    Technical two solutions are possible.
    Either a non volatile ram hardware (nvram) is needed (not available on the pi - as i know)
    or you need to have a working UPS (uninterruptable power supply) connected
    to the pi.
    Then the runtime store the retain data to a file on exit of Linux (a graceful shutdown is needed) and restore them
    on restart.
    So without additional hardware there is a 'no' on that question.
    BR
    Edwin

     
  • switcher - 2014-04-23

    Thank you Edwin,

    Yes, there is no NV RAM integrated in Rpi.
    I just like to save some setpoints, which are not changed frequently.
    I am thinking about the possibility to save this variables on SD card. For example, every hour a routine can check if some variable in specific variable set (as retain variable set) is different that one store in the SD card. And if there are some variables with different values, this variables will be overwritten on SD card. Is this possible solution? Some example how to do this will be great.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-05-21

    Hi Zdenko,

    attached an example to realize a manual save of the retain variables.
    Take care cyclic writing on the SD Card could damage the filesystem especially if you switch off the system while writing to files. (graceful shutdown is needed on Linux side...)

    BR
    Edwin

    SaveRetainsManually_Pi.projectarchive [5.58 MiB]

     
  • switcher - 2014-05-27

    Thank you Edwin,

    in the meantime, I managed to save some data in the file and read back .

    But I am very interesting in your solution, I am sure it is better.
    Unfortunately I don't understand it completely . Can you please explain the solution more detailed, including this declaration:
    Result : RTS_IEC_RESULT; ( Result code )

    Best regards,
    Zdenko.

     
  • switcher - 2014-11-06

    Hi Edwin,

    I managed to made more tests with your above example. I changed default value bRestore := TRUE; - to make load saved retain values at startup.
    In some cases, it seems to work fine, but mostly don’t work.
    The procedure I am using:
    -Login
    -Change some retain variables values
    - xSave set to TRUE to save values in file. No error appears and everything seems to be ok. If I set bit bRestore, I get right saved values.
    -Logout, power OFF Raspberry, Power ON Raspberry
    -Login and check the retain variables. Sometimes the values are ok (saved values), but in most cases they are not. Even if I set bRestore, I don’t get the right values.

    I am asking you if you can check this situation with your Raspberry. I am using B+ and Codesys V3.5 SP5 Patch 2.

    Here is the code:
    PROGRAM AppRetain
    VAR
    fbDelete : FILE.Delete; ( Function block to delete the file )
    ( The retain file <application-name>.ret is placed in the directory of the bootproject </application-name>)
    sFileName : STRING := 'App1.ret';
    pApp : POINTER TO APPLICATION;
    Result : RTS_IEC_RESULT; ( Result code )
    xInit : BOOL;
    xSave : BOOL;
    bRestore : BOOL := TRUE;
    END_VAR[/code]

    (* The retain variables are stores in a file and get retrieved afterwards. *)
    IF NOT xInit THEN
       pApp := AppGetCurrent(pResult:=ADR(Result));
       xInit := TRUE;
    END_IF
    IF xSave THEN   
       (* First delete the retain file.
          This is necessary, because the function AppStoreRetainsInFile appends the data at the end of the file. *)
       fbDelete(xExecute:=TRUE, sFileName:=sFileName);
       IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = File.Error.NOT_EXIST) THEN
          (* Attention: It takes at least one cycle until xDone is TRUE *)
          fbDelete(xExecute:=FALSE);
          xSave := FALSE;
          (* Now, it's the time to save the retains. *)
          IF pApp <> 0 THEN
             (* Store the variables in a file*)
             Result := AppStoreRetainsInFile(pApp,sFileName);
          END_IF
       END_IF
    END_IF
    (* Restore the Retain Variables from the file.
       For storing and restoring, the same pointer to application (pApp) must be used.*)
    IF bRestore THEN
       Result := AppRestoreRetainsFromFile(pApp, sFileName);
       bRestore := FALSE;
    END_IF
    

    I noticed that when variables are not read sucessfully from file after reboot I get the RTS_IEC_RESULT = 30, otherwise is result=0.

    After some further tests I noticed that if I shut down Raspberry with sudo shutdown, then variables are successfully restored after power ON.
    If I just plug off power supply, then restore from file fails. How can we make this work even if the raspberry is not shut down with the graceful shutdown?

    Thank you!
    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-11-11

    Hi Zdenko,

    maybe I confused you with the example, because in that case is maybe a mixture of the runtime/save the retains
    by the system (this is the case for plc's which have NVRAM or UPS - in your case the pi has none of that) - you know usually you
    do not need to save anything from the application, this is all served by the runtime.
    Now we have maybe a mixture of this - Runtime System save and restore retains and application save and restore them manually triggered.

    I think the problem might be that you use App1.ret for the Retain file and your CODESYS Application is called App1 too?
    Is that the the case in your application?

    I think you need to change the retain file name,
    and make sure on every restart you restore them by the application.
    Hope this solves your problem.

    BR
    Edwin

     
  • switcher - 2014-11-11

    Hi Edwin,

    thank you!

    Yes, you are right Edwin, it seems to be a mixture of both.

    Firstly I changed the name of Retain file, that the name of app is different from the file name. But the problem stays the same.

    It looks that runtime and application uses the same file for storing retain variables.
    If I change some values of retain variables, after graceful shutdown and re-power-on all variables are restored automatically, without manually save them and without application (Manually) restore! And the result is the same if I use manually save/restore with application.
    So if I graceful shutdown Raspberry everything is ok. But If I shut down Raspberry with removing supply connector – in this case don’t work runtime and also don’t work restore with application.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-11-11

    Hi Zdenko,

    so your solution should be use a unique name for the retains file

    sFileName           : STRING := 'App1my.ret';
    

    after that you have everything under control (except that the runtime save a second file on an graceful shutdown and restore
    a retain file after restart)
    but if you restore your retains (from your file) from your application you know the right point / application state to do this,
    this should work.

    I think this should help you, if not please let me know.

    BR
    Edwin

     
  • switcher - 2014-11-11

    Edwin thanks!

    I checked that restore with runtime works automatically, no application code is needed. But if the shutdown is not graceful, this doesn’t work. Because of this, we have to store retains within the application.

    Like I said, I gave custom file name for application. I am using this file name:

    sFileName           : STRING := 'VarRet.ret';
    

    I am using the above code to store/restore Retain variables. Unfortunately also with this procedure restore Retain variables doesn’t work if Raspberry shutdown is not graceful. It works from time to time (Maybe 1 time from 20 attempts). I checked - I can store variables in this custom file and after this I can read variables from this file in application. But after direct power off, restore mostly don’t work.
    Because of this, I am still looking for a reliable method to restore retain variables. It must works also with the direct power off.
    Edwin, I am asking you if you can check this on your side.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-11-11

    Hi Zdenko,

    what Is your trigger to save the retains from application?

    BR
    Edwin

     
  • switcher - 2014-11-11

    Edwin, I do this manual in online mode.

    Save retains in file: Manual change xSave bit to TRUE.
    Restore retains from file: Manual change bRestore bit to TRUE.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-11-11

    ok will check this...!
    BR
    Edwin

     
  • switcher - 2014-11-12

    Hi Edwin,

    I made some further tests.

    I can copy created restore file in application to for example /home/pi directory and I can open this file in Nano terminal editor. I can also open/close this file in application. The content of this file is the same also after non-graceful shutdown.

    But the problem is with function AppRestoreRetainsFromFile, which don't restore Retain variables after non-graceful shutdown. I think there must be something included in file that indicate non-graceful shutdown and function AppRestoreRetainsFromFile dont't restore variables in this case.

    Best regards,
    Zdenko.

     
  • eschwellinger

    eschwellinger - 2014-11-12

    Hi Zdenko,

    I see the problem... give me some time to give an advice or an update or whatever.

    BR
    Edwin

     
  • eschwellinger

    eschwellinger - 2014-11-19

    Hello,

    this 'manual retain save issue' will be solved with 3.5SP6,
    there is a workaround available:
    Execute a 'sync' by >Zitat:
    Sys ExecuteCommand
    after saving the retains manually.
    This lead to a file flush.. retains are saved immediately.

    This will be not needed then with 3.5SP6 release.

    BR
    Edwin

     
  • sallos - 2014-11-24

    Hi,

    can you help me my code don't work:

    IF Save THEN
       
       (* First delete the retain file.
          This is necessary, because the function AppStoreRetainsInFile appends the data at the end of the file. *)
       fbDelete(xExecute:=TRUE, sFileName:=sFileName);
       IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = File.Error.NOT_EXIST) THEN
          (* Attention: It takes at least one cycle until xDone is TRUE *)
          fbDelete(xExecute:=FALSE);
          Save := FALSE;
          (* Now, it's the time to save the retains. *)
          pApp := AppGetCurrent(pResult:=ADR(Result));
          IF pApp <> 0 THEN
             (* Store the variables in a file*)
             Result := AppStoreRetainsInFile(pApp,sFileName);
             _(pszCommand:='sync');
             
          END_IF
       END_IF
    END_IF
    (* Restore the Retain Variables from the file.
       For storing and restoring, the same pointer to application (pApp) must be used.*)
    IF Restore THEN
       Result := AppRestoreRetainsFromFile(pApp, sFileName);
       Restore := FALSE;
    END_IF
    

    I can restore the retain, after a power fail.

     
  • switcher - 2014-11-26

    Hi,

    It is working in my case:

    PROGRAM AppRetain
    VAR
       fbDelete            : FILE.Delete; (* Function block to delete the file *)
        (* The retain file <application-name>.ret is placed in the directory of the bootproject *)
       sFileName           : STRING := 'App10.ret';
       pApp            : POINTER TO APPLICATION;
       Result              : RTS_IEC_RESULT; (* Result code *)
       Result1             : RTS_IEC_RESULT; (* Result code *)
       xInit            : BOOL;
    END_VAR
    
    IF NOT xInit THEN
       pApp := AppGetCurrent(pResult:=ADR(Result));
       xInit := TRUE;
    END_IF
    IF xSavePers THEN   
       (* First delete the retain file.
          This is necessary, because the function AppStoreRetainsInFile appends the data at the end of the file. *)
       fbDelete(xExecute:=TRUE, sFileName:=sFileName);
       IF fbDelete.xDone OR (fbDelete.xError AND fbDelete.eError = File.Error.NOT_EXIST) THEN
          (* Attention: It takes at least one cycle until xDone is TRUE *)
          fbDelete(xExecute:=FALSE);
          xSavePers := FALSE;
          (* Now, it's the time to save the retains. *)
          IF pApp <> 0 THEN
             (* Store the variables in a file*)
             Result := AppStoreRetainsInFile(pApp,sFileName);
             SysProcess._('sync',ADR(Result1));
          END_IF
       END_IF
    END_IF
    (* Restore the Retain Variables from the file.
       For storing and restoring, the same pointer to application (pApp) must be used.*)
    IF bRestore THEN
       Result := AppRestoreRetainsFromFile(pApp, sFileName);
       PersVarsChk := PersVars;
       bRestore := FALSE;
    END_IF
    

    And you should add "sync" command in CODESYSControl.cfg, like described here:
    l viewtopic.php?f=21&t=5714 l

    Best regards,
    Zdenko.

     
  • sallos - 2014-11-27

    Hi thanks...but after this stop the Raspi...wen i will restore the RETAIN

     
  • switcher - 2014-11-28

    Hi,

    I configured xSavePers and bRestore control bits as Global variables, so I can save and restore Retain variables from the application.

    Restore is made in the INIT phase and Save is done after Retain variables value change.

    Best regards,
    Zdenko.

     
  • AlexB - 2014-12-12

    My small code for autosave retain on change with time filter (no raspberry!, another platform). As is.

    • CmpChecksum.lib
    PROGRAM RetainManager
    VAR_INPUT
       RetainFilePathName : STRING := '/tmp/extend/pccard/SD_MMC0_1/Retain';
       SaveFilterTime : TIME := T#5S;
       ForceSave : BOOL;
    END_VAR
    VAR
       Init: BOOL;
       pRetainFilePathName : POINTER TO STRING;
       pCurrentApp : POINTER TO APPLICATION;
       RetainAreaSize: __XWORD;
       pRetainArea: POINTER TO BYTE;
       dwCRCSave: DWORD;
       dwCRC: DWORD;
       TOF1 : TOF := (PT := SaveFilterTime);
       R_TRIG1: R_TRIG;
    END_VAR
    VAR_OUTPUT
       RTSIECResult : RTS_IEC_RESULT;   
       AttemptSaveCounter: INT;
    END_VAR
    IF NOT Init THEN
       pCurrentApp := AppGetCurrent(ADR(RTSIECResult));
       IF RTSIECResult<>0 THEN RETURN; END_IF
       RetainAreaSize := AppGetAreaSize(pApp:= pCurrentApp, uiType:= DA_RETAIN, pResult:= ADR(RTSIECResult));
       IF RTSIECResult<>0 THEN RETURN; END_IF
       pRetainArea := AppGetAreaAddress(pApp:= pCurrentApp, uiType:= DA_RETAIN, pResult:= ADR(RTSIECResult));
       IF RTSIECResult<>0 THEN RETURN; END_IF
       IF LEN(RetainFilePathName) <> 0 THEN
          pRetainFilePathName := ADR(RetainFilePathName);
       ELSE
          pRetainFilePathName := ADR(pCurrentApp^.szName);   
       END_IF
       RTSIECResult := AppRestoreRetainsFromFile(pCurrentApp, pRetainFilePathName^);   
       CASE RTSIECResult OF
          0: // #define ERR_OK 0x0000
          16#1E: // #define ERR_SIGNATURE_MISMATCH 0x001E   /* Signature mismatch of an api function */
          16#32: // #define ERR_FILE_ERROR 0x0032   /* File error. e.g. cannot open a file for writing because it could be write protected */
       ELSE RETURN;
       END_CASE
       dwCRCSave := CRC32Finish(ulCRC:= CRC32Update(ulCRC:= CRC32Init(), pData:= pRetainArea, ulSize:= RetainAreaSize));
       Init := TRUE;   
    END_IF
    R_TRIG1(CLK := ForceSave);
    dwCRC := CRC32Finish(ulCRC:= CRC32Update(ulCRC:= CRC32Init(), pData:= pRetainArea, ulSize:= RetainAreaSize));
    IF dwCRC <> dwCRCSave OR R_TRIG1.Q THEN
       IF NOT TOF1.Q OR R_TRIG1.Q THEN
          RTSIECResult := AppStoreRetainsInFile(pCurrentApp, pRetainFilePathName^); // записасать в файл
          IF RTSIECResult = 0 THEN
             dwCRCSave := dwCRC;         
          END_IF
          AttemptSaveCounter := AttemptSaveCounter + 1;
          TOF1(IN := TRUE);
       END_IF
    END_IF
    IF TOF1.Q THEN
       TOF1(IN := FALSE);
    END_IF
    
     
  • kruglovay - 2015-11-20

    Edwin Schwellinger hat geschrieben:
    This will be not needed then with 3.5SP6 release.

    Hello Edwin.
    What does it mean?
    I tried retains in 3.5sp7 and it still doesn't work.

     
  • eschwellinger

    eschwellinger - 2015-11-21

    Hi,
    usually nothing is needed except an UPS... no additional code to execute.

    BR
    Edwin

     
  • kruglovay - 2015-11-21

    So the problem with manual saving retains to sd card isn't solved?
    And the only way to have retains saved without additional code is unterruptable power supply?

     
  • Ledrunner - 2015-12-24

    Hi everyone! Has anyone used 24C32(64) EEPROM chip to saving retain variables? Is it possible? I have this part: http://www.ebay.com/itm/400503978923 m

     
1 2 3 > >> (Page 1 of 3)

Log in to post a comment.