One of the first things I tried when I started playing with Arduino was running a stepper motor. As I had bought 2 small 28BYJ-48 stepper motors with my first Arduino. Since I knew very little about programming I just used the Arduino stepper library. The library works but it’s not that usefull, it is a blocking library. You can’t do much else when running the motors. I then put the motors away and nearly forgot about them. Until I saw that Rocket Brand studios sells wheels that fit these motors. So I ordered a couple of the wheels. I might make a small robotic vehicle powered by these little stepper motors.
Now that I have a litle bit more experience writing code I wrote some non blocking code for my little stepper motors. The code also includes an acceleration function. It will slowly start the motor and after x number of steps it will ramp up the speed 🙂
Here is a video I made during the testing of my code:
This code will run the stepper motor in both directions for 15 seconds:
// http://www.bajdi.com // Non blocking code for a 28BYJ-48 stepper motor controlled by an ATmega1284 // Using the delay function in void loop will break this code //declare variables for the motor pins const int motorPin1 = 11; // IN1 on motor control board const int motorPin2 = 12; // IN2 const int motorPin3 = 13; // IN3 const int motorPin4 = 14; // IN4 #define runEvery(t) for (static typeof(t) _lasttime;(typeof(t))((typeof(t))millis() - _lasttime) > (t);_lasttime += (t)) unsigned long previousMicros; unsigned long steps; byte motor1Step = 0; bool direction; int stepInterval; void setup() { //declare the motor pins as outputs pinMode(motorPin1, OUTPUT); pinMode(motorPin2, OUTPUT); pinMode(motorPin3, OUTPUT); pinMode(motorPin4, OUTPUT); } void loop(){ // Time between steps in microseconds = stepInterval if (steps < 200) { stepInterval = 1800; } if (steps >= 200 && steps <= 400) { stepInterval = 1400; } if (steps > 400 && steps <= 600) { stepInterval = 1100; } if (steps > 600 && steps <= 800) { stepInterval = 900; } if (steps > 800) { stepInterval = 650; } // Switch direction every 15 seconds runEvery(15000) { steps = 0; // reset steps if (direction == LOW) direction = HIGH; else direction = LOW; } if (direction == LOW) { clockWise(); } else { counterClockWise(); } } void clockWise() { // Clockwise stepper code if (micros() >= previousMicros){ previousMicros = previousMicros+stepInterval; motor1Step = motor1Step +1; if (motor1Step == 9){ motor1Step = 1; steps = steps +1; } } switch (motor1Step){ case 1: digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); break; case 2: digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); break; case 3: digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, LOW); break; case 4: digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); break; case 5: digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, LOW); break; case 6: digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin1, HIGH); break; case 7: digitalWrite(motorPin4, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); break; case 8: digitalWrite(motorPin4, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin1, HIGH); break; } // end switch } void counterClockWise() { // Counterclockwise stepper code if (micros() >= previousMicros){ previousMicros = previousMicros+stepInterval; motor1Step = motor1Step +1; if (motor1Step == 9){ motor1Step = 1; steps = steps +1; } } switch (motor1Step){ case 1: digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); break; case 2: digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); break; case 3: digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, LOW); break; case 4: digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, HIGH); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); break; case 5: digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, LOW); break; case 6: digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, HIGH); digitalWrite(motorPin4, HIGH); break; case 7: digitalWrite(motorPin1, LOW); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); break; case 8: digitalWrite(motorPin1, HIGH); digitalWrite(motorPin2, LOW); digitalWrite(motorPin3, LOW); digitalWrite(motorPin4, HIGH); break; } // end switch }
Sir, All decent CNC code runs accel and decell ramps check out GRBL and look at the parameters section and you will see where the user sets the acell and decell speeds,along with the min/max speed ,its called slewing to a desired position also auto telescope mounts do the same thing but anyway great code practice….WCH
Hi! In the text you said that the code is non-blocking. Probably, I am not experienced enough because I am unable to find out why. While the stepper is running, the MCU should be capable of doing something else at once. For instance taking measurements by means of a sensor. Another difficult task is getting both steppers to rotate at different RPMs simultaneously. Could you possibly demonstrate such ability of your program? Thanks and regards!
The stepper library that comes with the Arduino IDE uses the delay function. My code is based on the millis function. So you can run other code while you control the stepper motor.
Hello,thank you for sharing you code with us. I have a question. How do I controll the speed of the stepper motor? If I change the stepInterval to 1, the speed is still very slow!
Thank you for your time!