Jump to content
OMRON Forums

Determining that a motion script has aborted


Recommended Posts

I would appreciate some advice on determining when a motion script has aborted. I am controlling the execution of the motion script from a background C program. What I've found is that when the script errors, such as if I provoke an excessive following error (FatalFeLimit), it aborts as I expect but I don't really see any difference in Coord[x].Ldata.Status. It merely changes from 0x60 to 0x01 which is what happens on a normal termination of the script. I can see that "list apc" is correctly telling me where the abort has taken place which is useful but it is an awkward method to determine programmatically that an abort has occurred. Can you suggest a simpler method ?

Thanks and regards


Link to comment
Share on other sites

  • Replies 11
  • Created
  • Last Reply

Top Posters In This Topic

Thanks for your reply, Charles. I had already tried this. Unfortunately the FeFatal error that provoked the abort, is transitory. It lasts just a few clocks and then the following error disappears as the motors are killed. There is therefore no indication in ErrorStatus (or indeed Status) that any error occurred so programmatically it is not possible to tell the difference between a normal and abnormal termination. Yet there must be some difference in internal state that indicates an abnormal termination because it is indicated by the fact that "list apc" behaves differently.
Link to comment
Share on other sites

OK, now I know what is supposed to happen I can see what is going on, although some of the things I'm doing have definitely had some unexpected and undesireable consequences.


You're correct in your guess, Sina, that I have a background plc that is monitoring my motors and reporting errors to the MMI. It's also doing some clean up that was having unexpected effects.


On detecting the following error it did the following:

1) jog/ 1..10; // Bring all the motors to a controlled stop

2) kill 1..10; // Disable all the motors

3) cmd "undefine all"; // Remove the motors from the CS


1) has the side-effect of enabling the motor with the following error and thus clearing the motor's latched following error which is why I didn't believe it was latched. My fault.


2) has the side-effect of hiding the fact that 1) had happened. As it wasn't obvious that the motor had been enabled in between the error being triggered and it being cleared.


3) I do this because its only when I enable the motor I put it in the coordinate system, so as I'm disabling all the motors in 2) I also remove them from the CS. However this has a further side-effect of disconnecting the Motor[x].Status[0] from Coord[x].Status[0] so although the motor has its FeFatal bit still set in Status[0], it no longer shows up in Coord[x].Stauts[0].


So if I remove 1) and 3) I get the Status persistent in Coord[x].Status[0] which is a good thing.


It's a shame that this sort of error is not incorporated in Coord[x].ErrorStatus. Yet this does not appear to be the case.


One final suprise that I hadn't come across previously because I have been inadvertantly clearing the motor errors with the jog/ is that when I attempt to re-enable a motor that has an error I see that all the motors that are enabled are instantly killed and I have to go and enable them again. Is this expected and indeed can I control this at all ?


Thanks again







Link to comment
Share on other sites

Graham wrote "One final suprise that I hadn't come across previously because I have been inadvertantly clearing the motor errors with the jog/ is that when I attempt to re-enable a motor that has an error I see that all the motors that are enabled are instantly killed and I have to go and enable them again. Is this expected and indeed can I control this at all ?"


Ignore this comment. Further investigation showed this was also my fault.

Link to comment
Share on other sites

I'm not sure if this is 100% correct or completely comprehensive, but this is what I do:


int CheckCSClosedLoopAndNoErrors(unsigned CSNum)
int ret=0;

if(  pshm->Coord[CSNum].MinusLimit ) ret++;
if(  pshm->Coord[CSNum].PlusLimit ) ret++;
if(  pshm->Coord[CSNum].SoftMinusLimit ) ret++;
if(  pshm->Coord[CSNum].SoftPlusLimit ) ret++;
if(  pshm->Coord[CSNum].I2tFault ) ret++;
if(  pshm->Coord[CSNum].SoftLimit ) ret++;
if(  pshm->Coord[CSNum].EncLoss ) ret++;
if(  pshm->Coord[CSNum].LimitStop) ret++;
if(  pshm->Coord[CSNum].FeFatal) ret++;
if(  pshm->Coord[CSNum].AmpFault) ret++;

if(! pshm->Coord[CSNum].AmpEna) ret++;
if(! pshm->Coord[CSNum].ClosedLoop) ret++;

return ret;


Any return of non zero meant something bad happened. Any other suggestions of what to check would be welcome but this seems to work for me in the errors I've seen pop up, including FatalFE.



Link to comment
Share on other sites

I am completely puzzled by what you were attempting to do with the PLC. Re-enabling an automatically "killed" motor not only makes it difficult to figure out why there was a problem, but is EXTREMELY dangerous, as it can lead to the runaway condition that the fault was designed to protect against.


Our "killing" faults, such as fatal following error trips, disable the motor completely because under these conditions, we believe that attempts to bring the motor to a controlled stop will fail, and in an unsafe manner. Yet you are trying to do just that. If you re-enable a motor that was killed due to following error from lost or reversed feedback, you are almost guaranteed a full-out runaway.


You have a choice as to what you want done to the other motors in the coordinate system on a "killing" fault of each motor. If bit 0 of Motor[x].FaultMode is 0, the other motors are automatically "aborted" (brought to a controlled closed-loop stop). If this bit is 1, the other motors are automatically killed as well. This choice covers just about every one.


Coord[x].ErrorStatus is just part of Coord[x].Status[0]. The ErrorStatus component is essentially for program execution type errors. You should be monitoring all of the error bits in Status[0], as KEJR is doing.


Instantly removing disabled motors from a coordinate system defeats many of our coordination, fault-sharing, and status-reporting features. You may want to rethink that strategy.

Link to comment
Share on other sites

I wouldn't mess around with monitor PLCs reporting to the HMI and all that if you are controlling this from a C program. The reason is that the C api, command interpreter, and shared memory is powerful and you can do it all from there.


I wrote a function called PmacCallMotionProgramAndWait() that starts a motion program in a coordinate system, waits for it to be done, and handles faults and restarts. Restarts on my system only occurr after an operator acknowledgment, however. You might also want to write one where the motion is triggered and then you can wait for it to be done sometime later on with another C function call. I'd post the code, but it is particular to our HMI system.


The point is that you can do all of this from C and make it modular, thus potentially eliminating mistakes.



Link to comment
Share on other sites

Thanks guys for your input, it has been very helpful.


Fundamentally I am not trying to re-enable a failed motor from inside a PLC. What I'm trying to do is implement a safety policy requirement on the machine we're building. The rule this part of the code was trying to do was on a certain type of error, (of which the following error was an example), the motion program should be aborted at the point of detection and all motors should be brought to a controlled stop where possible (clearly for the motor in fault this may not be possible).


It seemed sensible to me to have a PLC running all the time that did the monitoring as it is conceivable that such an error could occur when no motion script is running since for instance we have the ability to control motors from the HMI. This can interact with other PLCs running in our system to do the move (e.g. jog moves to start spindles etc.). So that's why I'm not doing this in background C, although I expect I could do it there.


In terms of re-enabling the failed motor, I'm not trying to do that at all. I'm trying to bring all the other motors to a controlled stop. I understand that if the motor that fails in is in a coordinate system then it can in turn cause other motors in the CS to abort. However the failed motor may not be in the coordinate system, but I still need to stop all other motors as soon as possible. I naively thought that the "jog /" followed by "kill" of all my motors would do this.


Although this is the effect I want, from your comments I believe I need a more involved approach in the motor stopping. In particular a) I musn't perform the "jog /" on a motor in error and b) since this is running in a plc context I need to wait for the motors to stop before performing the kill.


Link to comment
Share on other sites

I think you should try to build on top of our automatic safety features; presently you are fighting them. On one of our "killing" faults (following error, amp fault, I2T, encoder loss, optionally HW limit without previous SW limit), the program is automatically aborted, the offending motor is automatically killed, and the other motors in the coordinate system are either brought to a controlled stop (default) or killed (if bit 0 of Motor[x].FaultMode for the offending motor is 1). You must decide what to do with motors in other coordinate systems, and what to do with motors once they reach a controlled stop.


Remember the program commands for coordinate systems "abort" and "disable", which cause all motors in the coordinate system to be brought to a controlled stop or killed, respectively. You may want to monitor the status bits Motor[x].DesVelZero to see when the controlled deceleration has finished.

Link to comment
Share on other sites

I think that's a bit harsh to say that I'm fighting them. What I'm trying to do is implement a policy that is laid down as a safety requirement in a consistent manner. The faults that you mentioned are only a subset of the source of errors that I am handling. The error handler needs to be running all the time to monitor for error conditions and depending on a classification of the error they may estop, stop motors immediately or coast motors to a stop. Yes in the errors you mentioned the motion script is aborted automatically and the offending motors automatically killed and other motors in the coordinate system brought to a controlled stop. However in the case of other errors this won't be the case and I'll need to handle them myself. Indeed as I need to bring all motors to a stop and, as you mentioned, there is no automatic handling of motors outside the coordinate system that has faulted, I have to deal with those myself anyway. So as we Brit's say "I'm doing me best" in an unfamiliar scenario. And don't get me wrong, I very much appreciate the advice given.
Link to comment
Share on other sites

This topic is now closed to further replies.

  • Create New...