First time I used a stepper motor:
Unlike the Arduino stepper library, moving the stepper motor doesn't block your loop. This is useful if you want to control more than one motor at the same time. And the high interrupt rate of 10 kHz, in combination with the accumulator, allows a high resolution speed control.
Parts used:
- Pololu Stepper Motor NEMA 14 Bipolar 200 Steps/Rev 35×28mm 10V 0.5 A/Phase
- Pololu A4988 StepStick Stepper Motortreiber Carrier 1182
- Arduino Mega 2560
- 10k potentiometer
- breadboard and cables
- 10 V power supply for the motor voltage
Arduino sketch:
// pin numbers
const int analogPin = A0;
const int enablePin = 40;
const int ms1Pin = 41;
const int ms2Pin = 42;
const int ms3Pin = 43;
const int resetPin = 44;
const int sleepPin = 45;
const int stepPin = 46;
const int dirPin = 47;
// interrupt frequency
const float samplerate = 10000.0f;
void setup()
{
// init pins
pinMode(enablePin, OUTPUT);
pinMode(ms1Pin, OUTPUT);
pinMode(ms2Pin, OUTPUT);
pinMode(ms3Pin, OUTPUT);
pinMode(resetPin, OUTPUT);
pinMode(sleepPin, OUTPUT);
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
digitalWrite(enablePin, LOW);
digitalWrite(ms1Pin, LOW);
digitalWrite(ms2Pin, LOW);
digitalWrite(ms3Pin, LOW);
digitalWrite(resetPin, LOW);
digitalWrite(sleepPin, HIGH);
digitalWrite(stepPin, HIGH);
digitalWrite(dirPin, HIGH);
delay(100);
digitalWrite(resetPin, HIGH);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 16000000.0f / samplerate; // compare match register for IRQ with selected samplerate
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10); // no prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
uint32_t wait = 0;
int spd = 0;
int clk = 0;
// timer 1 interrupt
ISR(TIMER1_COMPA_vect)
{
// generate the next clock pulse on accumulator overflow
wait += spd;
if (wait > 0xffff) {
if (clk) {
digitalWrite(stepPin, HIGH);
} else {
digitalWrite(stepPin, LOW);
}
wait -= 0x10000;
clk = !clk;
}
}
void loop()
{
// read potentiometer and set direction
int poti = analogRead(analogPin);
if (poti < 512) {
digitalWrite(dirPin, LOW);
poti = 512 - poti;
} else {
digitalWrite(dirPin, HIGH);
poti -= 512;
}
// update the speed, which increments the accumulator in the interrupt
noInterrupts();
spd = poti * 10;
interrupts();
}