I get an occasional error when running through my homing routine in a system with 23 axis.
These are Kollmorgen AKD drives.
Each axis homes on its own Thread, and I have been starting them all at roughly at the same time.
Here is the error that is occasionally thrown:
“Timeout Timed out trying to write Service Channel (SDO) (Error 10) (RapidCodeNetworkNode::ServiceChannelWriteCore) (Object 40) (File rapidcodenetworknode.cpp) (Line 450) (Version 10.2.2.0)”
I tried adding a 10ms wait between starting each thread and it seemed to make no difference.
Could anyone help with what may be causing this error and what we can do to prevent it?
Thanks!
public void HomeMethod()
{
try
{
if (Settings.Any(s => s.Disabled)) return;
lock (_isHomedLock)
_isHomed = false;
Error = false;
var laneNames = string.Join(", ", Settings.Select(s => s.Name).ToList());
NewMessage($"Homing Initializing {laneNames}...", null);
// 1. READY DRIVE
Axis.OperationModeSet(RSIOperationMode
.RSIOperationModeHOMING_MODE); // Mode of Operation set to Homing Mode.
Axis.NetworkNode
.AKDASCIICommand(
"DRV.OPMODE 2"); // Sets the drive operation mode (0 - current | 1 = velocity | 2 = position).
Axis.NetworkNode
.AKDASCIICommand(
"HOME.AUTOMOVE 0"); // 0 = Disabled | 1 = Homing starts when drive is enabled.
// Make sure you know your motor's position, velocity, and acceleration units before you send any values.
// 2. SET YOUR LIMIT SWITCHES
Axis.NetworkNode
.AKDASCIICommand(
"DIN1.MODE 0"); // Sets the digital input modes. - DI1 is now our Home Switch.
Axis.NetworkNode
.AKDASCIICommand(
"DIN1.INV 0"); // Sets the indicated polarity of a digital input mode. - DI1 is now active when High.
Axis.NetworkNode
.AKDASCIICommand(
"DIN2.MODE 0"); // Sets the digital input modes.
Axis.NetworkNode
.AKDASCIICommand("DIN2.INV 0"); // Sets the indicated polarity of a digital input mode.
Axis.NetworkNode
.AKDASCIICommand(
"DIN3.MODE 11"); // Sets the digital input modes.
Axis.NetworkNode
.AKDASCIICommand("DIN3.INV 0"); // Sets the indicated polarity of a digital input mode.
// 3. CONFIGURE DRIVE HOMING PARAMETERS
Axis.NetworkNode
.AKDASCIICommand(
"HOME.MODE 16"); // Selects the homing method; active in opmode 2 (position) only. MODE 16 = Find Home switch using dual edges
Axis.NetworkNode
.AKDASCIICommand(
"HOME.V 0.2"); // Sets homing velocity; active in opmode 2 (position) only.
Axis.NetworkNode
.AKDASCIICommand(
"HOME.ACC 1"); // Sets homing acceleration; active in opmode 2 (position) only.
Axis.NetworkNode
.AKDASCIICommand(
"HOME.DEC 1"); // Sets homing deceleration; active in opmode 2 (position) only.
Axis.NetworkNode
.AKDASCIICommand(
"HOME.DIR 1"); // Sets homing direction; active in opmode 2 (position) only. (0 = negative | 1 = positive)
Axis.NetworkNode
.AKDASCIICommand("HOME.P 0"); // Sets home position; active in opmode 2 (position) only.
Axis.NetworkNode
.AKDASCIICommand(
"HOME.DIST 0"); // Sets homing distance; active in opmode 2 (position) only.
Axis.NetworkNode
.AKDASCIICommand(
"HOME.MAXDIST 0"); // Sets the maximum distance the motor is allowed to move during the homing routine. (Disabled when value = 0)
Axis.NetworkNode
.AKDASCIICommand(
"HOME.IPEAK 6"); // Sets the current limit during homing procedure to a mechanical stop; active in opmode 2 (position) only.
// 4. READY AXIS
Axis.ErrorLimitActionSet(RSIAction.RSIActionNONE);
Axis.Abort(); // Disable axis.
Axis.ClearFaults(); // Clear any faults.
Axis.AmpEnableSet(true); // Enable the axis.
Thread.Sleep(100); // Allow time for amp enable
NewMessage("Homing Started...", null);
lock (_cancelHomingLock)
{
if (_cancelHoming)
throw new Exception("Homing Cancelled");
}
// 5. START HOMING
Axis.NetworkNode
.AKDASCIICommand(
"HOME.MOVE"); // Starts a homing procedure; active in opmode 2 (position) only.
var now = DateTime.UtcNow.ToLocalTime();
var timeout = now.AddSeconds(10);
// 6. CHECK IF HOMING IS DONE
var isHomedvalue = 0;
var isHomeErrorValue = false;
while (isHomedvalue != 1 &&
DateTime.UtcNow.ToLocalTime() < timeout) // When isHomedValue = 1, homing has finished.
{
var statusWordValue = Axis.NetworkNode.StatusWordGet(Settings[0].AxisIndex);
isHomedvalue =
statusWordValue >>
12; // Get the 12th bit only. This bit tells us homing is done when it goes HIGH.
isHomeErrorValue =
(statusWordValue >>
13) == 1; // Get the 13th bit only. This bit tells us homing is in error when it goes HIGH.
lock (_cancelHomingLock)
{
if (_cancelHoming)
{
Axis.Stop();
Axis.AmpEnableSet(false);
throw new Exception("Homing Cancelled");
}
}
if (isHomeErrorValue) break;
}
Error = DateTime.UtcNow.ToLocalTime() >= timeout || isHomeErrorValue;
NewMessage($"Homing {(Error ? "Failed" : "Successful")}", null);
// 7. CLEAN UP
Axis.OriginPositionSet(0.0);
Axis.Abort(); // Disable the axis.
Axis.OperationModeSet(RSIOperationMode
.RSIOperationModeINTERPOLATED_POSITION_MODE); // Mode of Operation Restore
Axis.ErrorLimitActionSet(RSIAction
.RSIActionNONE); // Restore the position error action to whatever you want it to be.
Axis.ClearFaults();
Thread.Sleep(100);
HelperFunctions
.CheckErrors(Axis); // [Helper Function] Check that the axis has been initialize correctly.
Axis.ClearFaults();
lock (_cancelHomingLock)
{
Axis.AmpEnableSet(!_cancelHoming);
if (_cancelHoming)
throw new Exception("Homing Cancelled");
}
Axis.MoveRelative(Settings[0].HomingOffset, 1.0, 1.0, 1.0, Settings[0].JerkPct);
Axis.MotionDoneWait(10000);
var homed = Axis.StateGet() == RSIState.RSIStateIDLE;
lock (_isHomedLock)
_isHomed = homed;
NewMessage($"Homing {(homed ? "Complete" : "Fault")}. Axis State: {Axis.StateGet()}", null);
}
catch (Exception e)
{
Error = true;
NewMessage(
$"{MethodBase.GetCurrentMethod().Name} AxisIndex: {Settings[0].AxisIndex} Error: {e.Message}",
new HomingSequenceError($"Homing Exception for {Settings[0].Name}", e.Message));
}
lock (_cancelHomingLock)
{
_cancelHoming = false;
}
}
I believe the problem is occurring when you call Axis.OperationModeSet in the first case and Axis.NetworkNode.ServiceChannelWrite to do the same thing in the second.
It sounds like there are some cases where your drive is slow to transition or somehow fails to transition modes. I see three different patterns.
(1) 1. READY DRIVE.
Here you don’t seem to be doing anything to interrupt other possible motion. I’d Abort(); ClearFaults(); first something you do in stage 4. You can move those lines up to the start of 1.
(2) 7. CLEAN UP
Here you Abort(); Switch Modes. ClearFaults();
(3) 2nd example
Here you Abort(); ClearFaults(); Switch Modes.
Can you tell when you get the failure when using your Public HomeMethod does Homing actually take place? This would determine if the failure was (1) or (2) or both?
When in the failure state if you check the Mode of Operation does it ultimately succeed or fail? Compare the desired/actual (0x6061) If it does slowly get there, we can use overloads for extra time if needed.
Jacob,
I am not sure exactly where the error was happening at.
This code has been running unchanged for a couple of months while running testing, but after some changes in the higher level control system last week, we began to see this error pop up.
I cannot confirm whether the Axis was able to finish homing after the Exception was raised. The operator has been restarting the system whenever they saw the error.
As soon as I can take the system down, then I will try to run some tests to see if we can pinpoint a problem.
You may be able to prevent it by switching to Axis.OperationModeSet to Axis.NetworkNode.ServiceChannelWrite while using a longer timeout overload. You could try it with a long timeout to see if that prevents the problem from occurring completely.
Today I updated and ran the application using the Axis.NetworkNode.ServiceChannelWrite() method in both homing routines.
I set the timeout to 1000msec.
I did not see any more homing errors after testing it through about 5 system restarts.
It looks like this has resolved this issue.
If not, then I will update this thread.
Thanks!