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 Feb 17, 2019 11:25 am

All times are UTC+01:00




Post new topic  Reply to topic  [ 12 posts ] 
Author Message
 Post subject: POINTERs
PostPosted: Wed Jan 23, 2019 7:07 pm 
Offline

Joined: Sun Jun 28, 2015 12:23 pm
Posts: 77
Hello
I have a GlobalVariable table with just BOOLs.
I'd like to loop through each BOOL. The list will change as the application develops, so I was hoping to make a pointer to the first VAR and a pointer to the last VAR and loop through them.
I think the ADR() of the VAR is not based on the position in the table though, rather the order they are added.
Is there a technique to look at all the VARs in a table?

I know I could make an ARRAY of BOOL, but I have my reasons to keep them as individual vars.
Thanks


Top
   
 Post subject: Re: POINTERs
PostPosted: Wed Jan 23, 2019 7:57 pm 
Offline
Frequent User
Frequent User

Joined: Tue Dec 03, 2013 11:52 pm
Posts: 106
It might be possible the way you are describing but I have always used a structure to hold something like that. For example:

Your structure would look like this and can be expanded as needed.
Code:
TYPE TABLEBOOLS
STRUCT
    xBool1        :    BOOL;
    xBool2        :    BOOL;
    xBool3        :    BOOL;
    ......
END_STRUCT
END_TYPE


If you want to use a GVL you can declare it like:
Code:
VAR_GLOBAL
//Define global variable
    structTABLEBOOLS        :    TABLEBOOLS;
END_VAR


Then to loop through the structure you would do:
Code:
VAR
    iCount        :    BOOL;
    pLocation    :    POINTER TO BOOL;
    pAdjustedLocation    :    POINTER TO BOOL;
    xValue        :    BOOL;
END_VAR

//Get address of structure
    pLocation := ADR(GVL.structTABLEBOOLS);
   
//Loop through structure and store each value in xValue
    FOR iCount := 0 TO (SIZEOF(GVL.structTABLEBOOLS)-1) BY 1 DO
        pAdjustedLocation := pLocation + INT_TO_DWORD(iCount);    //This changes the pointers location.
        xValue := pAdjustedLocation^;    //This would give you the value of each bool as it iterates through the structure.
    END_FOR


If you have different data types besides BOOL/BIT this method would not work. There would need to be more checking done for iterating through it properly.


Top
   
 Post subject: Re: POINTERs
PostPosted: Wed Jan 23, 2019 9:23 pm 
Offline

Joined: Sun Jun 28, 2015 12:23 pm
Posts: 77
Thanks ComingBack4U.
I like that idea :D


Top
   
 Post subject: Re: POINTERs
PostPosted: Thu Jan 24, 2019 3:55 am 
Offline

Joined: Mon Oct 01, 2012 8:33 am
Posts: 48
@Comingback4u's method is platform/compiler dependent. Struct members are not necessarily packed in a contiguous manner on all CPU architectures.


Top
   
 Post subject: Re: POINTERs
PostPosted: Thu Jan 24, 2019 3:14 pm 
Offline
Frequent User
Frequent User

Joined: Fri Feb 23, 2018 3:41 pm
Posts: 100
Why not using an array with a constant defining the length ?
Then access may be done by an ENUM, defining each value your array index may take.

For instance,
Code:
VAR_GLOBAL
   MyBool : ARRAY [1..Const._MAXVALUE] OF BOOL;
END_VAR

Code:
TYPE MyBools_ENUM :
(
   First := 0,
   Second:= 1,
   Third:= 2,
   WhatEver := 3
) UINT;
END_TYPE

Then usage is in a loop, as a standard array or this way :
Code:
MyBool[MyBools_ENUM.WhatEver] := 99;


Top
   
 Post subject: Re: POINTERs
PostPosted: Thu Jan 24, 2019 6:10 pm 
Offline
User avatar

Joined: Tue Aug 30, 2011 1:21 am
Posts: 96
First understand Codesys treats bools as one byte. So you can not pack the bits unless you locate them to physical memory. I already have many post on this so I will not repeat it here.

Also Codesys does not allow for array of pointers or references but here is work around by making an array of structures with the pointer or reference. I prefer references because you do not have to keep dereferencing them like pointers. See Example below that will the number of on bools.

Code:
TYPE DUT_REF :
STRUCT
   xBool: REFERENCE TO BOOL;
END_STRUCT
END_TYPE

Code:
PROGRAM TEST
VAR
   myref: ARRAY[0..7] OF DUT_REF;
   BIT00: BOOL;
   BIT01: BOOL;
   BIT02: BOOL;
   BIT03: BOOL;
   BIT04: BOOL;
   BIT05: BOOL;
   BIT06: BOOL;
   BIT07: BOOL;
   i: INT;
   num_of_on: UINT;
END_VAR

Code:
myref[0].xBool REF= BIT00;
myref[1].xBool REF= BIT01;
myref[2].xBool REF= BIT02;
myref[3].xBool REF= BIT03;
myref[4].xBool REF= BIT04;
myref[5].xBool REF= BIT05;
myref[6].xBool REF= BIT06;
myref[7].xBool REF= BIT07;

BIT00:=TRUE;
BIT06:=TRUE;
BIT07:=TRUE;

num_of_on:=0;
FOR i:=0 TO SIZEOF(myref)/SIZEOF(DUT_REF)-1 DO
   IF __ISVALIDREF(myref[i].xBool) THEN
      IF(myref[i].xBool) THEN
         num_of_on:=num_of_on+1;
      END_IF   
   END_IF
END_FOR;

_________________
The Original SoMachine Ninja


Top
   
 Post subject: Re: POINTERs
PostPosted: Thu Jan 24, 2019 9:20 pm 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 297
Please take care with pointer and reference assumptions - as was warned by others regarding memory locations! The following screenshots show issues in the idea that a list of BOOLs will be where you expect them:

This was at first build and download - note the huge gap between Bool1 and Bool2 (so reading one memory location after Bool1 would be complete garbage!):
Attachment:
pointer-gap.png


This was after I added another BOOL and performed an online change - notice Bool3 is spaced 4 bytes after Bool2:
Attachment:
pointer-online-change.png


This was after I performed a clean and download - note that Bool3 is now moved relative to the online change (and is as one would "expect" - at 1 memory location after Bool2):
Attachment:
pointer-clean-download.png


If you are going to use a solution using POINTER TO or REFERENCE TO, please know that online changes can sometimes move variables and FBs around in memory, breaking those pointers (point to the old location, not the new one) - refresh the pointers to avoid online change problems (you can avoid online changes, but somebody else using your code may use online change...). I am pretty sure REFERENCE TO has the same problem with online change, since behind the scenes a REFERENCE TO is a special handling of POINTER TO.

Good luck!


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

_________________
Scott Cunningham
KEB America, Inc.
www.kebblog.com
www.kebamerica.com


Top
   
 Post subject: Re: POINTERs
PostPosted: Thu Jan 24, 2019 10:45 pm 
Offline
User avatar

Joined: Tue Jun 28, 2016 2:45 pm
Posts: 61
Wow - Scott, Thank you for this detailed description.

Gesendet von meinem LYA-L29 mit Tapatalk

_________________
Building & Process Automation with HVAC Library for CODESYS© - www.hvac-automation.com


Top
   
 Post subject: Re: POINTERs
PostPosted: Fri Jan 25, 2019 12:12 am 
Offline
Frequent User
Frequent User

Joined: Tue Dec 03, 2013 11:52 pm
Posts: 106
Scott,
I understand your example of just creating a BOOL and how there is no guarantee that bool2 will be right after bool 1 but isn't that where using a structure would fix that?

For example whenever I change the structure and do an on-line change you get a warning that the variable you declared that used that structure will move to new memory locations. This moves all of the existing variables in the structure and keeps them in order. I have yet to find a device/os/compiler that doesn't put this in order when talking about CoDeSys.

I'm trying to understand how to do what the original author was asking if the way I suggested is not reliable. Just trying to learn.

Regards,
CB


Top
   
 Post subject: Re: POINTERs
PostPosted: Fri Jan 25, 2019 5:30 am 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 297
CB
A STRUCT should be one continuous space IF the struct elements are all the same (such as a struct if BOOLs). This becomes false when you mix data types (DWORDS don’t start at an odd memory location).

I also received the “warning” message when I made the online change with Bool3, but I simply did what too many people do - I quickly clicked OK and ignored it! :)

Your offered solution is good, with a small change - I would not use +1 in your pointer math - that assumes that a BOOL will always only use one byte of memory location... this may not be the case on all hardware platforms! (This may seem silly, but so does CoDeSys’ BOOL as 8 bits of space instead of 1 bit to a C programmer!). Instead, use + SIZEOF(BOOL) in the for loop and the pointer calculation.

It would be interesting to see some type of OOP solution, too! Seems close to a linked list.

_________________
Scott Cunningham
KEB America, Inc.
www.kebblog.com
www.kebamerica.com


Top
   
 Post subject: Re: POINTERs
PostPosted: Fri Jan 25, 2019 3:04 pm 
Offline
Frequent User
Frequent User

Joined: Tue Dec 03, 2013 11:52 pm
Posts: 106
Thanks Scott,
Great suggestion. I hadn't thought of using sizeof to determine the length of a data type for iterating through memory locations.

Regards,
CB


Top
   
 Post subject: Re: POINTERs
PostPosted: Fri Jan 25, 2019 6:33 pm 
Offline

Joined: Sun Jun 28, 2015 12:23 pm
Posts: 77
Comingback4u wrote:
Thanks Scott,
Great suggestion. I hadn't thought of using sizeof to determine the length of a data type for iterating through memory locations.

Regards,
CB

Agree. Thanks Scott


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

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 3 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