Sign in to follow this  
Followers 0
wander_who

Triggering events using a timer & counter combo

26 posts in this topic

Hi all, This is what I have (CompactLogix) : XIO Pulse_Interval_Timer.DN TON Pulse_Interval_Timer 200 0 XIC Pulse_Sequence_Counter.DN RES Pulse_Sequence_Counter XIC Pulse_Interval_Timer.DN CTU Pulse_Sequence_Counter 40 0 Each count of the Pulse_Sequence_Counter is used to trigger the start of an event, giving 40 different start 'pulses' spread out with 200ms between each. This is supposed to give a time (between the first & last count) of 8 seconds (40 x 200ms). However, because of an accumulated error due to scan time, I am actually getting around 13 seconds! The scan time of the continuous task is about 125ms. Because plc needs to scan the timer rung one more time to actually set the .DN bit), this gives an error of approx 125ms for every count, resulting a total time of 13sec (40 x (200ms + 125ms) = 13 sec) After much stuffing around, trying .TT bits instead of .DN bits, timer values, etc... I am almost out of ideas... My work-around: I put the logic into a periodic task. The error is still there, but as the period is now known & repeatable, I can then just reduce the timer preset by an amount equal to the task period, so that I end up with 8 seconds... But I would like to fix it properly! So... Is there a better way of doing this? Or a CompactLogix instruction I could use? I have had a look, but I could not find any... It would be good if i could keep the timer & counter so that I could easily deploy a fix to a few other CompactLogix systems already installed, and keep the logic standard... but at this stage I am open to anything... Cheers, Andrew W

Share this post


Link to post
Share on other sites
Are you pulsing an output or executing some logic each time the pulse counter is incremented? 125ms scan time is extremely high

Share this post


Link to post
Share on other sites
Hi TWControls, There are two tasks - one main continuous task as mentioned previously, and one pid loops periodic task with 32 pid loops. The period of the pid loops task is set to that total time I mentioned in my previous post, (eg: counter preset x timer preset = 40 x 200ms = 8 seconds) There is a lot of other code in the main task. One program contains this pulse timer & counter logic. The scan time of this program is about 20,000us. In this program, there are 10 routines (most ladder, some structured text). Two of these routines are the main ones, and each has 40 JSR's. Each JSR has up to 15 input and 15 output parameters. Every JSR has one input as an input parameter and up to 3 outputs as return parameters. Also, every JSR has a BOOL 'pulse' flag (set when the pulse counter equals a certain value) as an input parameter. As the JSRs are all continuously scanned, the pulse flag triggers logic that determines if the outputs should remain on or be turned off, and how long between changes in on/off state, etc. (This is all for a temperature control process, for which the pulse flags synchronise the start & duration of a number outputs such as burner air & gas valves) The timer, counter, pulse flags, and logic that gets triggered by each flag, are all used only within this one program and its routines. The tags for the timer, counter, pulse flags, and a few others are all controller scope, all other tags are program scope. Hope this info helps ! What kind of scan time should I be expecting ? Cheers, Andrew W

Share this post


Link to post
Share on other sites
I looks like wander_who as already figured out that.... DON'T CASCADE TIMERS IF YOU WANT A REPEATBLE RESULT! Start all your timer at the same time. If this would requre too many timers then use the real time clock or millisecond clock. The interrupt should work too but don't put the timer in the interrupt. Just count interrupts. The time between interrupts should be more consistant than what you indicate. A trick I use goes like this: StartTime = MillisecondClock do something while ( (MillisecondClock-StartTime) < DoSomethingTime Note, you cannot do this : do something while ( MillisecondClock)< (StartTime+DoSomethingTime)) This fails when roll over occurs. This is a small but important difference. The events can't have any better resolution than the scan but at least the errors will not accumulate. 125 milliseconds is very long. Too long. I would consider jumping over code that doesn't get executed or find ways of condiditionally calling the subroutines. Calling subroutines and then doing nothing in them is wasteful.

Share this post


Link to post
Share on other sites
125 ms that's an eternity in a processor that counts time in microseconds. I think most of your time is ate up in parameter passing. If you can do it rewrite your program without parameter passing. Use the equ instruction at the start of several rungs to execute them conditionally. Might improve your scan time.

Share this post


Link to post
Share on other sites
Using a SFC is one way. If you are using INT's extensively, they will have a significant impact on execution time as well as program memory usage. Use DINT's. You might be amazed.

Share this post


Link to post
Share on other sites
Both Boblfoot and Gerry have made excellent points but I am still a bit baffled by the execution time. Their suggestions will help reduce your scan time and should get your 200ms down but could you post your program? Something in it is still puzzling me to push your scan time that high.

Share this post


Link to post
Share on other sites
I am not puzzled at all. TW try the following on any Logix5000 Platform machine and watch the results. Create a subroutine which takes two input parameters and after adding them places the result in a return parameter. Next create a fox next routine in your main routine which calls the ADD routine and proceeds to the next iteration. Use a value of 1, 2 5, 10 and 25 for your for loop. You'll be surprised how low a number gives you a scan time over 50 ms. I was. INMHO the CLGX series does not optimize variable handling in sub calls at least in pres V15 versions.

Share this post


Link to post
Share on other sites
That would be a glaring flaw. Take a look at Automation Direct. Each function requires that parameters are pushed on a stack before calling the function. We can call functions on our motion controller. It is not as efficient as loading the parameter directly but the difference is small. Almost all modern languages pass parameters on the stack. Some allow parameters to be passed in registers which is the fastest means of passing parameters. Passing parameter shouldn't take that long. I can't believe RS can be that incompetent.

Share this post


Link to post
Share on other sites
I understand what you are saying Bob, but 125ms just seemed steep to me. Then again if it were a Micrologix I would go and calculate the rough scan time off of an instruction execution time chart.to get it through my head. I have never seen such a chart for the Compactlogix but it is still hard for me to imagine 125ms.

Share this post


Link to post
Share on other sites
I can understand TW, but I had the "priviledge" of revising a ControlLogix Program with 5 arrays of 1000 DINTS each. All 5 arrays had to be examined by a for next loop to locate items of interest. They also had to be shifted routinely so item 1 went to item 0 and etc. Original Scan time was 130 ms after much revision I got it down to 85 ms. So yes if the original writer used poor logic or you have a large amount of manipulations to do scan time can be high.

Share this post


Link to post
Share on other sites
Ok I see what you are talking about. Hopefully Wonder_Who will let us see the program.

Share this post


Link to post
Share on other sites
FYI - On this Subject an SSV or GSV takes 7 times longer on average than an MUL or DIV instruction,

Share this post


Link to post
Share on other sites
This is something that a lot of us have been asking RA for (I know I've been asking for an eternity) - passing by reference, not by value. I don't think it will ever happen, though. I'd also be hesitant to use an timed interrupt and count the ISR hits.... The scheduled tasks don't happen very repeatibly, even with an aggressive priority setting. Determinism isn't something I've counted on in Logix. Matt

Share this post


Link to post
Share on other sites
Version 16 has a roll your own instruction. It looks very promising for this type of thing but I have not used the beta yet

Share this post


Link to post
Share on other sites
Hi all, Been away for a while - had to remove everything from my old laptop and am using another temporarily... Thanks for all the replies.. everything has been helpful so far. Ok, specific replies/further questions: - Peter Nachtwey, mbrugman: By interrupt do you mean a periodic task? - Peter Nachtwey: About not cascading timers... There are two main routines that call all these JSRs. In the first main routine, there is only one timer, and one counter, other misc logic, and 40 JSRs. In the subroutine called by these JSRs, there are no timers or counters. (althought there are an additional two nested JSRs, but they are conditional and so will only be called once every 8 seconds) In the other main routine, there are 40 JSRs only, and in the subroutine called by these, there are two timers and one counter. But these are conditional and will very rarely (in terms of PLC time) be enabled. About the real time clock or millisecond clock, and counting interrupts: I don't quite understand your example... I know what you mean by the real time clock, but I think I am missing something with your description of how to use it or a millisecond clock (DoSomethingTime etc) About jumping over code that doesn't get executed: I understand this and agree.. but the problem is, the structure of the code requires the subroutine to be called every time, even though certain logic in the subroutine may only be executed once in every 40 counts, there are many lines of logic that is executed every scan. (See my comments below about re-writing the program, too) - BobLfoot, TWControls. Basically I am using a new program that I wrote, 90% of which is code written from scratch, but made to match standard algorithms etc (so that it matches our other progam, for Omron plcs). Unfortunately, the only part of the program that I did not change from it's predescessor (written by someone else), was this routine and the subroutine. I did add perhaps 50% of the input & return parameters - but the structure is unchanged. The other downside to this, is that I cannot afford the time for a rewrite at this stage, and would also like sort of fix that I could apply to the existing systems using this program structure. - Gerry, mbrugman: Gerry suggested to use a periodic task and count up every time it was scanned, but mbrugman thought that this would not be repeatable enough. As described in my previous post, the 'pulse' needs to be 100% reliable, or it will effect the temperature control process... About using DINTs instead of INTs: I have hardly any INTs in my PLC program (other than I/O tags, such as t/c inputs) - TW Controls About posting my program...well I am not sure I can/should? After all, it has taken me a while to convince the powers-that-be of the need to control our PLC programs, rather than leaving a copy on every customer's computer, all over the world... However, I do know that the bulk of the scan time is taken up by this one program (containing the two main routines with the JSRs, as described above) in the main task, so posting the rest of the plc program wouldn't be of much use, i think. I could post specific parts, I suppose ? There really isn't much to it that I already haven't posted! - TWControls & others: About scan times... Well, I just checked it again. II monitored the main task, cleared the max recorded scan time, and then watched the scan time. It has been stable at around 90ms so far. The scan time of the one program in question is about 25ms. All other programs in the main task are less than 10ms, most less than 5ms, and quite a few are less than 1ms. The only other task is the periodic (every 8 sec) PID loops taks. It's scan time is about 15ms. - TWControls About scan times per instructions: From the manual "1756-rm087_-en-e" (controllers execution time & memory use reference manual May 2005), the execution times of the JSR/RET instruction pair, for the L32E, is 10.6us + 2us per parameter. This means, for 40 JSRs with 15 inputs/14 returns + 40 JSRs with 12 inputs/8 returns + 40 JSRs with 5 inputs/4 returns, the execution time for all JSR/RET pairs only, would be: 1.4ms - TWControls & others I went to a Rockwel seminar about the new rev16, and am hanging out for these instructions. However, in the mean time, I had been thinking about modifying the JSRs: instead of using up to 15 input parameters + 15 return parameters, perhaps I could use a user defined data type, and (eg call it "Burner Pulse"), which contained members that matched the number, size, and data type of these parameters, and simply pass it to, and return it from, the subroutine, for each JSR ? Could I expect a big decrease in scan time if I streamlined it this way? Ok. Sorry for the long responses. Now, I should say that every tag passed from the JSR as an input parameter or return parameter, is one member of an array. All JSRs use the same parameters, just each one has a different index (eg 40 JSRs, so array elements 0 to 39). Example of one of the 40 JSRs: 15 input parameters, 14 return parameters input: 9 are one element of a DINT[64], 3 are one element of a BOOL[64], 2 are one element of a REAL[64], and 1 is a BOOL (a real I/O output actually). return: 11 of the return parameters are the *same* tags as the input parameters (all the array tags), plus 3 BOOLs (real I/O outputs). Do any of the following greatly increase execution and/or scan time: - Passing real inputs or outputs ? - Returning the same parameters that were passed as inputs? - Passing REALs - Passing BOOLs Lastly, back to my original question: As Peter Nachtwey said: "The events can't have any better resolution than the scan but at least the errors will not accumulate" (using his interrupt idea) So... short of a small or big re-write... is the interrupt idea the only thing I can do to improve the accuracy of the timer & counter combination ? (If so, as I mentioned above, I'm don't quite understand his example, so if you guys could elaborate...) What else I can do ?? Cheers, Andrew W

Share this post


Link to post
Share on other sites
So, what is your experience with periodic task repeatability?

Share this post


Link to post
Share on other sites
1. Why do you need to generate 40 pulses 200 milliseconds apart? I must ask this because I must be sure we are finding the right answer for the right problem. 2. Aren't there high speed counter cards that can work independently of the PLC cpu? 3. Get a faster PLC like a control logix. I think that too much is expected from the Compact logix PLC. Hardware is cheap compared to programming time. We use hardware to guarantee timing and rarely leave any critical timing to software, but then we deal in nanoseconds.

Share this post


Link to post
Share on other sites
40 JSRs with 15 inputs/14 returns Assuming the SBR has 40 generic rungs and each is XIO XIC OTE. that translates to 0.06us + 0.05us + 0.09us or .2us per rung. 40 rungs is 8us per routine. 40 routines is 320us or 0.32ms. Adding 14 rungs with 2 NEQ and 1 MOV we have 2 * 0.23us + 0.20us = 0.66us * 14 = 9.24us per routine 40 routines yields 369.6us or 0.3696ms. 40 JSRs with 12 inputs/8 returns = Assuming the SBR has 40 generic rungs and each is XIO XIC OTE. that translates to 0.06us + 0.05us + 0.09us or .2us per rung. 40 rungs is 8us per routine. 40 routines is 320us or 0.32ms. Adding 8 rungs with 2 NEQ and 1 MOV we have 2 * 0.23us + 0.20us = 0.66us * 8 = 5.28us per routine 40 routines yields 211.2us or 0.2112ms. 40 JSRs with 5 inputs/4 returns = Assuming the SBR has 40 generic rungs and each is XIO XIC OTE. that translates to 0.06us + 0.05us + 0.09us or .2us per rung. 40 rungs is 8us per routine. 40 routines is 320us or 0.32ms. Adding 4 rungs with 2 NEQ and 1 MOV we have 2 * 0.23us + 0.20us = 0.66us * 4 = 2.64us per routine 40 routines yields 105.6us or 0.1056ms. SBR Scan Summation = 369.6us + 211.2us + 105.6us = 686.4us. Total Summation = 5.912 ms + 0.6864ms = 6.5984 ms rounding to 7ms. A far cry from 1.4ms eh?

Share this post


Link to post
Share on other sites
BobLfoot, ok well I guess thats why I shouldn't do maths at 4am yes, 1.4ms was totally wrong ! Peter, 1. Very simply, the pulsing is to control many burners, the outputs driving air & gas valves, in an on/off fashion. (pilot light or high fire). The time spent on is determined by a pid loop, among other things. (not necessarily 40 pid loops though). All for temperature control. 2. A high speed card might be an option in future programs, but unfortunately not with those i'm currently working on. I have often thought about getting more precise with the control.. 3. ControLogix instead of CompactLogix... could be an option, but the deciding factor would always come down to $$. Hypothetically, if I used identical code in the ControlLogix, what sort of reduction in scan time could I hope to see ? Gerry, My experience with periodic tasks is limited to a handful of plc programs that are all basically the same as this one. We only started using the CompactLogix 2 (3?) years ago.. before that were a few SLCs... So, It looks like my only option at the moment is to move the code to a periodic task, and count each time it is scanned rather than using a self-resetting timer for the intervals between counts... (is that correct?) No special instructions that can give me a pulse every x ms's, or a pulse output ? Cheers, Andrew W

Share this post


Link to post
Share on other sites
With regards to the repeatibility of periodic tasks... All of my applications are motion applications. You can schedule a periodic task, and think it will hit absolutely at the desired time, but it will be interrupted by other higher priority tasks. The motion planner is the highest priority, and will interrupt all other tasks. Probably not a problem in this application. There is also the concern of event tasks - if they are a higher priority they will preempt your periodic task. A case in point - I "inherited" a really poorly written application that contained motion, a couple of event tasks, the default continuous task, and a couple of periodic tasks. The original programmer was trying to use the periodic tasks to handle a function not too unlike the case here. The task was set to fire at a 5ms interval; I found that it was hitting anywhere from 4 to 8.5 ms. You can see that just by looking at the task properties online. That's not what I call repeatible or deterministic. Not by a long shot. The moral is that you can set up your application, plan your tasks and ISRs; but don't absolutely rely on them being completely deterministic. Matt

Share this post


Link to post
Share on other sites
So these pulses are use to provide a PWM output for the PIDs? Are the PIDs running at the same interval, or multiple intervals? How often a PID is run is critical too. Unless the time constant of the system is fast you may be able to live with the 125 milliseconds if this is just a PID control problem. That is why the final goal needs to be stated. You may be able to go with what you have got.

Share this post


Link to post
Share on other sites
No it's not PWM or anything like that.. and there is no connection to the PID loops... Just one tag that is true every 1 in 40 counts, which is just used to synchronise the start, or the end, of a burst of gas & air, for example... and also to make sure each burner starts a small amount of time after the previous one, and in a particular order (staggered and spread out) The PID loops are in the periodic task, running at the same (total) time, 8 seconds. (40 x intervals = 8sec) The PID control is fine - both the code & the resultant temperature control. Yes, looks like a periodic task is the way I will have to do it for now (regardless of wether it is deterministic or not - i will soon find out how good / bad - but in any case, it will be better than a compound 125ms error!) Cheers, Andrew W

Share this post


Link to post
Share on other sites
Matt, I see your point. The originator was apparently oblivious to the internals. Likely the continuous task took an inordinately long time to complete. I also work with CLX motion applications. I have done several that contain a 20 msec periodic task whose interval varies by less than +/- 1 msec. (If I was on-line I'd quote the microseconds). Andrew, I was hoping you would post the interval variation on your 8 sec. periodic task. I don't have any hands-on experience with CompactLogix so don't know the performance, but on a L61 (for example) I would expect the variation to be measured in microseconds. A 200 msec task should be similar. Importantly for your application, the variations are small (negligible) and non-cumulative.

Share this post


Link to post
Share on other sites
Hi all, Delayed response here.. just thought I should let you guys know how I went. I put the counter on an unconditional rung in a periodic task, and got rid of the timer (the interval is now set by setting the period of the task). All working very well Thanks for the help. Cheers, Andrew W

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