CODESYS - the IEC 61131-3 automation software

Welcome to the official CODESYS Forum
Deutsche Version English version russian version 
It is currently Thu Oct 19, 2017 7:16 pm

All times are UTC+01:00




Post new topic  Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Fri May 05, 2017 7:23 am 
Offline
User avatar

Joined: Wed May 04, 2016 2:43 pm
Posts: 23
Hi Everyone
I'm currently working on a project with a lot a data to send to a TouchScreen and as I'd like to optimize the communication speed, I have to use array
But for example, I build an array with all the data for my motor so I obtain
Motor1 array[1..10] of word;
So if in my program I do:
LD word1
ST motor1[1]

So I'd like if there is a way to give to this motor1 a name or a comment, so if I use my mouse on it, I could see the comment

Many thanks in advance for your help :)


Top
   
PostPosted: Fri May 05, 2017 6:51 pm 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 256
Solution 1 (I recommend):
  • Have your speaking variables and structures as you need.
  • Have a HmiData array of WORDs
  • Create a PRG that is called every PLC scan with the name like "MapHmiData"
  • Explicitely map speaking variables to HmiData array (read only variables)
  • Explicetly map HmiData array entries to speaking variables (user write variables)

Advantages:
  • You get to use your speaking variables
  • You control scaling exactly as you need (i.e from REAL to WORD)
  • You can see exactly what variable goes to which array entry - no math, no counting in your head, etc.

Disadvantages:
  • Uses twice as much variable space (I've never run out of RAM space on a CoDeSys platform)
  • Manually code each assignment (but I prefer to see the explicit list 3 years from now when I forget what was being sent)
  • Takes CPU time (copying data into arrays of 100 or 200 WORDs does not take much processing power anymore - I've never had to optimize this until now over 11 years!)

Code Example:
Code:
PROGRAM MapHmiData
VAR
END_VAR

//copy drive1 data
GVL_APP.HmiData[0] := INT_TO_WORD(GVL_APP.Drive1.ControlWord);
GVL_APP.HmiData[1] := INT_TO_WORD(GVL_APP.Drive1.StatusWord);
GVL_APP.HmiData[2] := REAL_TO_WORD(GVL_APP.Drive1.Temperature * 10); //0.1 deg C resolution
GVL_APP.HmiData[3] := INT_TO_WORD(GVL_APP.Drive1.ActualCurrent);
GVL_APP.HmiData[4] := DWORD_TO_WORD(SHR(GVL_APP.Drive1.HourCounter,16)); //high word
GVL_APP.HmiData[5] := DWORD_TO_WORD(GVL_APP.Drive1.HourCounter); //low word

//copy drive2 data
GVL_APP.HmiData[6]  := INT_TO_WORD(GVL_APP.Drive2.ControlWord);
GVL_APP.HmiData[7]  := INT_TO_WORD(GVL_APP.Drive2.StatusWord);
GVL_APP.HmiData[8]  := REAL_TO_WORD(GVL_APP.Drive2.Temperature * 10); //0.1 deg resolution
GVL_APP.HmiData[9]  := INT_TO_WORD(GVL_APP.Drive2.ActualCurrent);
GVL_APP.HmiData[10] := DWORD_TO_WORD(SHR(GVL_APP.Drive2.HourCounter,16)); //high word
GVL_APP.HmiData[11] := DWORD_TO_WORD(GVL_APP.Drive2.HourCounter); //low word

//copy user data to controller
GVL_APP.UserCtrl.AutoRun     := WORD_TO_BOOL(GVL_APP.HmiData[20]);
GVL_APP.UserCtrl.CmdSpeed    := WORD_TO_INT(GVL_APP.HmiData[21]);
GVL_APP.UserCtrl.CyclesToRun := GVL_APP.HmiData[22];


Solution 2 (old school PLC programmer trick):
  • Define HmiData array at a specific memory location (AT %MW0)
  • Define your speaking variables at specific memory locations so they overlap with HmiData

Advantages:
  • Doesn't "waste" RAM by having two WORDS for same data
  • Doesn't use extra CPU time

Disadvantages:
  • Much work up front to align the memory locations
  • Cannot scale anything - what's in the memory location is how it will be.

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


Top
   
PostPosted: Thu Jun 01, 2017 5:15 am 
Offline

Joined: Mon May 15, 2017 6:47 am
Posts: 43
@scott_cunningham,

You could definitely scale using:

HmiData AT %IW101: ARRAY[1..10] OF WORD;

This attaches array to memory : [%IW101, %IW102, %IW103, ...%IW110]

Bad thing is all items must be of same data type.


Top
   
PostPosted: Fri Jun 02, 2017 9:02 am 
Offline
User avatar

Joined: Tue Aug 30, 2011 1:21 am
Posts: 92
If you are using CoDeSys v3 which is assumed since this is posted in v3 section you could also use a reference to achieve this functionality. Reference is similar to a pointer but once you assign the reference you can use the variable just like any other variable.


Code:
VAR
   arWord: ARRAY[0..10] OF WORD;
   rMyWord: REFERENCE TO WORD;
END_VAR

rMyWord REF= arWord[0];
rMyWord:=777;  //arWord[0] will equal 777


You could also use pointers but you need to deference the pointer with the ^ operand each time to use the value.
Code:
VAR
   arWord: ARRAY[0..10] OF WORD;
   pMyWord1: POINTER TO WORD;
END_VAR

pMyWord1:=ADR(arWord[1]);
pMyWord1^:=777;  //arWord[1] will equal 777


_________________
The Original SoMachine Ninja


Top
   
PostPosted: Fri Jun 02, 2017 5:56 pm 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 256
I've been using references a lot lately - they are great when you don't need scaling or conversion. I would recommend to add an initializer to references when they are defined to at least avoid crashes (unreferenced reference written to usually writes into a really bad space).

Code:
VAR
   SafeRef : WORD;
   MyRef1 : REFERENCE TO WORD := SafeRef;
   ...



You can also use
Code:
__IsValidRef()
to check - I will do that on FBs that have a state machine and I just define an init step.

Of course, when there is scaling or conversion, I use my "solution 1"...

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


Top
   
PostPosted: Sat Jun 03, 2017 12:24 am 
Offline
User avatar

Joined: Tue Aug 30, 2011 1:21 am
Posts: 92
scott_cunningham wrote:
Of course, when there is scaling or conversion, I use my "solution 1"...

Not sure what you mean by scaling but if you mean casting then there is trick that you can use by the combination of pointers and references to make it work. See below an example how to cast a part of a word array to a REAL reference. Just keep note of the data type size when using pointer and not to exceed the array bounds.


Code:
VAR
   arWord: ARRAY[0..10] OF WORD;
   pMyREAL: POINTER TO REAL;
   rMyREAL: REFERENCE TO REAL;   
END_VAR

pMyREAL:=ADR(arWord[1]);
rMyREAL REF= pMyREAL^;
rMyReal:=777.777; // arWord[1] and arWord[2] would hold real value of 777.777



_________________
The Original SoMachine Ninja


Last edited by jzhvymetal on Sat Jun 03, 2017 12:44 am, edited 1 time in total.

Top
   
PostPosted: Sat Jun 03, 2017 12:40 am 
Offline
User avatar

Joined: Tue Aug 30, 2011 1:21 am
Posts: 92
nothinrandom wrote:
@scott_cunningham,

You could definitely scale using:

HmiData AT %IW101: ARRAY[1..10] OF WORD;

This attaches array to memory : [%IW101, %IW102, %IW103, ...%IW110]

Bad thing is all items must be of same data type.


Also if you mean casting the above is not true you would just define a second variable to cast it. All the example below would overlapp on memory thus automatically casting it

Code:
myByte  AT %MB0   : BYTE; //Byte Type
mySINT  AT %MB0   : SINT;
myUSINT AT %MB0   : USINT;
myByteArary AT %MB0 : ARRAY[0..10] OF BYTE;

myWORD  AT %MW0   : WORD; //16 bit types
myINT   AT %MW0   : INT;
myUINT  AT %MW0   : UINT;
myWordArary AT %MW0 : ARRAY[0..10] OF WORD;

myDWORD AT %MD0   : DWORD; //32bit Types
myDINT  AT %MD0   : DINT;
myUDINT AT %MD0   : UDINT;
myReal  AT %MD0   : REAL;
myDwordArray AT %MD0 : ARRAY[0..10] OF DWORD;

_________________
The Original SoMachine Ninja


Top
   
PostPosted: Sat Jun 03, 2017 7:16 pm 
Offline
Frequent User
Frequent User

Joined: Fri Sep 02, 2011 8:02 pm
Posts: 256
I don't mean casting. Many times, data is a WORD but has a scaling. For example, temperature may have a resolution of 0.1 degrees on a device but may only use a WORD to store it. In that case, a raw value of 123 means 12.3 degrees. If I don't care about the fraction, I only want 12. Or a better example is a servo drive that has a speed resolution of 0.125 rpm (+/- 4000 rpm is +/- 32000 raw data). This is held in a WORD register in the servo. There is no reason in most cases to display 0.125 rom resolution - much easier to just adjust the raw to be +/- 1 rpm before sending it. In this case, a second variable and "scaling" is the solution.

I just avoid at memory definitions - it obfuscates what's happening and requires someone to dig deeper to understand your code. I prefer to be explicit in my conversions at least, that's my style

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


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 8 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