Page 1 of 1

Stepper velocity tolerance

Posted: Thu May 04, 2017 2:39 pm
by markrages
Hi,

I am using the 1067_0 board for controlling the velocity of a stepper motor.

When I command 60 RPM, I measure an actual cadence of 60.685 RPM, averaged over 60 revolutions, with a standard deviation of 0.387 RPM.

I do not see a specification for how accurate the velocity control of this board is. But it is apparently generated from a microcontroller with an accurate crystal reference, so I was hoping velocity could be controlled with better than 1% accuracy. Is this not the case?

I am using setVelocityLimit() in the Python interface. I measure actual velocity with a magnetic proximity sensor and frequency counter / period timer.

Regards,
Mark

Re: Stepper velocity tolerance

Posted: Thu May 04, 2017 4:13 pm
by Patrick
Velocity resolution is 1 1/16 steps/sec - you would have to convert to RPM with actual steps/revolution to know the RPM resolution. Timing is very consistent/precise, otherwise USB wouldn't work, or the stepper would misstep, etc..

-Patrick

Re: Stepper velocity tolerance

Posted: Thu May 04, 2017 8:02 pm
by markrages
Patrick wrote:Velocity resolution is 1 1/16 steps/sec - you would have to convert to RPM with actual steps/revolution to know the RPM resolution. Timing is very consistent/precise, otherwise USB wouldn't work, or the stepper would misstep, etc..

-Patrick
OK, interesting. The DLL takes a double-precision float for the velocity value. So how does the DLL round to integer? The rounding error will be greater at lower RPM.

I forgot to mention, I'm using a 200 counts/rev motor. (I think it's a 3331_0, but there's no nameplate.)

Re: Stepper velocity tolerance

Posted: Fri May 05, 2017 9:44 am
by Patrick
3331 has a 1.8° step angle, so that's 200 steps/rev or 3,200 1/16th steps/rev.

For 60 RPM, you need 192,000 1/16th steps/minute or 3,200 1/16th steps/second.

So, if you set your velocity limit to 3200, you should be getting exactly 60 RPM.

Also, don't forget to consider acceleration - you should only measure your RPM when the motor is actually turning at the velocity limit.

-Patrick

Re: Stepper velocity tolerance

Posted: Mon May 08, 2017 4:24 pm
by markrages
Patrick wrote:3331 has a 1.8° step angle, so that's 200 steps/rev or 3,200 1/16th steps/rev.

For 60 RPM, you need 192,000 1/16th steps/minute or 3,200 1/16th steps/second.
I peeked at the C source and made the following script, which gives this output:

Code: Select all

stats for 200 step motor
========================

1062_1 STEPPER_UNIPOLAR_4MOTOR
                     max speed = 57.4875 RPM
  max speed quantization error = 0.1125 RPM

1063_1 STEPPER_BIPOLAR_1MOTOR (old bipolar board)
                     max speed = 614.4 RPM
  max speed quantization error = 0.15 RPM

1067_0 STEPPER_BIPOLAR_1MOTOR_M3 (new bipolar board)
                     max speed = 4687.5 RPM
  max speed quantization error = 0.01875 RPM
But in my application I am seeing about 10x the error I calculated above. I am measuring the period at constant RPM, so there should be no acceleration in the measurement.

Here is the script:

Code: Select all

#!/usr/bin/python

"""
Constants from cphidgetstepper.c
"""

class StepMotor(object):
    def closest_speed(self, desired):
        "Tells what speed to request to get closest to desired speed."
        i = self.int_speed(desired)
        actual = self.back_calc(i)
        actual1 = self.back_calc(i+1)
        if abs(actual1 - desired) < abs(actual - desired):
            return actual1
        else:
            return actual

    def int_speed(self, speed):
        return int(self.speed_range * speed/self.speed_max)

    def back_calc(self, int_speed):
        return int_speed * float(self.speed_max) / self.speed_range

    def speed_to_rpm(self, speed, motor_steps=200):
        return 60. * speed / (self.microsteps * motor_steps)

    def max_speed_quantization_error(self):
        "in steps / second"
        return self.back_calc(1.)

    def __repr__(self):
        return " ".join((self.number,self.name))

    def print_stats(self, motor_steps=200):
        print self
        print "                     max speed =",self.speed_to_rpm(self.speed_max,motor_steps),"RPM"
        print "  max speed quantization error =",self.speed_to_rpm(self.max_speed_quantization_error(),motor_steps),"RPM"
        print

class Motor_1062(StepMotor):
    name = "STEPPER_UNIPOLAR_4MOTOR"
    number = "1062_1"

    microsteps = 2
    accel_max = (250 * (0.75 * 0.75)) * 0x3f # 8859.375
    accel_min = (250 * (0.75 * 0.75)) # 140.625
    speed_max = ((microsteps * 0x100) - 1) * 0.75; # 383.25

    accel_bits = 6
    speed_bits = 9
    speed_range = (1<<speed_bits) - 1

class Motor_1063(StepMotor):
    name = "STEPPER_BIPOLAR_1MOTOR (old bipolar board)"
    number ="1063_1"

    microsteps = 16
    accel_max = 4000 * 0xff # 1020000 # one million twenty thousand
    accel_min = 4000
    speed_max = 8. * microsteps * 0x100; # 32768
    speed_bits = 12

    # range is 4096 at cphidgetstepper.c:210
    # range is 4095 at cphidgetstepper.c:488
    # I didn't try to model the discrepancy.
    speed_range = 1<<speed_bits

class Motor_1067(StepMotor):
    name = "STEPPER_BIPOLAR_1MOTOR_M3 (new bipolar board)"
    number = "1067_0"

    microsteps = 16
    accel_max = 10000000 # ten million
    accel_min = 2
    speed_max = 250000. # round number
    speed_bits = 24
    speed_range = speed_max # no scaling

if __name__=="__main__":
    motor_steps = 200

    header = "stats for %d step motor"%motor_steps
    print
    print header
    print "="*len(header)
    print

    for board in Motor_1062,Motor_1063,Motor_1067:
        b = board()
        b.print_stats(200)

Re: Stepper velocity tolerance

Posted: Tue May 09, 2017 10:52 am
by Patrick
With your set up (1067, 3331), and an optical encoder, I'm measuring an average RPM of 60.01. I think there must be something wrong with how you are measuring the RPM.

-Patrick