Bit variables & PLCs

  • Thread starter Campbell, David (Ex AS17)
  • Start date
C

Thread Starter

Campbell, David (Ex AS17)

Hopefully the following is not a stupid question: Q: Is it desirable to define a boolean variable (eg: type BOOL as defined in the IEC spec) as a single bit at a variable bit offset? eg: Define a variable as being bit 5 of byte 76. There is a nice feature of the IEC to declare a variable to report the rising or falling state of a memory location. The question that comes to mind is "how do we implement this?". I could use a C++ class but I have a feeling this is like using a sledgehammer (although a class would allow bit access of a word at the expense of CPU performance). David Campbell _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
M

Mario de Sousa

Hi David, I can see this being implemented at two different levels: - inside the linuxPLC libraries - by the IEC language compiled module. At the moment I favour the second (IEC module) as it seems very IEC language specific. I think this is exactly what you were considering doing. Later on, if we see that it may become usefule to many other modules, then we can consider having it in the linuxPLC library. How you go about implementing it in the compiled IEC language module is your decision. It also depends on the exact semantics implemented by the variable that reports the rising or falling state of another variable; 1) does it only detect rising or falling state between two updates to the plc memory (i.e. between two succesive iterations/loops of the program), or 2) does it detect rising and falling state of the variable as it changes value during the same iteration/loop of the program? If 1), then I can see you having a special short routine that updates the state of that BOOL variable at the beginning or end of the program loop. If 2), then I suppose that class implementation would be the easiest. Is there something I am missing here? Cheers, Mario. P.S. I am sorry about the delay in the dsp module. I had to re-learn how to implement butterworth/chebyshev/elliptic/iir/fir filters, along with the bilinear transformations, lowpass to highpass/bandstop/bandreject transformations, etc... I am about to finish the butterworth/lowpass implementation. From then on, I hope it will be easier... -- ---------------------------------------------------------------------------- Mario J. R. de Sousa [email protected] ---------------------------------------------------------------------------- The box said it requires Windows 95 or better, so I installed Linux _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
G

Gilles Allard

snip >> >> There is a nice feature of the IEC to declare a variable to report the >> rising or falling state of a memory location. The question that comes to >> mind is "how do we implement this?". I could use a C++ class but I have a >> feeling this is like using a sledgehammer (although a class would allow bit >> access of a word at the expense of CPU performance). >> > How you go about implementing it in the compiled IEC language module is >your decision. It also depends on the exact semantics implemented by the >variable that reports the rising or falling state of another variable; >1) does it only detect rising or falling state between two updates to >the plc memory (i.e. between two succesive iterations/loops of the >program), or 2) does it detect rising and falling state of the variable >as it changes value during the same iteration/loop of the program? > > If 1), then I can see you having a special short routine that updates >the state of that BOOL variable at the beginning or end of the program >loop. > If 2), then I suppose that class implementation would be the easiest. > Solution 1 would not be appropriate. According to IEC61131-3 (Ed.2), edge detection (R_TRIG and F_TRIG) are Function Blocks. This means that each instance has it's own memory (state variable). The internal code of R_TRIG is defined as: FUNCTION BLOCK R_TRIG VAR_INPUT CLK: BOOL; END_VAR VAR_OUTPUT Q: BOOL; END_VAR VAR M: BOOL; END_VAR Q := CLK and not M; M := CLK; END_FUNCTION_BLOCK Ther is no restriction about usage of R_TRIG. It may be used with a dynamically computed result, such as: ... VAR X R_TRIG; ... C := A and B; X (CLK := C); D := X.Q; (* get result of R_TRIG *) Thus it would not be appropriate to compute the edges at the beginning of the scan. David, please also note that the standard defines the R_EDGE and F_EDGE as a special attribute of a variable declaration. The call to R_TRIG (or F_TRIG) would be implicit (compiler-generated). Example: ... VAR_INPUT: K BOOL R_EDGE; L BOOL; END_VAR; ... Z := K and L; will implicitely call R_TRIG with K as input and returned value will be anded with L. I hope this help Gilles _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
C

Campbell, David (Ex AS17)

> From: Gilles Allard > snip > >> > >> There is a nice feature of the IEC to declare a variable to report the > >> rising or falling state of a memory location. The question that comes > to > >> mind is "how do we implement this?". I could use a C++ class but I have > a > >> feeling this is like using a sledgehammer (although a class would allow >> bit access of a word at the expense of CPU performance). > >> > Solution 1 would not be appropriate. According to IEC61131-3 (Ed.2), edge > detection (R_TRIG and F_TRIG) are Function Blocks. This means that each > instance has it's own memory (state variable). > The internal code of R_TRIG is defined as: Thanks for the pointer, quoting the standard: ================================================================== "7) In textual declarations, the R_EDGE and F_EDGE qualifiers can be used to indicate an edge-detection function on Boolean inputs. This shall cause the implicit declaration of a function block of type R_TRIG or F_TRIG, respectively, as defined in 2.5.2.3.2, to perform the required edge detection. For an example of this construction, see features 8a and 8b of table 33 and the accompanying NOTE." ================================================================== > David, please also note that the standard defines the R_EDGE and > F_EDGE as a special attribute of a variable declaration. The > call to R_TRIG (or F_TRIG) would be implicit (compiler-generated). Agreed. The standard fails to define when should the call to the R_TRIG / F_TRIG be made but immediately after the variable declaration seems to be the logical solution. Should the R_EDGE / F_EDGE variable be used more than once in a routine then both instances should return the same value. If the call was made immediately before each use then the second and subsequent uses of the variable will always return FALSE. I might be able to get away without needing another class. I have a minor semantic issue of using integer constants with BOOL variables (0 = FALSE, 1 = TRUE, other = ???). It only causes a problem with the data type checking routines. David Campbell _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
> I might be able to get away without needing another class. > I have a minor semantic issue of using integer constants with BOOL > variables (0 = FALSE, 1 = TRUE, other = ???). It only causes a > problem with the data type checking routines. > The best way to do it is - zero is false, everything else is true. This is primarily because boolean values are actually stored as at least a byte, or bigger. Some boolean operations may leave bits set at other locations. In general this is bad, but it might occur. Something I like to do to reset sanity (just in case) is when setting a boolean value, use 1 or 0 instead of the source value. (eg, if(result != 0) { result = 1;} Hugh _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
O

Oscar Esteban

Answer to some messages, all in one: >1) does it only detect rising or falling state between two updates to >the plc memory (i.e. between two succesive iterations/loops of the >program), or 2) does it detect rising and falling state of the = variable >as it changes value during the same iteration/loop of the program? > Solution 1 would not be appropriate. According to IEC61131-3 (Ed.2), = edge > detection (R_TRIG and F_TRIG) are Function Blocks. This means that = each > instance has it's own memory (state variable). Ok, but when should it be updated? 1) seems ok to me. But... as said, a) it must be possible to udpate while running a PLC cycle, not before (edge detection on signals internal to an ST snippet, for example) but b) the call should return the same value on each cycle, independently of how many times it is called. It seems it could be made defining a static variable on compiling time and using a hidden pointer to it on each FB activation. The compiler should take care of associating each instance (activation) to its hidden variable. Besides, it should keep a list of already activated FB's, which would be reset on each cycle's beginning. This way, the new value would be calculated the first time it was used in a cycle. If a "changing in a cycle" behaviour was desired, it could be as easy as ignoring the "already activated" flag. An odd behaviour comes to my mind. Let's suppose I have an ST snippet which is only executed in some cases. It uses a R_TRIG on a signal which eventually goes high, but my code is only executed some time later (with the signal still high). Should it still see the rising edge, even if it has not happened in this very moment, but some time ago? If this is not desirable, every R_TRIG should be evaluated not when it is used, but on each cycle's beginning. Should it need to be done this way, it seems feasible to build a table of R_TRIG / L_TRIG / any_other_FB instances (as many as hidden static variables) and evaluate them all before running the PLC code. About classes: I don't remember if the language used is C or C++. If C, just remember that classes are "functions for the class" + "data for each object". It can be done in C if care is taken to have "data for each object" and give them to the "functions for the class". Of course, taking care of the "type association" by hand. Greetings, Oscar _______________________________________________ LinuxPLC mailing list [email protected] http://linuxplc.org/mailman/listinfo/linuxplc
 
Top