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