CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum by 3S-Smart Software Solutions GmbH | A member of the CODESYS Group
Deutsche Version English version russian version 
It is currently Sun Oct 20, 2019 10:28 am

All times are UTC+01:00




Post new topic  Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Thu Jul 25, 2019 4:24 pm 
Offline

Joined: Sat Feb 17, 2007 5:06 pm
Posts: 34
Is the a function block that forces the values of the persistent variables to be written to the disk? I am using a Raspberry Pi which does not have a UPS. My list of persistent variables is small and change infrequently, so I can monitor the values for any changes and write the values when a change occurs.


Last edited by arj3090 on Thu Jul 25, 2019 10:15 pm, edited 1 time in total.

Top
   
PostPosted: Thu Jul 25, 2019 4:29 pm 
Offline

Joined: Mon Apr 28, 2014 7:05 pm
Posts: 97
Good question. I know there is one in TwinCAT but I am not aware of any function block to do it in Codesys. I would be interrested to know.


Top
   
PostPosted: Fri Jul 26, 2019 3:30 pm 
Offline

Joined: Sat Feb 17, 2007 5:06 pm
Posts: 34
I am guessing the requested FB does not exist, so I started creating a function block to mimc the persistent variable functionality. It requires the SysFile library. It seems kind of clunky, but works. If anyone has any improvements or better options, I am open for them. This is what I have so far
Code:
FUNCTION_BLOCK PUBLIC fbSaveMemoryBlock
VAR_INPUT
   Write : BOOL;               //Edge triggered
   Read : BOOL;               //Edge triggered
   MemLocation : POINTER TO BYTE;   // e.g ADR(%MB0)
   ByteLength : DWORD;            // byte count to monitor and store
   MinTimeBetweenWrites : TIME;   // Used to limit writing
END_VAR
VAR_OUTPUT
   WriteCount : DINT;            //Count showing number of times write was triggered
END_VAR
VAR
   LastWrite : BOOL;
   LastRead : BOOL;
   
   FileHandle : RTS_IEC_HANDLE;
   OpenResult: RTS_IEC_RESULT;
   WriteResult,ReadResult: RTS_IEC_RESULT;
   
   pCompare : POINTER TO BYTE;
   LastByteLength : DWORD;
   DifferenceFound : BOOL;
   index : DWORD;
   pWorking, pWorking2 : POINTER TO BYTE;
   FirstPass : BOOL;

   TimeBetweenWrites : TON;
END_VAR

Code:
(*********************************************************************************)
(* This function block is to provide an alternative to persitent variable values *)
(* on systems that do not have a UPS or NOVRAM                                   *)
(* CAUTION must be used because excessive writing can damage flash memory        *)
(* MemLocation is specified like ADR(%MB0)  or ADR(V1)                                      *)
(* Variable values to be saved are mapped to the block starting as specified     *)
(* by MemLocation                                                                *)
(* A method that works, but not guaranteed is to create a GVL only for the      *)
(* variables to be persisted. Use ADR(firstvar) and calculate the byte length of *)
(* all the variables in the list to use in ByteLength                            *)
(* EDIT : The method above will not work as variables are added unless a Clean All*)
(* is done to reorganize the variable memory assignments                         *)
(* The memory block values are monitored for changes which will trigger the write*)
(* The writing can be limited by using the MinTimeBetweenWrites                  *)
(* Read input can be set to TRUE to load values on first scan                    *)
(*********************************************************************************)

(******************************************************************************)
(* Read the file and store in memory - rising edge triggered                  *)
(******************************************************************************)
IF Read AND Read<>LastRead THEN
   FileHandle:=SysFileOpen('PFile.dat',SysFile.AM_READ,ADR(OpenResult));
   
   IF OpenResult=0 THEN
      SysFileRead(FileHandle,(MemLocation),ByteLength,ADR(ReadResult));
   
      SysFileClose(FileHandle);
   END_IF

   LastRead:=Read;
END_IF

(******************************************************************************)
(* Create a memory area for comparing a change in values                      *)
(******************************************************************************)
IF LastByteLength<>ByteLength THEN
   IF LastByteLength>0 THEN
      __DELETE(pCompare);
   END_IF
   
   pCompare := __NEW(BYTE,ByteLength);
   LastByteLength:=ByteLength;
END_IF

(******************************************************************************)
(* Check for a change in values                                               *)
(******************************************************************************)
// Do not set PT here so that first check occurs without delsy
TimeBetweenWrites(IN:=TRUE);
index:=0;
IF TimeBetweenWrites.Q THEN
   WHILE (index<ByteLength) DO
      pWorking:=pCompare+index;
      pWorking2:=MemLocation+index;
   
      IF (pWorking^ <> pWorking2^) THEN
         DifferenceFound:=TRUE;
         // Copy all values to working memory area for checking value chsnge
         pWorking^:=pWorking2^;
      END_IF
      
      index:=index+1;
   END_WHILE
   IF DifferenceFound THEN
      TimeBetweenWrites(IN:=FALSE,PT:=MinTimeBetweenWrites);
   END_IF
END_IF


(******************************************************************************)
(* Write Values to the file                                                   *)
(******************************************************************************)
IF (Write AND Write<>LastWrite) OR (DifferenceFound AND FirstPass) THEN
   FileHandle:=SysFileOpen('PFile.dat',SysFile.AM_WRITE,ADR(OpenResult));
   
   IF OpenResult=0 THEN
      SysFileWrite(FileHandle,(MemLocation),ByteLength,ADR(WriteResult));
   
      SysFileClose(FileHandle);
   END_IF
   
   LastWrite:=Write;
   WriteCount:=WriteCount+1;
END_IF

DifferenceFound:=FALSE;
FirstPass:=TRUE;


Last edited by arj3090 on Fri Jul 26, 2019 4:02 pm, edited 1 time in total.

Top
   
PostPosted: Fri Jul 26, 2019 3:43 pm 
Offline

Joined: Sat Feb 17, 2007 5:06 pm
Posts: 34
Here is a sample of its use:
Attachment:
SaveMemoryBlock.png


You do not have the required permissions to view the files attached to this post.


Top
   
PostPosted: Fri Jul 26, 2019 5:54 pm 
Offline

Joined: Sat Feb 17, 2007 5:06 pm
Posts: 34
With some more digging I did discover the function blocks to read and write retain variables do exist:

AppStoreRetainsInFile
AppRestoreRetainsFromFile


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 5 posts ] 

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited