Stepper Motors (Part 4)

Part 12, 3, 4, 5, 6, 7, 8, 9

Speed management

As seen in the previous posts,torques must be taken into account while setting the rotor speed during the acceleration, steady and deceleration phases. Starting from there, we have two options: the theoretical and the experimental approaches. Although playing with physics and maths might be fun, it is probably quicker and more efficient to go the experimental way.

Under loaded conditions, let’s firstly estimate the starting speed using at pretty low frequency  such as 50/100Hz. Then increase the frequency up to the point where the rotor can no longer cope with the driving wave. Now that we know the limits, all we have to do is to program a ramping process. The following sketch illustrates a simple routine which accelerates and decelerates the rotor speed automatically.

uint8_t _stepPinMask = (1 << PINB5);
uint8_t _dirPinMask = (1 << PINB4);
const uint16_t _pulsesPerRound = 48; /* As per motor specifications */
const uint16_t _pulseWMax = 15000;
const uint16_t _pulseWMin = 5000;
const uint16_t _pulseWSteps = 500;

void setup(void)
{ 
	/* Initialize ports */
	DDRB |= _stepPinMask;
	DDRB |= _dirPinMask;
}


void loop(void)
{
	Rotate(48 << 2, 1);
	Rotate(48 << 2, 0);
}


inline void Pulse(uint16_t pulseWidth) 
{
	PORTB |= _stepPinMask;
	delayMicroseconds(2);
	PORTB &=  ~_stepPinMask;
	if (pulseWidth < 16000) {
		delayMicroseconds(pulseWidth);
	} else {
		delay(pulseWidth / 1000);
	}
}


void Rotate(uint16_t steps, uint8_t direction) 
{
	/* Set direction */
	if (direction) {
		PORTB |= _dirPinMask;	
	} else {
		PORTB &= ~_dirPinMask;
	}
	uint16_t rampsSteps = ((_pulseWMax - _pulseWMin) / _pulseWSteps);
	/* Constrain the number of ramp steps to the whole number of steps */
	if (rampsSteps > steps) {
		rampsSteps = (steps >> 1);
	}
	/* Compute the number of steps at constant speed */
	uint16_t constSpeedSteps = (steps - (rampsSteps << 1));
	uint16_t pulseW = _pulseWMax;
	/* Acceleration phase */
	for (uint16_t i = 0; i < rampsSteps; i++) {
		Pulse(pulseW);
		pulseW -= _pulseWSteps; /* Decrease pulse width */
	}
	/* Constant speed phase */
	for (uint16_t i = 0; i < constSpeedSteps; i++) {
		Pulse(pulseW);
	}
	/* Deceleration phase */
	for (uint16_t i = 0; i < rampsSteps; i++) {
		Pulse(pulseW);
		pulseW += _pulseWSteps; /* Increase pulse width */
	}
}

Note that the pulsing engine has been taken apart in an online routine in order to ease the readability of the code. In the same manner, the maximum, minimum and step pulse width are set in global constants.

It is interesting to compare the effects of both the constant speed operation and the accelerated and decelerated operations on the torque applied to the motor while starting, stopping or changing directions. The instantaneous torque reduction might be very useful for reducing the instantaneous stress applied to the belt if such an accessory is attached to the motor via a timing belt pulley. The counterpart of this improvement is some noise at lower excitation frequencies.

Next post on same subject

Leave a Reply

You must be logged in to post a comment.