I am using an ADM00308 development board from MicroChip. The board has a PIC16F883 processor. The code example can be downloaded from their website. I am using a nanotec steppermotor ST4118m0706 with a step 1.8 degree. I've calculated the max speed of the stepper motor:
from this website
RPMmax = 24V/(2⋅0,032mh⋅0,5A) = 3,75n/s (3,75⋅60 = 225rpm)
Minimum time per step = (2⋅0,032mh⋅0,5)/24V = 0,00133 seconds.
So in theory, the stepper motor should be able to handle 225rpm without oscillating. Now the software.
The code example provides a variable speed up to around 45rpm. This is too slow, since my target is 130rpm. Here is the original code:
Pulse width, Max speed and scan
// Prescale: Must change both values together - PRESCALE Divisor and BIT MASK */
// 1 = 0b00000000, 2 = 0b00010000, 4 = 0b00100000, 8 = 0b00110000
//#define REF_PWM_PRESCALE 8
//#define REF_PWM_PRESCALE_MASK 0b00110000
// The Rollover Count is the period of the timer.
// The timer period = 0 - Rollover Count.
//#define REF_PWM_PERIOD = ((float) ((1.0 / (((float)_XTAL_FREQ) / 4.0)) * (REF_PWM_PRESCALE * REF_RWM_ROLLOVER_COUNT)))
//#define REF_FREQ ((float) (1.0 / REF_PERIOD) )
// Set minimum speed by (65535 - MAX_SPEED_COUNT) * usec per bit
// 12 msec =
#define MIN_MOTOR_PULSEWIDTH (0.015)
#define MAX_SPEED_COUNT ((unsigned int) (65535.0 - ((float) ((MIN_MOTOR_PULSEWIDTH / (1.0 / (((float)_XTAL_FREQ) / 4.0))) / (ROTATION_PRESCALE * 2)))))
#define SPEED_INPUT_SPAN ((unsigned int) 900)
#define SPEED_INPUT_COUNTS_PER_BIT ((unsigned int) (MAX_SPEED_COUNT / SPEED_INPUT_SPAN))
#define ROTATION_ROLLOVER_COUNT (MAX_SPEED_COUNT + 100)
#define ROTATION_PRESCALE 8
#define ROTATION_PRESCALE_MASK 0b00110000
#define ROTATION_PERIOD = ((float) ((1.0 / (((float)_XTAL_FREQ) / 4.0)) * (ROTATION_PRESCALE * ROTATION_ROLLOVER_COUNT)))
#define ROTATION_FREQ ((float) (1.0 / ROTATION_PERIOD) )
SpeedUpdate
FaultTypeEnum SpeedUpdate(void)
{
FaultTypeEnum Fault;
unsigned int Speed;
Fault = NO_FAULT;
if (SpeedInput < 65)
{
/* open/shorted(GND) speed input */
Speed = 0;
Fault = SPEED_INPUT_LOW;
}
else if (SpeedInput < 100)
{
Speed = 0;
Fault = NO_FAULT;
}
else if (SpeedInput > 950)
{
Speed = 0;
Fault = SPEED_INPUT_HIGH;
}
else if (SpeedInput > 900)
{
/* open/shorted(VDD) speed input */
Speed = MAX_SPEED_COUNT;
Fault = NO_FAULT;
}
else
{
Speed = (SpeedInput - 100) * SPEED_INPUT_COUNTS_PER_BIT;
Fault = NO_FAULT;
}
RotationTimerRolloverCount = MAX_SPEED_COUNT - Speed;
/* setup the next timer reload value */
T1CON = 0b00000000; /* Temporarily pause the PWM timer */
/* use variables to reload timer faster in interrupt routine */
RotationTimerReloadHi = (unsigned )(RotationTimerRolloverCount >> 8);
RotationTimerReloadLo = (unsigned short) RotationTimerRolloverCount;
T1CON = 0b00000001 | ROTATION_PRESCALE_MASK; // Re-enable PWM timer, set prescale
return Fault;
}
Timer
/* Rotation Timer. Must be fast. */
if (PIR1bits.TMR1IF)
{
PIR1bits.TMR1IF = 0;
TMR1H = RotationTimerReloadHi;
TMR1L = RotationTimerReloadLo;
/* Calculate next stepper rotation state */
/* HOLD switch sets min_rotation_state = max_rotation_state */
/* SINGLE STEP switch sets min_rotation_state = max_rotation_state */
if (System.Bits.Stop)
{
/* no current output */
RotationData.All = ROTATION_STOP;
}
else
{
/* update stepper driver with last calculated data */
PORTB = ((PORTB & 0b11000000) | RotationData.All);
I managed to change the speed to 146rpm by changing:
#define MIN_MOTOR_PULSEWIDTH (0.015)
to for testing
#define MIN_MOTOR_PULSEWIDTH (0.006)
The stepper rotates at a speed of 98rpm with the potentio completely rotated to the left. Lowering the value to 0.004 will get a speed of 146rpm with good torque on a 24v supply(torque will suffer on a 12v supply). Lowering the value even more, will oscillate the motor (you can hear the motor but it doesn't rotate anymore). Which is strange since the max rpm is supposed to be 225rpm. However, the main problem is that I can't seem to reach a rpm of 130. Changing the value to 0.005, 0.0045, etc doesn't increase the speed more than 98 until 0.004. It also seems that the potentiometer has some kind of presets. By turning the potentiometer, it changes from 146rpm to 98rpm, to 73rpm, etc. It doesn't change the speeds fluently, if you get my point. Hence I am getting the idea it's programmed in presets, which I also tried to change.
Firmware and information can be downloaded on the original site