I have a pretty simple script that I'm using to control the RPM of my stepper motor:

void loop(){ 
  digitalWrite(PIN, HIGH);
  digitalWrite(PIN, LOW);

as you can see it's just producing a pretty standard pulse, I have my Arduino connected to a driver that manages the motor. The wait variable comes from a second order equation I derived from measuring the RPM with a Tachometer and tweaking the value.

// From data RPM = 31729/x + 17.327 thus x = 31729/(RPM-17.527)
wait = M/(RPM-C);

It works pretty well, I get readings consistently within only 1 - 2 rotations off. But the slope and intercept seem completely arbitrary to me. Is there a chance it has to do with the clock speed of the Arduino? I'm using an Uno and from playing around with the numbers I can't seem to find a relationship. From what I can tell, the driver looks hardwired so I don't think it has much to do with the equation.

Any idea what these values, the slope/intercept mean?

Equation: RPM = 31729/wait + 17.327

  • \$\begingroup\$ This question can't be answered unless you specify which "slope" and "intercept" you're looking at. Also, your loop will heep the line high most of the time, and have a very short "off" period while the loop() function re-starts. Is that what you intend? \$\endgroup\$
    – Jon Watte
    Apr 29, 2014 at 23:29
  • \$\begingroup\$ I initially had 2 delays but it gave a less consistent RPM reading. I put the values in the arduino code comment but I'll make it more explicit. \$\endgroup\$ Apr 30, 2014 at 0:06
  • \$\begingroup\$ Are you driving the motor when the PIN is High or when it is Low? In other words which is your "drive" pulse and which is your "dwell" time? \$\endgroup\$
    – FiddyOhm
    Apr 30, 2014 at 0:19
  • \$\begingroup\$ HIGH drives. Low causes the driver to switch states. As for the equation, Im not asking anyone to solve a problem, just asking for a high level relationship. \$\endgroup\$ Apr 30, 2014 at 0:24
  • \$\begingroup\$ What stepper driver are you using? When you say "I have my Arduino connected to a driver that manages the motor" I assume that means you have a driver that accepts direction and step inputs and handles sequencing the coils automagically. Do you have micro-stepping enabled? \$\endgroup\$ Apr 30, 2014 at 15:34

3 Answers 3


The slope is related to the number of steps it takes your motor to make 1 revolution.

For example, common steppers I've worked with take 200 steps per revolution. If you want to rotate at 100 RPM, then you have to give (100 * 200) steps every minute, or 333.33 steps per second. If you want 50 RPM, then its (50 * 200)/60 = 166.7 steps per second.

The number of steps per second is controlled by your [wait] time. The longer you wait, the fewer steps per second you get.

I'm not sure why you got the offset value you did. That implies that if your wait was infinite, (0 steps per second) your stepper would still be turning 17 RPM. That clearly can't be true. I suspect some measurement error.

I recommend looking at the data sheet for your stepper driver. It should specify minimum and maximum pulse widths and dwell time for the step signal. With the tight loop you have, there's a chance you're violating those specs and the behavior of the driver is unpredictable.

  • \$\begingroup\$ I think you make the most valid point that the C has to be an error term. Furthermore, directing me to my data sheet was a solid call on your part. The others have valid points, but flawed in slight ways \$\endgroup\$ May 1, 2014 at 19:54

I think what you are finding with your linear equation is the same thing you could observe with a very simple test set-up using a pulse generator and amplifier to drive the motor "manually". There are two effects taking place in the stepping motor.

First: Assuming the motor is at rest on one of its poles, it is being held there by the remnant magnetism of the pole pieces comprised of the stator and rotor. In order to get the rotor to break away from this condition, it must be activated for a certain amount of time with a certain amount of force. The force comes from the current driven thru the coil(s), and will of course be variable with the magnitude of that current. The TIME has to be long enough to overcome the attractive force of the current (i.e. present) rotor position to the pole and also long enough that the inertia developed in the rotor by the applied force will allow it to "jump" or "coast" or be magnetically attracted to the next pole, in sequence, by that "target" pole's remnant magnetism. This is the fixed "C" factor in your equation.

What is lacking in your equation is the magnitude of the applied current and the "force factor" of your stepper motor. That is, how the magnitude of the electric current is converted to a magnitude of magnetic attractive or repulsive force. You would have to figure this out empircally in a similar manner to how you have figured out your present equation. You would probably end up with a family of equations, one for each drive current. If you plan on using a fixed drive current, your single equation will be adequate.

Once you have enough minimum drive pulse width to get the stepper motor to "jump" poles, the rest is merely repetition rate. That is, how often you apply the pulses to the drive coils. That's your "M" coefficient.

As another commenter has pointed out you are "lacking" a second delay in your loop. At least by traditional methods of this type of timed drive scheme. Nonetheless, your drive scheme has a "Drive - Delay with Drive - Very Fast Idle - Drive - Delay with Drive - Very Fast Idle - etc..." sequence. Since your Idle command is merely stepping the drive sequencer to its next drive state, you are never allowing the rotor to come to a complete stop. Or, the amount of time it is stopping is being dictated by the amount of time the Drive pulse is "over driving". That is, the time the coils are being driven while the rotor is properly positioned over the "target" pole. This produces uneccessary heat because it is producing no rotor motion, just resistive loss in the coils. If you include that additional dwell delay in your loop you will likely find that you are expending less energy to rotate the motor. You will also have to recalculate your "M" coefficient, and maybe even your "C" offset factor. The additional delay provides a defined idle time.

If you have a strobe light you can learn a lot about the rotor movement with respect to your drive pulses by attaching a disk to the rotor shaft, marking the disk with a few equally spaced white "spoke" marks, and then triggering the strobe light from your drive pulses, or from auxilliary microcontroller output pulses which you can vary with respect to the main drive pulses.

By "properly" I mean smoothly, quietly and efficiently. "Smooth" means the radial motion is linear and not a jerky stop-&-stop sequence. "Quietly" means the motor is not chattering as it runs because it is not running smoothly. "Efficient" means you are allowing only enough drive time to get the motion you need and not "overdriving" (as I described above) and thereby merely adding additional heat to the motor and wasting supply current and energy. Part of the art of applying stepper motors is determining which of these three performance factors are important to your specific application and tailoring the drive profile to optimize these operational qualities of smoothness, quietness and efficiency.

Good Luck!


So, by "slope" and "intercept" you really mean the constants in your inverse relation? They mean that those are the best fit parameters for whatever function you're using.

The constant part likely comes from the fact that operations other than delayMicroseconds() take time for each cycle, although I would expect that to be negative in a "perfect" formula.

The scalar part comes from the number of microseconds in a minute, and from the number of steps per revolution in your motor (and, if enabled, microstepping in the controller.)

To turn the equation around: Let's say your motor has N steps per revolution, and your controller microsteps by M microsteps per step. Further, there are 60,000,000 microseconds in a minute. The "perfect" RPM formula given a delay (in microseconds) between pulses is then:

RPM = 60,000,000 / (N * M * delay)

You can factor this out as:

RPM = (60,000,000 / (N * M)) / delay

So, in your equation, 60,000,000 / (N * M) appears to be 31792, although I still think your curve fitting has some error.

In typical systems design, you will start with the data sheets for your driver and motor, and work forwards to the RPM you need. As long as you don't overload your stepper (and miss steps) then the system is fully deterministic. There are various ways to avoid overloading steppers, including using acceleration curves, characterizing load suitably, etc.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.