Suppose I want to be notified when an axis/multiaxis gets a limit error (exceeds position error exceeds ErrorLimitTriggerValueGet()
). Can I turn on the RSIEventTypeLIMIT_ERROR
interrupt mask and receive an interrupt?
Which object(s) do I need to enable this on? Both the MotionController
and the Axis
? Only the axis? Do (or can) all the interrupts come in through the motion controller’s InterruptWait()
method or do I have to check on each object, too?
I’m not seeing an interrupt like this when I’ve set this via InterruptMaskOnSet()
and retrieved interrupts via MotionController::InterruptWait()
. There aren’t examples of doing this, so I’m trying to make an educated guess (but seem to be doing it wrong).
I found this in our automated tests. I believe it achieves what you are trying to do.
Hopefully this can be a use full example for you for now.
[Test]
public void InterruptTestPositionLimit()
{
const int moveid = 1234;
axis.InterruptEnableSet(true);
axis.InterruptMaskOnSet(RSIEventType.RSIEventTypeLIMIT_ERROR);
axis.MotionIdSet(moveid);
Assert.AreEqual(moveid, axis.MotionIdGet(), "Motion ID not equal, this is a problem");
Console.WriteLine("MotionId is set to: " + moveid);
axis.UserUnitsSet(1);
axis.ErrorLimitTriggerValueSet(20);
// move 30 counts in about one second
axis.MoveTrapezoidal((axis.CommandPositionGet() + 30), 1000, 1000, 10000);
Assert.AreEqual(moveid, axis.MotionIdExecutingGet(), "We commanded a motion with this ID, it should be executing.");
bool gotLimitError = false;
bool done = false;
while (!done)
{
RSIEventType myInterrupt = axis.InterruptWait(4000);
if (myInterrupt == RSIEventType.RSIEventTypeLIMIT_ERROR)
{
gotLimitError = true;
}
if (myInterrupt == RSIEventType.RSIEventTypeMOTION_DONE)
{
done = true;
Console.WriteLine("Axis Interrupt Test -- Got Motion Done");
Console.WriteLine("InterruptMotionId = " + axis.InterruptMotionIdGet());
Assert.That(moveid, Is.EqualTo(axis.InterruptMotionIdGet()), "Interrupt Motion ID does not match set value!");
}
else if (myInterrupt == RSIEventType.RSIEventTypeTIMEOUT)
{
done = true;
Console.WriteLine("InterruptTest failed with TIMEOUT");
Assert.Fail("InterruptTest failed with TIMEOUT");
}
Console.WriteLine("Axis IRQ " + myInterrupt);
Console.WriteLine("IRQ Type " + axis.InterruptNameGet());
Console.WriteLine("InterruptSourceNumber = " + axis.InterruptSourceNumberGet());
Console.WriteLine("InterruptSampleTimer = " + axis.InterruptSampleTimeGet());
Console.WriteLine();
}
Assert.That(gotLimitError, Is.True);
// this added 20070808 -- failing with exception
axis.InterruptWake();
axis.InterruptEnableSet(false);
}
1 Like
Thanks for the good example.
Does this mean that I ought to spawn separate threads (one per axis, say) to wait for and handle these interrupts? I already have a thread that waits for interrupts on the motion controller, but I won’t see the axis interrupts, right?
Yes, ideally you would have a thread for each axis.
1 Like
Thanks, @nikolas.
For the sake of offering constructive criticism, I did not find any clear direction about how to do this on the documentation portal. Here’s where I started looking:
Perhaps the problem is that I didn’t know where to start looking for information, but I couldn’t find any docs that provided any detail for the interrupt interface or how it worked. I suppose it’s a logical assumption to think that whatever object you MaskSetOn(...)
for would be the object that you Wait()
for, but I would prefer to have definitive answers as opposed to good guesses. (-8