Sign in to follow this  
Followers 0
servant

ControlLogix 1sec,1 min, and 15min average calcs

8 posts in this topic

Is there a simple way to perform ControlLogix 1second, 1 minute, and 15minute average calcs, and then reset the average to prepare for the next time period averages? I am reading some analog inputs and a modbus input, and need them to be averaged at the aforementioned intervals, so that drift calculations can be performed. Please assist.

Share this post


Link to post
Share on other sites
Store your analog values in an array, then use the FAL instruction to calculate the average for 1 second. Store the results in a second array, average those values every 1 minute, store the results in an additional array, average those every 15 minutes.

Share this post


Link to post
Share on other sites
Can you offer any examples? I'm guessing to have a 60 point array being filled every second and dividing the sum of all 60 values by 60 for the one minute array. Then I suppose to take the one minute calculated averages into a 15 point array and dividing the sum of all 15 values by 15. Example code or picture would be very helpful, as I have never used the arrays.

Share this post


Link to post
Share on other sites
1. Run the task periodically so that you can control the timing rate at which it takes samples. So for instance if the task runs every 25 ms, then you will have 1000/25 = 40 samples. 1a. Alternatively, set up say a millisecond timer with a preset of 1 second. The timer preset can be anything as long as it is significantly larger than the sampling interval. On each program scan, check if the timer accumulator exceeds your resolution (25 ms in this example). If so, then SUBTRACT 25 ms out of the accumulator and trigger the totalizer code. This will introduce some timing jitter to your sampling but it has the advantage that you don't have to have a specialized task for the timing issue. 2. Clear 2 registers. One will be a sample count. The other will be a totalizer. The sample count can be implemented as a counter which is handy because some of the logic is built-in. 3. At each time interval, add 1 to the sample count. Take a sample and add it into the totalizer (a running total). 4. At the end of your time period, divide the totalizer by the sample count. This is your average. Then go back to step 2. 5. Since your time intervals are exact multiples of each other, you can either repeat this block of code 2 more times (with different sample counts and time intervals) or simply add the 1 second total to a second sample count/totalizer for 1 minute (for 60 samples), and then add THAT one to a totalizer for 15 minutes (15 samples). The results are the same but this version can be more efficient since 2/3rds of your code runs very infrequently (once per second, once per minute). A second issue is that for the 15 minute interval at 25 ms intervals, you will have to use something other than an integer (40 samples per second * 60 secs/min * 15 minutes = 36000 samples, which is larger than 32767). This version is a running totalizer. Alternatives (which are slower since division is slow on virtually all CPU's) is to do the division operation on every sampling interval. You could do the division every time following the same math as above or calculate ((old average * sample count-1) + new sample) / sample count). The downside of this calculation is that it will have precision issues (division is almost always approximate) so it is best to avoid it. Finally, you can trigger this sort of code just as easily off the real time clock instead of a sample counter. In this case, most of the time I use a trigger that looks something like the following (in pseudo-code): If LastReading <> ClockSeconds then LastReading=ClockSeconds Set "trigger" to run the code that should run once per second end if The primary advantage of triggering off the real time clock is that frequently when doing running totals or averages, managers get hung up with the physical clock on the screen/wall and expect 15 minutes to be synchronized with "real time". There are also issues with this. If someone is screwing with your clock (since PLC clocks are notoriously inaccurate and can gain/lose a few seconds per day, and also to implement daylight savings time sanely), it will screw up your code if you don't account for it. For the same reasons, if you run a sample count, you may find some jitter in that say on 25 ms intervals, you will sometimes have 40 samples, sometimes 39 samples, or sometimes 41 samples. So the safest bet of course is to implement both (keep a sample count but use the real time clock in the PLC) if you find yourself in a situation of running block averages tied to the wall clock. All previous versions are a running totalizer system. The previously mentioned FAL or AVERAGE instructions also work. They take more memory and have more processor timing jitter since the processor does the addition step all at once at the end of the interval. Plus, the 15 minute average with 25 ms sampling rates amounts to 36,000 samples. Even on Contrologix, that is going to be one heck of a delay every time it executes an FAL for that many samples.

Share this post


Link to post
Share on other sites
Wow, Thanks paul! You said a mouthful. My first, or current attempt follows closely with your original proposal, except I used an "ADD + 1" instruction instead of a counter. I'm, also using a 100ms timer to trigger my counts, or summations. My biggest setback, or concern, is when to clear the register to get ready for the subsequent averages on the 1sec, 1min, and 15min totals for which to derive my averages. I will not be able to test the logic until one or two days before the scheduled FAT test; therefore, I was hoping to be certain as to the logic results.

Share this post


Link to post
Share on other sites
If you keep a running total and a circular FIFO it is not necessary to perform the summing of all 60 samples every time you recalculate the average. Here is a sample of the method I set up for another poster who was using an ML1100 to average 200 samples. This would be even simpler in the CLX, especially in ST.. It implements a circular FIFO using an array and a pointer instead of fifo instructions. Its fast because it doesn't shift any large chunks of data around in memory and each new sample requires only one subtracion, one addition, and a single divison to recalculate the new average. On the CLX use the CPT instruction to avoid the intermediate result storage. http://forums.mrplc.com/index.php?act=Atta...ost&id=5403 (original thread with the solution above http://forums.mrplc.com/index.php?showtopic=12206)

Share this post


Link to post
Share on other sites
Thanks guys, I have downloaded the file and see if I can replicate it and get it to work. This looks super!!!!!!!!!!!!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0