Jump to content
OMRON Forums

Creating and using timers in PPMAC


mshaver
 Share

Recommended Posts

I have a process (say a specialized homing routine) running in a motion program and I want to have a watchdog timer running such that if it expires before the routine is complete I cancel the process and declare a fault.

 

I can't find anything "built in". Am I overlooking a built in method? I've read and implemented some logic I found in older posts. The examples of comparing sys.time and a value x seconds from now in a "while loop" in the same program that is the watchdog simply don't work. I built in some hooks so I could see what happens to sys.time and a done bit from the homing routine program, and neither one ever updates. The system truly is in an infinite loop and does not actually check sys.time each time it loops. I implemented an example that uses a subprogram, and this does work, but it's not even close to deterministic. Tests showed that for a 1 second timer, usually the actual time was closer to 1.5 to 2 seconds and sometimes as much as 3 to 4 seconds.

 

Am I overlooking something more native? I'm more used to controllers that have native timer objects or OOP environments such as C#, VB.net, Java, and so on that have native timer objects.

 

What about using the RTI for PLC 1 and using counters within PLC 1, starting, stopping, and clearing them from other programs? How deterministic might this approach be?

 

Anyone have more elegant solutions?

Thanks;

MShaver

mshaver@pekoprecision.com

Link to comment
Share on other sites

  • Replies 5
  • Created
  • Last Reply

Top Posters In This Topic

From an earlier post:

 

open plc 1

L1 = sys.time + 0.01;

while(L1 > sys.time) {};

p2 = p2 + 1;

close

 

// So based on the above, I wrote this as my watchdog on the homing process.

// The sends are just hooks I added to see why the thing never timed out.

// When this runs, I get the first four sends over and over hundreds of times without ever

// stopping. Keeps running long after HomeInProgress has gone to zero. It continues to return

// the same value for sys.time over and over without ever advancing.

// It is simply not obtaining an updated value for sys.time.

open plc 21

send 2,"Checking in plc 21"

send 2,"Timer1=%d\n",Timer1

send 2,"Sys.time=%d\n",Sys.Time

send 2,"HomeInProgress=%d\n",Motor[1].HomeInProgress

 

//Wait until time out or home in progress = 0

while ((Sys.Time > Timer1) && (Motor[1].HomeInProgress==0)) {}

 

send 2,"Proceeding in plc 21"

send 2,"Timer1=%d\n",Timer1

send 2,"Sys.time=%d\n",L1

send 2,"HomeInProgress=%d\n",Motor[1].HomeInProgress

 

if (Motor[1].HomeInProgress!=1) {

 

if (Motor[1].HomeComplete) {

send 2,"Motor 1 homed successfully"

}

else {

send 2,"Motor 1 homing failed"

}

 

send 2,"Exiting plc 21";

disable plc 21

}

 

if (sys.Time > Timer1) {

cmd"&1A"

send 2,"Motor 1 homing timed out"

send 2,"Exiting plc 21";

disable plc 21

}

close

 

 

// So I tried the following: Same result. The first 4 sends repeat continuously long after I know 3 seconds has elapsed and long after the home in progress has gone to zero in the status window.

open plc 21

send 2,"Checking in plc 21"

send 2,"Timer1=%d\n",Timer1

send 2,"Sys.time=%d\n",Sys.Time

send 2,"HomeInProgress=%d\n",Motor[1].HomeInProgress

 

//Wait until time out or home in progress = 0

if ((Sys.Time > Timer1) || (Motor[1].HomeInProgress==0)) {

 

send 2,"Proceeding in plc 21"

send 2,"Timer1=%d\n",Timer1

send 2,"Sys.time=%d\n",L1

send 2,"HomeInProgress=%d\n",Motor[1].HomeInProgress

 

if (Motor[1].HomeInProgress!=1) {

 

if (Motor[1].HomeComplete) {

send 2,"Motor 1 homed successfully"

}

else {

send 2,"Motor 1 homing failed"

}

 

send 2,"Exiting plc 21";

disable plc 21

}

 

if (sys.Time > Timer1) {

cmd"&1A"

send 2,"Motor 1 homing timed out"

send 2,"Exiting plc 21";

disable plc 21

}

}

close

Link to comment
Share on other sites

This worried me so I investigated. I only looked at the first case. There are a couple of issues with the logic you have used:

 

Firstly this cannot be all the code as you don't show that you start the home or how you initialise Timer1. I will assume you start the home, set Timer1=Sys.Time+3, start the PLC.

 

//Wait until time out or home in progress = 0
while ((Sys.Time > Timer1) && (Motor[1].HomeInProgress==0)) {}

should be

//Wait until time out or home in progress = 0
while ((Sys.Time < Timer1) && (Motor[1].HomeInProgress==1)) {}

you want to wait WHILE the timeout has not been reached and WHILE the home is still in progress. In your code, during the home, your while will just drop through.

 

The 7th send

send 2,"Sys.time=%d\n",L1

should be

send 2,"Sys.time=%d\n",Sys.Time

 

You say you get the first four sent messages (or what you call 'hooks') repeatedly but I found the first eight sends repeated with the bad logic. This is because during the home and timeout period your 'while' drops through and neither of the following 'if' conditions are met so the PLC executes again repeating the eight messages.

 

PLCs are effectively loops. A quick experiment shows mine running at 1000Hz. So your example was buffering out 8000 message lines a second. This looks slow in the Unsolicited window as it is catching up with these buffered messages, and appears unchanging as there are 8000 messages before Sys.Time will have a new value.

Link to comment
Share on other sites

mshaver,

 

There is a timer subroutine that works quite nicely for PLC applications. It should be in the project solution under the 'Libraries' folder (subprog2.pmc). It takes care of all the while loop nonsense, all you need to do is specify the time in seconds.

 

Usage in a plc

...
call timer (0.250);   // dwell PLC for 250msec
...

 

 

If you don't have the subroutine in your project, just add a new pmc file to your Libraries folder and add this code to it:

/****************************************/
// Sample calling timer SUBPROGRAM
//    open plc 1
//    call timer (3);  // have a 3 second delay
//    close
//
// Brad Pedersen  Sept 9th 2010
/****************************************/

open subprog timer (time)
local EndTime;
local count;

EndTime = Sys.Time + time
do count++ while (EndTime > Sys.Time)
close

 

Of course you can forgo calling the subroutine and implement this code right in your plc, adding whatever other conditionals are required.

Link to comment
Share on other sites

To DAVES: Thanks, makes much more sense now. Was obviously confused with how the DT deals with the while loops, what gets scanned what doesn't upon reentry, etc. Works great now. Was able to consolidate everything into one program now that I know and "trust" what the DT is doing in these loops.

 

To kmonroe023: Also thanks, will give this a try.

 

Different animal this PPMAC. Been programming every kind of platform under the sun for 40 years. At times the PPMAC makes me feel like I'm in my very first programming class all over again with that feeling of "What the ...

 

Thanks

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share


×
×
  • Create New...