Current status of IEC-61131-3 translator [was: What now? (flame bait)]

J

Thread Starter

Jiri Baum

Campbell, David (Ex AS17):
> There is an area which needs to be clarified. The LPLC uses names
> (strings) to reference memory locations while the IEC standard uses
> direct referencing, eg:
> ===================================================================
> B.1.4.1 Directly represented variables
> PRODUCTION RULES:
> direct_variable ::= '%' location_prefix size_prefix integer {'.' integer}
> location_prefix ::= 'I' | 'Q' | 'M'
> size_prefix ::= NIL | 'X' | 'B' | 'W' | 'D' | 'L'
> ===================================================================

> This may require some modifications of plc_pt_by_name() to handle
> references such as "%MW1.3.2".

plc_pt_by_name() can handle such references now.

My opinion: I would consider the % sign a syntactic element and "MW1.3.2" the point name. This will avoid the need to quote things in linuxplc.conf while providing strict standard compliance.

The function obtaining the handle (or a standalone program) should check the size and mode of the handles obtained and verify that they are compatible with the location and size prefixes, but that's easy enough.


There should probably be an option to accept "%"[[:alnum:]._-]+ as direct variables; again, drop the % sign and pass the rest to plc_pt_by_name(), skipping the type-check. Does the standard provide some way of switching
vendor-specific options? ("pragma relax_points" or something...)

Jiri
--
Jiri Baum <[email protected]>
What we do Every Night! Take Over the World!

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Jiri Baum wrote:

> Campbell, David (Ex AS17):
> > There is an area which needs to be clarified. The LPLC uses names
> > (strings) to reference memory locations while the IEC standard uses
> > direct referencing, eg:
> > ===================================================================
> > B.1.4.1 Directly represented variables
> > PRODUCTION RULES:
> > direct_variable ::= '%' location_prefix size_prefix integer {'.' integer}
> > location_prefix ::= 'I' | 'Q' | 'M'
> > size_prefix ::= NIL | 'X' | 'B' | 'W' | 'D' | 'L'
> > ===================================================================
>
> > This may require some modifications of plc_pt_by_name() to handle
> > references such as "%MW1.3.2".
>

I have been waiting for this to come up for some time now ;-)

I see two ways of supporting this, one similar to what Jiri proposes (but that I wont describe so as not to create more confusion,as it does not have any advantages of Jiri's proposal), and another that I was pushing for some time back when we were discussing something related, but that I eventually let it drop because the discussion was getting confusing and starting to include too many issues at the same time.

>
> plc_pt_by_name() can handle such references now.
>
> My opinion: I would consider the % sign a syntactic element and "MW1.3.2"
> the point name. This will avoid the need to quote things in linuxplc.conf
> while providing strict standard compliance.
>
> The function obtaining the handle (or a standalone program) should check
> the size and mode of the handles obtained and verify that they are
> compatible with the location and size prefixes, but that's easy enough.
>

Note that this should work, but requires the module to be a little clever.

It often happens that the same memory location may be accessed as a 32 bit integer, or each bit individually. In this case the module must recognize that the bit being accessed is not another linuxplc point per se, but a bit of on
another larger linuxplc point.

One way to do this is to only map 32 bit (or should it be 16 bit?, it depends on the IEC... standard) memory words into linuxplc points (say MW32 20). When a bit needs to be accessed (e.g. MW1 32.0) then the whole linuxplc point must
be read but only the referenced bit used (e.g. get MW32 20, but only use bit 0). Actually, the linuxplc library already offers a shortcut for this. It is possible to get a plc_pt_t handle to part of another linuxplc point referenced
through another plc_pt_t handle.
e.g.:
plc_pt_t MW20_pt = plc_get_pt_by_name("MW20);
plc_pt_t MW20.0_pt = plc_subpt(MW20_pt, 0 /* start bit */, 1 /* length */ );


plc_set(MW20_pt, 0xFFFF)
plc_get(MW20.0_pt); /* will return 1 ! */
plc_set(MW20_pt, 0xFFFE)
plc_get(MW20.0_pt); /* will return 0 ! */


The main drawback with this approach is that eventually we will get a globalmap (plc state) of say 4 kBytes, but have more than 64kBytes for the
confmap (configuration map that stores where each point resides in the globmap). It just doesn't make sense. (Please note that it is the proportions that are important, not the actuall values I sugested)


*********

The second way of doing it would be to have the linuxplc library support arrays of points. Other variants could be structures, or maybe even simply
points with bit size larger than 32.

The last option has the advantage that no changes to the API are required, but will make the linuxplc library code more complex, and therefore make the accesses to the points slower.

The array of points has exactly the opposite properties.

With arrays of points you could get an array for the MW, another for MI and yet another for MQ. But this has the drawback that then we must support arraypoints with multiple owners, even though each element of the array could only have one owner.

We must really think this through properly before we charge into any coding. For the moment, I sugest you follow Jiri's suggestion until we can come to a consensus.


Mario.


----------------------------------------------------------------------------
Mario J. R. de Sousa [email protected]
----------------------------------------------------------------------------




_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Mario de Sousa wrote:

> ============================================
> >
> > > This may require some modifications of plc_pt_by_name() to handle
> > > references such as "%MW1.3.2".
> >
>
> I have been waiting for this to come up for some time now ;-)
> (...)
> e.g.:
> plc_pt_t MW20_pt = plc_get_pt_by_name("MW20);
> plc_pt_t MW20.0_pt = plc_subpt(MW20_pt, 0 /* start bit */, 1 /* length */ );
>
> plc_set(MW20_pt, 0xFFFF)
> plc_get(MW20.0_pt); /* will return 1 ! */
> plc_set(MW20_pt, 0xFFFE)
> plc_get(MW20.0_pt); /* will return 0 ! */
>

I must apologize for getting all the IEC memory location syntax wrong. Maybe this will make it a little more clear...

This should be:
plc_pt_t MW20_pt = plc_get_pt_by_name("MW20);
plc_pt_t MB20.0_pt = plc_subpt(MW20_pt, 0 /* start bit */, 1 /* length */ );

plc_set(MW20_pt, 0xFFFF)
plc_get(MB20.0_pt); /* will return 1 ! */
plc_set(MW20_pt, 0xFFFE)
plc_get(MB20.0_pt); /* will return 0 ! */


Sorry for the confusion.

Mario.

----------------------------------------------------------------------------
Mario J. R. de Sousa [email protected]
----------------------------------------------------------------------------

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
> > Campbell, David (Ex AS17):
> > > There is an area which needs to be clarified. The LPLC uses names
> > > (strings) to reference memory locations while the IEC standard uses
> > > direct referencing, eg:
> > > ===================================================================
> > > B.1.4.1 Directly represented variables
> > > PRODUCTION RULES:
> > > direct_variable ::= '%' location_prefix size_prefix integer {'.' integer}
> > > location_prefix ::= 'I' | 'Q' | 'M'
> > > size_prefix ::= NIL | 'X' | 'B' | 'W' | 'D' | 'L'
> > > ===================================================================

> > > This may require some modifications of plc_pt_by_name() to handle
> > > references such as "%MW1.3.2".

Jiri Baum:
> > plc_pt_by_name() can handle such references now.

> > My opinion: I would consider the % sign a syntactic element and
> > "MW1.3.2" the point name.
...

Mario de Sousa:
> It often happens that the same memory location may be accessed as a 32
> bit integer, or each bit individually. In this case the module must
> recognize that the bit being accessed is not another linuxplc point per
> se, but a bit of on another larger linuxplc point.

Oops, right you are.

I would suggest that if the program calls for a point shorter than 32 bits, *and* the point doesn't in the lPLC map, to look for a point without the bit-specification.

So, if the program calls for %M20.3:
1) look for point M20.3
if exists, return it
2) look for point M20
if exists, return the .3 subpoint of it
otherwise error


Mind you, using a point that way is pretty shocking from a program-design point of view. I can see when you might want to do it, but it's pretty sad that you'd have to.

This would be in addition to my "%"[[:alnum:]._-]+ suggestion; perhaps in that, too, if it ends in .3 and it's not found, look for a point without
the .3 and return a subpoint to it.

Jiri
--
Jiri Baum <[email protected]>
You know you've been hacking too long when ...
... reading a book you notice the word "From" at the beginning of a line.

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
H

Harald Albrecht

> I would suggest that if the program calls for a point shorter than 32 bits,
> *and* the point doesn't in the lPLC map, to look for a point without the
> bit-specification.
>
> So, if the program calls for %M20.3:
> 1) look for point M20.3
> if exists, return it
> 2) look for point M20
> if exists, return the .3 subpoint of it
> otherwise error
>
> Mind you, using a point that way is pretty shocking from a program-design
> point of view. I can see when you might want to do it, but it's pretty sad
> that you'd have to.

Let me look at some point name lists I got from various industrial users running larger DCS...
...the dot is already taken, same for the dash and the slash... ah, and here we have a percent sign, and next come square brackets...

Give the process control engineers ASCII and they will use every single character in it, including the tilde and the DEL character.
Give them UNICODE -- no, I don't even want to imagine *that*...

Two suggestions/ideas/bad tips:

1) impose a strict hierarchy, like it was suggested. BTW -- for larger systems, you typically do not only want to denote simple
hierarchy but also composition, as this has a different life span from simple containment/hierarchy. For this reason I use "/" to denote hierarchy and "." for composition, which is a strong form of aggregation. We already deploy this within some large systems and thus can avoid name clashes between attributes of objects and identical named child objects.

2) get out of the way of PLC technicians and do not impose anything unless you want to be beaten with &lt;insert your favorite PLC here>. Instead allow aliases, so you can map the M20 point to a 32 bit word and M20.3 to a single bit within the same word. Disadvantage: you need to configure *all* the aliases...

just my e.02...

Harald

--
Harald Albrecht
Chair of Process Control Engineering
RWTH Aachen University of Technology
Turmstrasse 46, D-52064 Aachen, Germany
Tel.: +49 241 80-7703, Fax: +49 241 8888-238

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
> > I would suggest that if the program calls for a point shorter than 32
> > bits, *and* the point doesn't in the lPLC map, to look for a point
> > without the bit-specification.

> > So, if the program calls for %M20.3:
> > 1) look for point M20.3
> > if exists, return it
> > 2) look for point M20
> > if exists, return the .3 subpoint of it
> > otherwise error

> > Mind you, using a point that way is pretty shocking from a
> > program-design point of view. I can see when you might want to do it,
> > but it's pretty sad that you'd have to.

Harald Albrecht:
> Let me look at some point name lists I got from various industrial users
> running larger DCS...
> ...the dot is already taken, same for the dash and the slash... ah, and
> here we have a percent sign, and next come square brackets...

Fortunately, here we are dealing with the IEC 61131 standard, which specifies exactly what a point name should look like.

In the IEC standard, a trailing ".number" always specifies a bit offset within a word.

> Give them UNICODE -- no, I don't event want to imagine *that*...

Actually, giving them unicode is a very good idea, because it'll let them use Chinese for point names.

> 1) impose a strict hierarchy,

Don't like that - normally you want a hierarchy by function, not by type.

> 2) get out of the way of PLC technicians and do not impose anything
> unless you want to be beaten with <insert your favorite PLC here>.

That's the appropach the lPLC takes. However, a logic engine which follows a standard or emulates a particular style of PLC may, and sometimes must,
enforce some conventions. Such is the case here.

> Instead allow aliases, so you can map the M20 point to a 32 bit word and
> M20.3 to a single bit within the same word. Disadvantage: you need to
> configure *all* the aliases...

Yup, that's the normal lPLC way of doing it. However, within the confines of the IEC module it makes sense to do it implicitly. Because that's the meaning of the standard.

Other than that, I agree with you. Allow anything and get out of the way.


Jiri
--
Jiri Baum <[email protected]>
You know you've been hacking too long when ...
... reading a book you notice the word "From" at the beginning of a line.

_______________________________________________
LinuxPLC mailing list
[email protected]
http://linuxplc.org/mailman/listinfo/linuxplc
 
Top