Storing Int data in an array

Akgaurihar

Member
Join Date
Apr 2020
Location
xxx
Posts
9
Hello,
I have an int variable that updates the value every second. I want to store the 100 values in an array. Array should keep storing the values until PLC is running. I couldn't achieve this using FOR loop since the loop executes per plc cycle and doesn't wait until a second the fill the array.
I am looking for a possible solution on my query.
Thank you.
 
Hello,
I have an int variable that updates the value every second. I want to store the 100 values in an array. Array should keep storing the values until PLC is [not?] running. I couldn't achieve this using FOR loop since the loop executes per plc cycle and doesn't wait until a second the fill the array.
I am looking for a possible solution on my query.
Thank you.


Well done! You have discovered that time is the most important part of PLC programming, and also that PLC scan cycle is the clock.

The PLC scan cycle is the loop you are looking for; there may be as many as one thousand scan cycles occurring over each single second of time. You want your code to only store the value only on one scan cycle every second, and to do nothing on all other scan cycles during that second. To do that it will need to detect an event or status that changes exactly once every second. There are many ways to do this; which is best depends on several factors:

  • How accurately in time does this once-per-second event need to be measured?
  • What is the make, model, and environment of the PLC that will be running this code (Siemens, Allen-Bradley, Codesys, Structured Text, Ladder Logic, etc.)?
  • After 100 seconds, 100 locations in the array will have values, and presumably the 100-element array will be full; where do you want to put the 101st (101.) value?
    • Is the FOR loop shifting the values in the array to make room for the updated value?
  • What programming experience do you have besides PLCs?
Possible solutions:

  • Put the code, that stores one updated value into the array, into a timed interrupt task that executes once every second (every 1000ms).
    • This approach requires you to configure the PLC to run that task once per second
    • the details of how that is done depends on the make, model, and coding environment of the PLC.
    • The timing accuracy is probably best in this approach.
  • Use an event that occurs each time the stored integer value is updated, and detect the rising or falling edge of that event to trigger storing the value into the array.
    • For example, perhaps a messaging instruction is reading the update value from another device via a serial or network connection (e.g. Modbus). In that case the code could detect the rising edge of the "done" or "complete" status of the messaging instruction to trigger storing the updated value.
  • Run a repeating 1s (1000ms) timer in the continuous task, and only store the updated value on the single scan cycle each time that timer expires.
    • The timing accuracy of this approach is limited by the duration of the continuous scan cycle, which could be many milliseconds in duration.
    • This is a form of the previous "Use an event ..." approach, where the trigger event is supplied synthetically using a timer.
    • If you search this forum for the terms "structured text repeating timer" you should find a solution.
    • Note that if you are using Siemens TON timers, you may need to buffer the timer output state (.Q) value to a separate variable to get the repeat to work.
  • If there is a system instruction to retrieve the current time as [year, month, day, hour, minute, seconds], then each time the seconds value changes you could
    • run the loop to store the updated value, and
    • copy that current seconds value to a persistent variable to use to detect the next change
 
Well done! You have discovered that time is the most important part of PLC programming, and also that PLC scan cycle is the clock.

The PLC scan cycle is the loop you are looking for; there may be as many as one thousand scan cycles occurring over each single second of time. You want your code to only store the value only on one scan cycle every second, and to do nothing on all other scan cycles during that second. To do that it will need to detect an event or status that changes exactly once every second. There are many ways to do this; which is best depends on several factors:

  • How accurately in time does this once-per-second event need to be measured?
  • What is the make, model, and environment of the PLC that will be running this code (Siemens, Allen-Bradley, Codesys, Structured Text, Ladder Logic, etc.)?
  • After 100 seconds, 100 locations in the array will have values, and presumably the 100-element array will be full; where do you want to put the 101st (101.) value?
    • Is the FOR loop shifting the values in the array to make room for the updated value?
  • What programming experience do you have besides PLCs?
Possible solutions:

  • Put the code, that stores one updated value into the array, into a timed interrupt task that executes once every second (every 1000ms).
    • This approach requires you to configure the PLC to run that task once per second
    • the details of how that is done depends on the make, model, and coding environment of the PLC.
    • The timing accuracy is probably best in this approach.
  • Use an event that occurs each time the stored integer value is updated, and detect the rising or falling edge of that event to trigger storing the value into the array.
    • For example, perhaps a messaging instruction is reading the update value from another device via a serial or network connection (e.g. Modbus). In that case the code could detect the rising edge of the "done" or "complete" status of the messaging instruction to trigger storing the updated value.
  • Run a repeating 1s (1000ms) timer in the continuous task, and only store the updated value on the single scan cycle each time that timer expires.
    • The timing accuracy of this approach is limited by the duration of the continuous scan cycle, which could be many milliseconds in duration.
    • This is a form of the previous "Use an event ..." approach, where the trigger event is supplied synthetically using a timer.
    • If you search this forum for the terms "structured text repeating timer" you should find a solution.
    • Note that if you are using Siemens TON timers, you may need to buffer the timer output state (.Q) value to a separate variable to get the repeat to work.
  • If there is a system instruction to retrieve the current time as [year, month, day, hour, minute, seconds], then each time the seconds value changes you could
    • run the loop to store the updated value, and
    • copy that current seconds value to a persistent variable to use to detect the next change

Thanks for your reply.
I am using TwinCAT 3 and ST for programming. I am using TON with PT 1 sec and the input always TRUE. That means output is always toggling. With the rising edge of output I am make some calculation every second. I want to store those values in an array. Array positions should always shift means 101th value should be filled in 1st position. I hope it's clear now. :)
 
I think it is going to be very difficult to store values in a PLC that is not in RUN mode. Unless, you have some external software writing the values in program mode.


It could be that they want to do this on startup, to prefill an array. In Siemensland, you can put code in a Startup OB (OB100, traditionally) which is called when the PLC boots up but before it is fully in RUN. When the code finishes executing, then it transitions into RUN.


If that's the case, could it make sense to just have default values in the array, instead of filling it up every time?
 
Yes, but he mentions 1 second per value, so wait 100 seconds on start up. You are right though, you could put a loop in OB100 with a time delay. On 2nd thought I guess you could do it on any platform, just run the array population routine before all others. In the past I have just populated the array with current value at start up, just get things running.
 
Thanks for your reply.
I am using TwinCAT 3 and ST for programming. I am using TON with PT 1 sec and the input always TRUE. That means output is always toggling. With the rising edge of output I am make some calculation every second. I want to store those values in an array. Array positions should always shift means 101th value should be filled in 1st position. I hope it's clear now. :)

Use the same rising edge to shift your array. Many ways to do this, one way in ST is a For loop.

Code:
TON(IN:=(NOT TON.Q), PT:=T#1s);
IF TON.Q THEN
     FOR i := (size - 1) TO 1 BY (- 1) DO 
          Array[i] := Array[i - 1];
     END_FOR;
END_IF;

Also assuming by "Running" you are referring to whatever program/task/routine you choose to be running vs the PLC itself being in a run state?
 
Thanks for your reply.
I am using TwinCAT 3 and ST for programming. I am using TON with PT 1 sec and the input always TRUE. That means output is always toggling[???]. With the rising edge of output I am make some calculation every second. I want to store those values in an array. Array positions should always shift means 101th value should be filled in 1st position. I hope it's clear now. :)


No it is not clear to me yet.

  • A TON with its input always TRUE [e.g. der_TON(IN:=True, ...)] will time to its expiry at 1s once, after which its output will always be TRUE, not toggling, and there will be only one rising edge.
  • The common way to do this is to invert the timer output as the input:
    • der_TON(IN:=NOT der_TON_expired, PT:=T#1s, OUT => der_TON_expired);
    • OR
    • der_TON(IN:=NOT der_TON.Q, PT:=T#1s);
    • so the TON is reset each time it expires i.e. when the input becomes 0 i.e. NOT 1
The Boolean, either der_TON_expired or der_TON.Q, will be 1 for exactly one scan cycle every second, and so can be used to control the storing of the updated value into the array.



Note that this will take an extra scan cycle beyond the 1s to accomplish its task.

Another way to do the same thing would be this (from here):
Code:
timer(IN := TRUE, PT := T#1S);
IF timer.Q THEN
     store_value();
     timer(IN := FALSE); // reset timer
END_IF;
 

Similar Topics

HI all, I have a backup from a Series 7000 Cognex camera. I am trying to restore and see the vision tools used in the job. Can I restore those...
Replies
0
Views
71
Hi I have a vision camera that I’m getting the string data P908765 from the vision on an advance trigger .which im using a S -move. Then I put...
Replies
1
Views
377
Hello You guys helped me with a similar issue some time back on storing totalized values to different tags each month. I have a similar issue...
Replies
19
Views
1,496
Is there any easy way to store a password for an email address that is changeable on the HMI that is not easily deciphered. aka, don't write it to...
Replies
0
Views
381
I've inadvertently tick the DHCP box in the sick software and uploaded this in the PLC (Sick FX0-GENT) and now i am unable to connect to it. Is...
Replies
1
Views
999
Back
Top Bottom