I have captured a trace direct from the circuit board stepper motor output. It makes for an interesting study as there is a visible pattern.
In the attached video you can watch the X2 motor (Top line) and the X1 motor (bottom line) run, stop and change directions - according to the script.
What is interesting is that some of the time (when it is working properly) the motors stopping in synchronisation as you expect. When it fails, you can see the X2 motor drive line go high - before the signal stops on X1 then X1 reverses direction and X2 is stalled. X2 does eventually power up again.
There is a very visible repeatable pattern. This does not look like a hardware issue. It is too repeatable for random.
What is even more interesting is the duty cycle of the failures.
It fails for 5 seconds every 20 seconds.
For those without an oscilloscope, you would be able to watch this by loosening the belts, over the X1 and X2 motor so they can spin freely. X2 simply just stop spinning.
I have studied movement.cpp and the class movementaxis.cpp and everything seems to checkout from a logical code structure point of view. (Actually it is incredibly well structured) IMHO.
This is the main axis call where the determination of X2 exists.
void MovementAxis::setMotorStep()
{
stepIsOn = true;
//digitalWrite(pinStep, HIGH);
(this->*setMotorStepWrite)();
if (pin2Enable)
{
(this->*setMotorStepWrite2)();
//digitalWrite(pin2Step, HIGH);
}
}
The issue is that pin2enable is only set or reset is the loadPinNumbers function
void MovementAxis::MovementAxis::loadPinNumbers(int step, int dir, int enable, int min, int max, int step2, int dir2, int enable2)
void MovementAxis::MovementAxis::loadPinNumbers(int step, int dir, int enable, int min, int max, int step2, int dir2, int enable2)
{
pinStep = step;
pinDirection = dir;
pinEnable = enable;
pin2Step = step2;
pin2Direction = dir2;
pin2Enable = enable2;
pinMin = min;
pinMax = max;
}