Stepper Motors (Part 3)
Part 1, 2, 3, 4, 5, 6, 7, 8, 9
A4988 module
Let’s go into the details of this module through the understanding of its pinout:
The suggested basic wiring is as follows:
- ~ENABLE: GND
- MS1, 2 & 3: GND
- ~RESET connected to ~SLEEP
- STEP: step pulse
- DIR: rotational direction
- GND: same GND for VDD and VMOT
- VDD: 3.3V to 5V
- 1A,1B: winding 1
- 2A, 2B: winding 2
- VMOT: as per stepper motor specifications
Note: the ~ spanish tilde is used for negating a bit value in C ((~0 | 1) == 1); this sign is also used in Ki
Step pulses must simply comply with the required pulse width as per the A4988 datasheet.
The nice thing about this driver is that you do not have to care about the duty cycle of the step pulse signal. On the other hand, care shall be taken about choosing the appropriate frequency so that it fits the stepper motor requirements (Check the “Torque” paragraph in Part 1). There is no danger at all at using innapropriate frequency. If the frequency is too high, the rotor will erratically move or not move at all. If the frequency is too low, the rotor will move in rough steps and generate a growling sound.
Next is a code sample for running the A4988 module in a basic way:
uint8_t _stepPinMask = (1 << PINB5); uint8_t _dirPinMask = (1 << PINB4); uint16_t _pulsesPerRound = 48; /* As per the stepper motor specifications */ void setup(void) { /* Initialize ports */ DDRB |= _stepPinMask; DDRB |= _dirPinMask; } void loop(void) { /* Rotate motor back and forth */ Rotate(_pulsesPerRound << 1, 1, 5000); Rotate(_pulsesPerRound << 1, 0, 5000); } void Rotate(uint16_t steps, uint8_t direction, uint16_t pulseWidth) { if (direction) { PORTB |= _dirPinMask; } else { PORTB &= ~_dirPinMask; } for (uint16_t i = 0; i < steps; i++) { /* Generate a step pulse. The pulse width is expressed in microseconds The on state is twice the minimum requirement and it is insignificant versus the off time which is mainly responsible for the frequency setting */ PORTB |= _stepPinMask; delayMicroseconds(2); PORTB &= ~_stepPinMask; /* Use the most appropriate delay function */ if (pulseWidth < 16000) { delayMicroseconds(pulseWidth); } else { delay(pulseWidth / 1000); } } }