Now that we have our stepper motor running we can add some extra features, like:
- change direction
- change speed
- rotate an exact amount of steps for accurate positioning
Read on below the video …
To change direction and to also show a direction indicator LED, a function is created. There’s no real need to make it a function, it’s used here to show the concept of how a function can return a value. The function is named dir() and it has the type byte. When it is called, it reads an input pin, switches the indicator LED accordingly and then returns a byte that represents the direction switch, which in this case is either 1 or 0.
byte dir() { byte dir_switch = digitalRead(DIR_PIN); digitalWrite(DIR_LED_PIN, !dir_switch); return dir_switch; }
To change the rotation speed we have to change the number of microseconds between the driver pulses that we send out. We’re again going to use a function that returns a value, this time an unsgined long number. The stepinterval() function looks like this:
unsigned long stepinterval() { // calculates step timing based on potmeter input rpm = map(analogRead(POTM_PIN), 0, 1024, 1, 13); // max 12 rpm, else pulses get lost if(rpm != rpm_old) { Serial.print("RPM: "); Serial.println(rpm); rpm_old = rpm; } return 60000000UL / PULSES_PER_REV / rpm; // [us] stepinterval }
A potentiometer is used to create a voltage on an Arduino input. This is analog read and mapped to a speed in RPM from 1 to 12. The RPM value is translated to a step interval time in microseconds which is returned with data type unsigned long.
The complete code now becomes:
#define MOTOR_PIN_1 A1 #define MOTOR_PIN_2 A2 #define MOTOR_PIN_3 A3 #define MOTOR_PIN_4 A4 #define POTM_PIN A5 #define ONOFF_PIN 9 // LOW = motor runs #define ONOFF_LED_PIN 5 // Motor running LED #define DIR_PIN 8 // LOW = rotate LEFT, HIGH = rotate RIGHT #define DIR_LED_PIN 4 // Motor direction LED #define PULSES_PER_REV 2048 // Pulses per revolution byte rpm, rpm_old, stepnr; unsigned long timeoflaststep; unsigned long stepinterval() { // calculates step timing based on potmeter input rpm = map(analogRead(POTM_PIN), 0, 1024, 1, 13); // max 12 rpm, else pulses get lost if(rpm != rpm_old) { Serial.print("RPM: "); Serial.println(rpm); rpm_old = rpm; } return 60000000UL / PULSES_PER_REV / rpm; // [us] stepinterval } byte dir() { byte dir_switch = digitalRead(DIR_PIN); digitalWrite(DIR_LED_PIN, !dir_switch); return dir_switch; } void do_one_step() { digitalWrite(ONOFF_LED_PIN, HIGH); if(dir() == 1) stepnr++; else stepnr--; stepnr = stepnr % 4; // remember in which of the 4 phases the motor is switch (stepnr) { case 0: digitalWrite(MOTOR_PIN_1, HIGH); digitalWrite(MOTOR_PIN_2, LOW); digitalWrite(MOTOR_PIN_3, LOW); digitalWrite(MOTOR_PIN_4, LOW); break; case 1: digitalWrite(MOTOR_PIN_1, LOW); digitalWrite(MOTOR_PIN_2, HIGH); digitalWrite(MOTOR_PIN_3, LOW); digitalWrite(MOTOR_PIN_4, LOW); break; case 2: digitalWrite(MOTOR_PIN_1, LOW); digitalWrite(MOTOR_PIN_2, LOW); digitalWrite(MOTOR_PIN_3, HIGH); digitalWrite(MOTOR_PIN_4, LOW); break; case 3: digitalWrite(MOTOR_PIN_1, LOW); digitalWrite(MOTOR_PIN_2, LOW); digitalWrite(MOTOR_PIN_3, LOW); digitalWrite(MOTOR_PIN_4, HIGH); break; } } void motor_idle() { digitalWrite(MOTOR_PIN_1, LOW); digitalWrite(MOTOR_PIN_2, LOW); digitalWrite(MOTOR_PIN_3, LOW); digitalWrite(MOTOR_PIN_4, LOW); digitalWrite(ONOFF_LED_PIN, LOW); dir(); // to switch the LED when motor not running } void setup() { pinMode(ONOFF_PIN, INPUT_PULLUP); pinMode(DIR_PIN, INPUT_PULLUP); pinMode(MOTOR_PIN_1, OUTPUT); pinMode(MOTOR_PIN_2, OUTPUT); pinMode(MOTOR_PIN_3, OUTPUT); pinMode(MOTOR_PIN_4, OUTPUT); pinMode(ONOFF_LED_PIN, OUTPUT); pinMode(DIR_LED_PIN, OUTPUT); Serial.begin(9600); } void loop() { while(digitalRead(ONOFF_PIN) == LOW) { if ((micros() - timeoflaststep) > stepinterval()) { timeoflaststep = micros(); do_one_step(); } } motor_idle(); }
Let’s try this out and see if we can change the direction and the speed.
Yes … we can!
On to the next video, where we are going to add a ‘zero find’ routine, which we need in preparation of accurate positioning the stepper motor. Unlike a servo, a stepper does not know where it is after startup.
— 0 —