Sketch written for 6400 mircrosteps, only works if driver configured to 3200

31 views
Skip to first unread message

Andris Cuksts

unread,
Jan 5, 2026, 1:02:57 PM (6 days ago) Jan 5
to accelstepper
I belong to a model railway club and have been working on building 2 turntables using a stepper motor and motor driver controlled by an Arduino using the Accelstepper library as means to index the bridge of the turntable to one of 40 tracks in the round house.  I am close to achieving the goal but have run into 2 issues.

The first issue. I have written my Arduino sketch for the stepper motor to rotate the steeper motor 360 degrees in 6400 micro steps. This is to to provide a high degree of accuracy when calibrating the motor to the home track and when the bridge is moved to other tracks the bridge will align with the roadhouse tracks as well.  Currently we are aiming for 9 degree move from track to track for 160 micro step move.   ( 6400 / 40 tracks = 160 ).     I have set the dip switches on the driver to 6400 micros steps to match the sketch  Unfortunately the motor only moves half as far as expected when moving from one indexed track to the next. 
When I set the driver to 3200 the indexing works...almost.  

So I could leave it as is because it seems to work, however when rotating the bridge 360 degrees during testing after moving the bridge a 3rd full 360 degree rotation in the same direction the bridge starts going out of alignment enough to derail the engines going on and off the bridge.  Interestingly if I rotate the bridge 3 times 360 degrees in the opposite direction the alignment issue goes away.

The program is designed so all the user has to do is tell the Arduino which track it wants the bridge to move to and program determines the shortest rotation to get there.  So in order for me to do a 360 for the bridge I have to move twice to  another track before I enter the track number where I started from.

I have added a number of print statements in my sketch verifying that I am indeed telling the driver via the library functions to move the number of steps I am expecting it to go.  I use the run function to move the stepper.  I checked the values returned by distanceToGo and currentPosition immediately after the run function is executed in the loop and the expected values are being returned. 

I am using the following hardware.   I have switched in and out spare uno boards, motors and the DM556D drivers,  no difference in results

Arduino board : SparkFun RedBoard Uno
Stepper motor : Oriental motor PKP246MD15A2 2-phase Bipolar Stepper Motor
                Correspondence with Oriental tech support indicated the 6400 steps/revolution can be achieved with this motor.
Driver ( I tried 2 different ones both with the same results )
          Driver 1 : Oriental motor driver for 2-phase motor CVD223FBR-K
          Driver 2 : Sourced from L-Star Motor a DM556D Stepper motor driver

The following is some of the relevant code from the sketch.  I also tested the run loop in the below sketch without the lcd.read to see if it was interfering with anything, again no change in behavior.

AccelStepper stepper( AccelStepper::DRIVER, 8, 9 );

#define FULLSPEED 60.0

stepper.setMaxSpeed( FULLSPEED );
stepper.setAcceleration( 30.0 );

....
 stepper.move( StepsToMove );
....
....
      if ( isRunning
           && stepper.distanceToGo() != 0
           && stepper.speed() != 0 )
      { counter = 0;
        stepper.setMaxSpeed( FULLSPEED );
        PowerOff(LastTrack);
        PowerOn(Track);
        LastTrack = Track;
        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 to often
          if ( remainder == 0 )
          { key = lcd.read();         // Read a key every 8th iteration to see if we want to stop
            if ( key == '#' )
            { ForcedStop();
              break;
            }
          }
        }

And lastly I have checked and rechecked to ensure the wiring between the Arduino and driver is correct and the wiring from the driver to the motor is correct.
Pin 8 is for the pulse and connected to the -Pulse terminal on the driver.
Pin 9 is for the direction and connected to the -Direction terminal on the driver.
5 volts is being supplied from the Arduino to the +Pulse and +Direction terminals on the driver.

A separate power supply is providing 24 volts to the driver.
Four wires are connected from the driver to the motor with matching A+ A- B+ and B- terminals at both ends

Any help or suggestions to debug the program or hardware would be greatly appreciated.

gjgsm...@gmail.com

unread,
Jan 7, 2026, 8:34:17 PM (4 days ago) Jan 7
to accelstepper
Hello Jonel,

Thanks for your post. Despite some complexity to your project, positioning the turntable using Accelstepper library is very doable. Unfortunately, because there are many factors involved, without the whole program(sketch) in its entirety it will be very difficult to give an effective response.
Because you have the basic setup working and based on the information you have given FWIW I offer a couple of observations which may or may not be influencing the issue.

1. The ‘while’ run loop is busy. Even though you tested without it, lcd.read() could still be an issue. There are other ways to minimise or elliminate potential stepping issues.

2. The PKP246MD15A2 motor (NEMA 42) is rated at 1.5 A/Phase.
     The DM556 driver lowest current setting is:  Peak 2.1A / RMS 1.5A
     Your dip switch settings should be: 1=ON, 2=OFF, 3=OFF, 4=ON, 5=OFF, 6=ON, 7=OFF, 8=ON.
     Excessive current can magnetically saturate the motor's core, which can reduce the effective torque.
     Check if the motor is getting hot after running for some time.

3. The PKP246MD15A2 motor is rated at 116 oz-in max holding torque that’s only ≈ 167 grams of force at a 50 cm radius.
EXAMPLE Torque calculation:
Assuming you are direct driving a 1 metre diameter turntable accomodating 40 tracks which has a certain mass and then add the mass of a train engine giving, lets say a conservative total of 1000gms at 50cm then allow for 25% motor and transmission losses you end up with a force of ~ 100gms pushing a 1000gm mass. Even though your acceleration is low at 30 m/s/s the motor may still be unable to handle it and there could be the potential for missed steps during the acceleration phase. Check for missed steps by running a dedicated step counting function or sketch.

4. Also, keep in mind the maximum speed (stepping rate) for an UNO/Red board is only ~4000 steps/sec.

Geoff

Jim Larson

unread,
Jan 8, 2026, 12:18:48 AM (4 days ago) Jan 8
to accelstepper
I've spent some time thinking about this problem since it was posted and have not had any moments of insight. While Geoff's response hits some of the known gotchas, I don't think it really nails the problem. To me, the key point is that the original position is lost after 3 rotations in one direction, then recovered after three the opposite direction. I cannot account for this behavior, and any behavior that would result in loss of steps or slippage will not account for it either. While I can't offer a solution, perhaps you could gather a little more information.
- Try moving one track at a time. Does the same result happen?
- Have you checked carefully that the target track for the 360 degree rotation is positioned exactly where it should be and not off by some small amount? That could cause a slow shift which would be restored by reversing the positioning direction, I think.
- Can you repeatedly rotate 360, then back without any loss of position?
- What happens if you rotate 360 four times? Is the error even worse, or does it lessen?

Perhaps those actions will be useful, if only to suggest some things to try that might *really* help.

Wish I could be more helpful.

                  -jim

Andris Cuksts

unread,
Jan 10, 2026, 1:55:19 PM (yesterday) Jan 10
to accelstepper
Geoff,
    thanks for the response.  

I've attached the entire copy of the sketch in this note for you to review.  There is also second sketch that is executed in a second Arduino that is in a hand held controller.   Not sure you need that one.    I have also attached a photo of the DM556D that shows the documented switch settings.

1.   When I tested it without the read I also removed tests and counters. The code looked like this.  I can't see how it could be any simpler.


        while ( stepper.distanceToGo() != 0
                && stepper.speed() != 0 )
              stepper.run();
         
 Is there another way to interrupt the loop, so that if someone entered the wrong track or head or tail instruction they could stop the turn table?

2.  For the dip switch settings for power I have set it to 1=ON, 2=OFF, 3=OFF for all my tests as you have recommended.   I set 4 to both ON and OFF while testing to see if either makes a difference.  I have noticed no change in behaviour.  

Now Dip switches 5 6 7 8 are interesting.   You have recommended  5=OFF, 6=ON, 7=OFF, 8=ON.    If you take a look at my photo of the DM556D driver you will see that it says that that setting is for 12800 pulse per revolutions.  What works for me is 5=OFF, 6=OFF, 7=ON, 8=ON which corresponds to 3200 even though I coded for 6400.    
I have tried 5=ON, 6=OFF, 7=ON, 8=ON which the driver faces says it is 6400, but when it is set to that value I only go half as far as expected 4.5 Degrees for 160 steps not 9 degrees.

I have checked if the motor is getting hot.  It is warm but not hot to the touch.

3.  The bridge of the turn table is small only around 12" and when I have done the 360 degree tests, I have done it without an engine being on the turntable.

I used the functions distanceToGo and currentPosition along with the print function to the serial monitor to see if I was getting reasonable and expected values.  While doing the loop, the first value returned for distanceToGo was 159 and when it finally stopped was 0.  About 300 values where returned so almost 2 values per execution of the run function.

4.  The bridge is moving slowly.  I am not even close to doing 4000 steps/second I'm in the range of 160 steps/second.

Hope this provides more info

Andris
YRM London turntable driver.HEIC

gjgsm...@gmail.com

unread,
Jan 10, 2026, 7:06:55 PM (yesterday) Jan 10
to accelstepper

Thanks Andris,

I can see one issue straight away. I’ve attached an image of one of my DM556 drivers and you will see the dip switch settings are different. I suspect your driver should have the same settings as mine printed on your driver, it would explain why you are getting 3200 steps/rev when you try to set it for 6400.

I have included a test program (adapted roughly from the 'Bounce' example) to independantly check your setup for missed steps, it’s pretty self explanatory. It will also verify the step resolution setting of your driver. The serial monitor output will only show the step count coming from the driver. It won’t tell you if there is a missed step, that can only be detected by observing the turntable reaching each of its targets and returning accurately to the starting point ie ‘step 0’.

I have tested this program successfully with an identical setup, red board mcu, nema 42 motor, DM556 driver.

To get an accurate picture of what is happening try it with different settings, speed, acceleration, steps/rev, etc… and observe for missed steps which can be caused by mechanical, motor driver fault, noise on the ground plane (more on that later) and software issues. While you verify your setup I’ll have a look at your code which, BTW does not appear to be attached.

Yes, a button tripping an ‘interrupt’ can be used to stop the turntable at any time, if you would like help with that let me know.

IMG_4208.jpeg

```
#include <AccelStepper.h>

// Define pin connections
const int stepPin = 2;  // Connect to STEP on DM556D
const int dirPin = 3;   // Connect to DIR on DM556D

// Create stepper instance
// AccelStepper::DRIVER means Step/Dir interface (1 = step, 2 = direction)
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

// Motor parameters
const int stepsPerRev = 3200;
const int stepsPerTrack = 80;

// Track Target positions
const long track1 = stepsPerTrack;        // 80 steps
const long track10 = stepsPerTrack * 10;  // 800 steps
const long track19 = stepsPerTrack * 19;  // 1520 steps
const long track31 = stepsPerTrack * 31;  // 2480 steps
const long track40 = stepsPerTrack * 40;  // 3200 steps

// Step count variables
long track1_StepCount = 0;
long track10_StepCount = 0;
long track19_StepCount = 0;
long track31_StepCount = 0;
long track40_StepCount = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);
 
  Serial.println("=== AccelStepper Bounce Test ===");
  Serial.println("Starting position: 0");
 
  // Configure stepper
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(50);
  stepper.setCurrentPosition(0);
 
  // Bounce Cycle 1: 0 -> track1 -> 0
  Serial.println("\n--- Bounce 1: Track 1 ---");
  stepper.moveTo(track1);
  runToTargetAndCount(track1_StepCount);
  stepper.moveTo(0);
  runToTargetAndCount(track1_StepCount);
 
  // Bounce Cycle 2: 0 -> track10 -> 0
  Serial.println("\n--- Bounce 2: Track 10 ---");
  stepper.moveTo(track10);
  runToTargetAndCount(track10_StepCount);
  stepper.moveTo(0);
  runToTargetAndCount(track10_StepCount);
 
  // Bounce Cycle 3: 0 -> track19 -> 0
  Serial.println("\n--- Bounce 3: Track 19 ---");
  stepper.moveTo(track19);
  runToTargetAndCount(track19_StepCount);
  stepper.moveTo(0);
  runToTargetAndCount(track19_StepCount);
 
  // Bounce Cycle 4: 0 -> track31 -> 0
  Serial.println("\n--- Bounce 4: Track 31 ---");
  stepper.moveTo(track31);
  runToTargetAndCount(track31_StepCount);
  stepper.moveTo(0);
  runToTargetAndCount(track31_StepCount);
 
  // Bounce Cycle 5: 0 -> track40 -> 0
  Serial.println("\n--- Bounce 5: Track 40 ---");
  stepper.moveTo(track40);
  runToTargetAndCount(track40_StepCount);
  stepper.moveTo(0);
  runToTargetAndCount(track40_StepCount);
 
  // Report results
  Serial.println("\n========== RESULTS ==========");
  Serial.print("Track 1 Total Steps:  "); Serial.println(track1_StepCount);
  Serial.print("Track 10 Total Steps: "); Serial.println(track10_StepCount);
  Serial.print("Track 19 Total Steps: "); Serial.println(track19_StepCount);
  Serial.print("Track 31 Total Steps: "); Serial.println(track31_StepCount);
  Serial.print("Track 40 Total Steps: "); Serial.println(track40_StepCount);
  Serial.println("=============================");
  Serial.println("\nTest Complete!");
}

void loop() {
  // Nothing runs in loop
}

// Function to run motor to target and count steps
void runToTargetAndCount(long &stepCounter) {
  long startPos = stepper.currentPosition();
 
  while (stepper.distanceToGo() != 0) {
    stepper.run();
  }
 
  long endPos = stepper.currentPosition();
  long stepsTaken = abs(endPos - startPos);
  stepCounter += stepsTaken;
 
  Serial.print("Target: "); Serial.print(stepper.targetPosition());
  Serial.print(" | Steps taken: "); Serial.print(stepsTaken);
  Serial.print(" | Current position: "); Serial.println(endPos);
}
```

Geoff

Andris Cuksts

unread,
4:32 PM (7 hours ago) 4:32 PM
to accelstepper
Geoff,
    thanks I will give a try at the club this week.     Also I attached the folder rather than the file.  Let's see if I get it right this time.

Also just to be clear, I have a DM556D and and your Driver is a DM556.  Not sure what the difference between the two other than the likely mistake on the pulse settings.

Andris
YRM_Turntable_London_G2_V1.9.ino

gjgsm...@gmail.com

unread,
6:51 PM (4 hours ago) 6:51 PM
to accelstepper
Andris,
It looks like the file V1.9 opens up ok, thanks. Yes I am aware they are different models but your driver's 'puls/freq' settings seem to be behaving more like my driver.  DM556D and DM556 are functionally the same class of digital stepper driver, the D version is usually a slightly newer retuned variant with smoother microstepping, many sold online are generic clones with inconsistent specs.
Reply all
Reply to author
Forward
0 new messages