Some back ground before I get into the details of the specific problem
Our model railway club has been working on building an HO scale turntable for a roundhouse and we are using a stepper motor to control the movement of the bridge of the turntable. We are using a Uno with a key pad to select the track that turntable bridge is rotate to. The stepper motor is a Longruner 17HS4401 controlled by a Stepperonline Driver, a DM542T and we are using a regulated power supply for the driver. There is no gear box attached to the motor shaft. There is a sensor attached to the turntable to provide a means to calibrate the stepper motor system to one of the tracks and to home it every time we start up the system.
In general I have been able to perform calibration, home and execute index movements of the stepper motor for the turntable movements successfully and accurately with one exception. We have set the dip switches on the driver to specify that the motor will have 6400 steps. We require this fine resolution so that we can calibrate the home track precisely to the bridge track. After that it is simple math to calculate the location of a track. We have 40 tracks around the turntable pit and we have decided to lay the track so that they are all an equal distance/angle to each other. So to move the bridge one track over we only need to move 160 micro steps ( 6400 / 40 = 160 ) to the next track.
Here's the problem.
After we have calibrated the system to find the home track, we are able to consistently and precisely move the bridge to the home track on start up of the system and always be able to index the turntable to the next track and further one or more tracks in the "clockwise" direction. However when the direction is changed and we go counter clockwise any multiple of 160 steps we are always short on the first CCW movement and it is always short by the same amount as long as we keeping going counterclockwise, no matter how many tracks we move. If we change direction again to clockwise we are short even more for the track we are moving to, but again we are consistently short the same amount if we keep going clockwise.
To compensate I added an adjustment to the movement and added 5 steps to the multiple of 160 step ( 5 + ( #tracks to move x 160 ) movement on a change of direction for the first movement in that direction. After that if a movement is made in the same direction I only calculate multiples of 160. It seemed to work, however when I tested some more on a change of direction where the movement is large.. say 3040 steps, or close to 180 degrees it appears my compensation does not work.
I have used the serial monitor to check how many steps I am telling the stepper motor to move before I added the 5 step adjustment. In the serial monitor I see correct multiples of 160 being used in the stepper.move() operations and when a change of direction occurs multiples of 160 are used but the actual motor move is short about 5 steps. So my 5 step adjustment is compensating for the stepper motor, program, system... missing 5 steps on change of direction.
So what is causing the consistent 5 step error? Why on larger moves 5 step compensation does not work. Is it code? Is it hardware?....I hope its code.
Here are the bits of code, I think are relevant. I've attached the full code below
I will provide schematic circuit diagram later, if required to diagnose the problem.
#include <AccelStepper.h> // I'm using version 1.57
AccelStepper stepper( AccelStepper::DRIVER, 4, 5 );
#define STEPSPERREV 6400 // matches the driver dip swithces used in a number of calculations
#define FULLSPEED 45.0
stepper.setAcceleration( 30.0 );
void loop()
....
stepper.move( StepsToMove ); // Calculated multiples of 160 ... if change of direction I add or subtract 5 steps to compensate for missed steps
.....
if ( isRunning
&& stepper.distanceToGo() != 0
&& stepper.speed() != 0 )
{ counter = 0;
stepper.setMaxSpeed( FULLSPEED );
while ( stepper.distanceToGo() != 0
&& stepper.speed() != 0 )
{ stepper.run();
++counter;
remainder = counter % 8; // Read the key for a stop command every 8th step. Reads are expensive and we don't want to do it too often
if ( remainder == 0 )
{ key = lcd.read(); // Read a key every 8th iteration to see if we want to force a stop
if ( key == '#' )
{ ForcedStop();
break;
}
}
}
....
YRM_Turntable_G2_V0.52.ino (27.4 KB)