How to Interface Stepper Motor to Arduino Uno
Introduction
I am thinking on creating this tinkering with stepper motor long time ago until yesterday when I met someone in Facebook group asking help regarding his project related to controlling the stepper motor while being able to check for some controls and update LCD to display information. So basically his project should be able to do multiple things at the same time or multi-tasking. Even though Arduino Uno is a powerful microcontroller but it has only one processing core. It means it can process only one task at one time.
To mimic or to copy the functionalities of multi-tasking, I suggest to use the proto-threading. Proto-threading is basically doing small chunks of task by using the power of millis() Arduino function. To do this, BlinkWithoutDelay example of Arduino is used (please refer to the source code below).
Bill Of Materials
- Arduino Uno.
- Stepper motor.
- Stepper motor driver (such as L298)
- Keypad shield with 16×2 LCD.
- Some jumper wires
Hardware Instruction
- By referring to the attached schematic above, connect the keypad shield to Arduino Uno.
- Connect the L298N motor driver to Arduino Uno as follows:
- Connect the IN1 of L298N to Arduino Uno pin 13.
- Connect the IN2 of L298N to Arduino Uno pin 12.
- Connect the IN3 of L298N to Arduino Uno pin 11.
- Connect the IN4 of L298N to Arduino Uno pin 3.
- Connect the stepper motor to L298N outputs.
- Enable the L298N by placing a jumper on enable pins.
- Connect a power supply on +12V pin according to your stepper motor voltage requirements.
- Connect the power supply GND to the GND pin of L298N.
- Connect the Arduino Uno GND to the GND pin of L298N.
- Upload the sketch provided in the source code below.
- The sketch basically functions as follows:
UP button – increases the angle
DOWN button – decreases the angle
LEFT button – counter clockwise direction
RIGHT button – clockwise direction
SELECT button – execute the stepper rotation according to angle and direction set.
The serial command basically functions by sending command in this format: <A, B, C>
Where A: is the command to rotate the stepper
B: is the parameter of direction, 1: CW 0: CCW
C: is the parameter of angle
< and > is necessary for parsing the command.
Video Demonstration
Source Code
1// For LCD and keypad refer to:
2// https://wiki.dfrobot.com/Arduino_LCD_KeyPad_Shield__SKU__DFR0009_
3// https://create.arduino.cc/projecthub/electropeak/using-1602-lcd-keypad-shield-w-arduino-w-examples-e02d95
4
5#include "LiquidCrystal.h"
6#include "Stepper.h"
7
8//LCD pin to Arduino
9const int pin_RS = 8;
10const int pin_EN = 9;
11const int pin_d4 = 4;
12const int pin_d5 = 5;
13const int pin_d6 = 6;
14const int pin_d7 = 7;
15const int pin_BL = 10;
16
17const int stepsPerRevolution = 200; // change this to fit the number of steps per revolution
18
19LiquidCrystal lcd( pin_RS, pin_EN, pin_d4, pin_d5, pin_d6, pin_d7);
20Stepper myStepper(stepsPerRevolution, 3, 11, 12, 13);
21
22// ####################################
23// PROTOTHREADING DEFINITIONS HERE:
24// ####################################
25unsigned long checkSerialTaskTimer = 0;
26const unsigned long checkSerialTaskInterval = 100;
27
28unsigned long setSerialTaskTimer = 0;
29const unsigned long setSerialTaskInterval = 100;
30
31unsigned long updateSerialTaskTimer = 0;
32const unsigned long updateSerialTaskInterval = 100;
33
34unsigned long doStepperTaskTimer = 0;
35const unsigned long doStepperTaskInterval = 500;
36
37unsigned long updateLCDTaskTimer = 0;
38const unsigned long updateLCDTaskInterval = 100;
39
40unsigned long checkButtonTaskTimer = 0;
41const unsigned long checkButtonTaskInterval = 100;
42
43// Global variables
44const byte numChars = 32;
45char receivedChars[numChars];
46char tempChars[numChars]; // temporary array for use when parsing
47
48// variables to hold the parsed data
49char userCmd[numChars] = {0};
50int firstParam = 0;
51int secondParam = 0;
52
53boolean newData = false;
54bool newCmd = false;
55
56int currAng = 0;
57bool currDir = true;
58bool executeSteps = false;
59
60
61void setup() {
62 // set the speed at 60 rpm:
63 myStepper.setSpeed(60);
64 // initialize the serial port:
65 Serial.begin(9600);
66 Serial.println("Stepper motor controller: ");
67 Serial.println("Enter command like <a href="https://www.blogger.com/null"> ");
68 Serial.println("A: command to turn stepper, 1:turn CW 0:CCW, 360: degrees");
69 Serial.println();
70
71 lcd.begin(16, 2);
72 lcd.setCursor(0,0);
73 lcd.print("L/R:Dir U/D:Deg");
74 lcd.setCursor(0,1);
75 lcd.print("DIR:");
76 lcd.setCursor(9,1);
77 lcd.print("DEG:");
78}
79
80void loop() {
81 if(millis() >= checkSerialTaskTimer + checkSerialTaskInterval){
82 checkSerialTaskTimer += checkSerialTaskInterval;
83 // do the task
84 checkSerial();
85 }
86
87 if(millis() >= setSerialTaskTimer + setSerialTaskInterval){
88 setSerialTaskTimer += setSerialTaskInterval;
89 // do the task
90 setSerial();
91 }
92
93 if(millis() >= updateSerialTaskTimer + updateSerialTaskInterval){
94 updateSerialTaskTimer += updateSerialTaskInterval;
95 // do the task
96 updateSerial();
97 }
98
99 if(millis() >= doStepperTaskTimer + doStepperTaskInterval){
100 doStepperTaskTimer += doStepperTaskInterval;
101 // do the task
102 doStepper();
103 }
104
105 if(millis() >= updateLCDTaskTimer + updateLCDTaskInterval){
106 updateLCDTaskTimer += updateLCDTaskInterval;
107 // do the task
108 updateLCD();
109 }
110
111 if(millis() >= checkButtonTaskTimer + checkButtonTaskInterval){
112 checkButtonTaskTimer += checkButtonTaskInterval;
113 // do the task
114 checkButton();
115 }
116
117}
118
119void checkSerial() {
120 static boolean recvInProgress = false;
121 static byte ndx = 0;
122 char startMarker = '<';
123 char endMarker = '>';
124 char rc;
125
126 while (Serial.available() > 0 && newData == false) {
127 rc = Serial.read();
128
129 if (recvInProgress == true) {
130 if (rc != endMarker) {
131 receivedChars[ndx] = rc;
132 ndx++;
133 if (ndx >= numChars) {
134 ndx = numChars - 1;
135 }
136 }
137 else {
138 receivedChars[ndx] = ''; // terminate the string
139 recvInProgress = false;
140 ndx = 0;
141 newData = true;
142 }
143 }
144
145 else if (rc == startMarker) {
146 recvInProgress = true;
147 }
148 }
149}
150
151void setSerial() {
152 char * strtokIndx; // this is used by strtok() as an index
153
154 if (newData == true) {
155 strcpy(tempChars, receivedChars);
156 // this temporary copy is necessary to protect the original data
157 // because strtok() used in parseData() replaces the commas with
158
159 strtokIndx = strtok(tempChars,",");
160 strcpy(userCmd, strtokIndx); // user command
161
162 strtokIndx = strtok(NULL, ",");
163 firstParam = atoi(strtokIndx); // first parameters
164 if (firstParam) {
165 currDir = true;
166 }
167 else {
168 currDir = false;
169 }
170
171 strtokIndx = strtok(NULL, ",");
172 //secondParam = atoi(strtokIndx); // second parameters
173 currAng = atoi(strtokIndx); // second parameters
174
175 //newCmd = true;
176 executeSteps = true;
177 newData = false;
178 }
179
180}
181
182
183void updateSerial() {
184}
185
186void doStepper() {
187 int steps = 0;
188
189 // command from keypad shield
190 if (executeSteps) {
191 steps = rotate(currDir, currAng);
192 if (firstParam) {
193 Serial.print("Rotated CW by ");
194 }
195 else {
196 Serial.print("Rotated CCW by ");
197 }
198 Serial.println(currAng);
199 executeSteps = false;
200 }
201
202}
203
204void updateLCD() {
205 lcd.setCursor(4,1);
206 if (currDir) {
207 lcd.print("CW ");
208 }
209 else {
210 lcd.print("CCW");
211 }
212 lcd.setCursor(13,1);
213 lcd.print(currAng);
214
215}
216
217void checkButton() {
218 int x;
219 x = analogRead (0);
220 lcd.setCursor(10,1);
221 if (x < 60) {
222 //lcd.print ("Right ");
223 currDir = true; // CW
224 }
225 else if (x < 200) {
226 //lcd.print ("Up ");
227 if (currAng >= 360) {
228 currAng = 360;
229 }
230 else {
231 currAng = currAng + 5; // increase angle
232 }
233 }
234 else if (x < 400){
235 //lcd.print ("Down ");
236 if (currAng <= 0) {
237 currAng = 0;
238 }
239 else {
240 currAng = currAng - 5; // decrease angle
241 }
242 }
243 else if (x < 600){
244 //lcd.print ("Left ");
245 currDir = false; // CCW
246 }
247 else if (x < 800){
248 //lcd.print ("Select");
249 executeSteps = true;
250 }
251 else {
252 //lcd.print (" "); // delete previous text when nothing is press
253 }
254 if (executeSteps) {
255 }
256}
257
258
259int rotate(bool rotateDirection, int reqAngle) {
260 int steps = reqAngle / 1.8;
261 // Clockwise direction
262 if (rotateDirection) {
263 myStepper.step(int(steps));
264 }
265 else {
266 myStepper.step(int(-steps));
267 }
268 return steps;
269}
Call To Action
If you find this lesson useful, please consider supporting my Youtube channel: TechToTinker
Please leave your comments and suggestions in the comment box below.
Thank you and have a good day. Bye.
Posts in this series
- How to Get Started with ATTiny85 in Arduino IDE
- Tutorial: How to use MFRC522 RFID module using Arduino
- SOS Flasher Using Millis Function with Enable Switch
- Tutorial: How to use DS3231 RTC in Arduino
- Tutorial: How to use 0.96 OLED - a small and cute display
- Tutorial: Getting Started with the NRF24L01 | How to use | Arduino
- Tutorial: How to use SIM800L GSM Module for Controlling Anything | Arduino
- Tutorial: How to use Keypad | Text Entry Mode | Arduino
- Tutorial: How to use 4x4 Keypad | Arduino
- Project Idea: Arduino Voltmeter
- Project Idea: Door Lock Security | Arduino
- Multitasking with Arduino | Relay Timer Controller | using millis
- Tutorial Understanding Blink Without Delay | How to millis
- Arduino Simple LCD Menu
- How to use SIM800L GSM Module using Arduino | Make or Answer Voice Calls
- Tutorial: How to Use Arduino Uno as HID | Part 2: Arduino Mouse Emulation
- Tutorial: How to Use Arduino Uno as HID | Part 1: Arduino Keyboard Emulation
- Tutorial: How to use SIM800L DTMF to Control Anything | Arduino
- Tutorial: Arduino EEPROM
- How to use SIM800L GSM Module | Arduino | Send and Receive SMS
- 16x2 LCD Menu for Arduino
- Tutorial: Arduino GPIO | How to use Arduino Pins
- MIT App Inventor for Arduino
- RC Car using L298N, HC-06, and Arduino Uno
- How to Use LCD Keypad Shield for Arduino
- How to Use Arduino Interrupts
- Project: Automatic Alcohol Dispenser
- TUTORIAL: How to use HC-SR04 Ultrasonic Sensor with Arduino
- Source Code: Astronomia Meme and Funeral Dance | melodies the Arduino way
- How to Get Started with L293D Motor Driver Shield with Arduino
- How to Get Started with L298N Motor Driver module using Arduino
- Part 2: Wav Music Player with Lyrics Using Arduino and SD Card
- Interfacing Infrared to Arduino Uno
- Part 1: Wav Music Player Using Arduino Uno and SD Card
- How To Play MP3 Files on Arduino from SD Card
- What is Arduino Software Serial
- How to Interface SD card to Arduino (without SD card shield)?
- Playing Melodies Using Arduino
- 8 Degrees Of Freedom (DOF) Robot Using Arduino Uno
- How to Interface PS2 Controller to Arduino Uno
- Part 3: DF Player Mini Tinkering with Arduino Nano and LCD
- How to Interface HC-06 to Arduino
- How to make a Remote Control RC car using Arduino and HC-06 bluetooth module
- Part 2: DF Player Mini Tinkering with Arduino Nano
- Part 1: DF Player Mini - a mini cheap mp3 player
No comments yet!