Arduino Stepper motor control with rotary encoder
Arduino Stepper motor control with rotary encoder
This Arduino project shows how to control unipolar stepper motor using Arduino UNO board and rotary encoder module.
The stepper motor used in this example is 28BYJ-48 (5V unipolar stepper motor) which usually comes with its driver board.
To see how to easily control stepper motor with Arduino, visit this post:
Arduino Unipolar Stepper Motor Control
In this project I used the rotary encoder shown below:
The rotary encoder module has 5 pins: GND, + (+5V or 3.3V), SW (push button), DT (pin B) and CLK (pin A).
As an addition to the rotary encoder there is a push button and three pull up resistors for pins SW, DT and CLK of 10k ohm. With the three pull-up resistors, the normal state of each terminal is logic high.
The rotary encoder generates (when rotating) two square waves on pins A (CLK) and B (DT) with 90° out of phase as shown in the figure below:
Since the normal state of pin A (CLK) and pin B (DT) are logic high we’ve to detect falling (transition from high to low) of one of them, here pin A is used to detect the movement of the rotary encoder in both directions (falling of pin A signal). Direction of rotation can be detected by knowing the status of pin B, if pin B is logic high this means the direction of rotation is clockwise (CW), and if pin B is logic low this means the direction of rotation is counter clockwise (CCW).
Hardware Required:
- Arduino UNO board —> Board details —> ATmega328P microcontroller datasheet
- 28BYJ-48 stepper motor (with ULN2003A driver board)
- Rotary encoder module
- 5V power source
- Bread board
- Jumper wires
Stepper Motor Control with Arduino and Rotary Encoder Circuit:
Project circuit schematic diagram is shown below.
The stepper motor is connected to the ULN2003A board which is supplied with external power source of 5V. The control lines (IN1, IN2, IN3 and IN4) of this board are connected to the Arduino as:
IN1 to Arduino pin 11,
IN2 to Arduino pin 10,
IN3 to Arduino pin 9,
IN4 to Arduino pin 8.
The rotary encoder module has 5 pins: GND, + , SW, DT (pin B or data pin) and CLK (pin A or clock pin) where:
GND is connected to Arduino GND pin,
+ is connected to Arduino 5V pin,
SW is push button pin, not used in this example,
DT is connected to Arduino analog pin 5 (A5),
CLK is connected to Arduino analog pin 4 (A4).
Stepper Motor Control with Arduino and Rotary Encoder Code:
In this example I used Arduino stepper motor library (built-in) which simplifies the code, it’s included in the code using the following line:
1
|
#include <Stepper.h>
|
The stepper motor which I used in this project is 28BYJ-48, this motor is equipped with speed reducer of 1/64. The internal motor has 32 steps per one revolution which means the external shaft has 2048 steps per one revolution (64 x 32). Number of steps is defined in the code as shown below:
1
|
#define STEPS 2048
|
and the connection of the control lines of the stepper motor with the Arduino are defined as:
1
2
3
4
5
6
7
8
|
// define stepper motor control pins
#define IN1 11
#define IN2 10
#define IN3 9
#define IN4 8
// initialize stepper library
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
|
The rotary encoder pin A (CLK) and pin B (DT) are connected to Arduino UNO pins A4 and A5 respectively. Both pins can be used to interrupt the Arduino microcontroller (ATmega328P) whenever there is a change in the state of at least one pin. The following lines are used to enable interrupt-on-change for pins A4 (PCINT12) and A5 (PCINT13):
1
2
3
|
// pin change interrupt configuration
PCICR = 2; // enable pin change interrupt for pins PCINT14..8 (Arduino A0 to A5)
PCMSK1 = 0x30; // enable pin change interrupt for pins PCINT12 & PCINT13 (Arduino A4 & A5)
|
Full Arduino code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
/*
* Arduino stepper motor control with rotary encoder.
* This is a free software with NO WARRANTY.
* https://simple-circuit.com/
*/
// include Arduino stepper motor library
#include <Stepper.h>
// number of steps per one revolution is 2048 ( = 4096 half steps)
#define STEPS 2048
// define stepper motor control pins
#define IN1 11
#define IN2 10
#define IN3 9
#define IN4 8
// initialize stepper library
Stepper stepper(STEPS, IN4, IN2, IN3, IN1);
int8_t quad = 0;
uint8_t previous_data;
void setup()
{
stepper.setSpeed(10); // set stepper motor speed to 10 rpm
// get rotary encoder state
previous_data = digitalRead(A5) << 1 | digitalRead(A4);
// pin change interrupt configuration
PCICR = 2; // enable pin change interrupt for pins PCINT14..8 (Arduino A0 to A5)
PCMSK1 = 0x30; // enable pin change interrupt for pins PCINT12 & PCINT13 (Arduino A4 & A5)
}
ISR (PCINT1_vect) // ISR for Arduino A4 (PCINT12) and A5 (PCINT13) pins
{
uint8_t current_data = digitalRead(A5) << 1 | digitalRead(A4);
if( current_data == previous_data )
return;
if( bitRead(current_data, 0) == bitRead(previous_data, 1) )
quad -= 1;
else
quad += 1;
previous_data = current_data;
}
int8_t encoder_update(void)
{
int8_t val = 0;
while(quad >= 4){
val += 1;
quad -= 4;
}
while(quad <= –4){
val -= 1;
quad += 4;
}
return val;
}
// main loop
void loop()
{
int8_t stp = encoder_update();
while(stp != 0)
{
int8_t dir = (stp > 0) ? –1 : 1;
stepper.step( 20 * dir );
stp += dir;
stp += encoder_update();
}
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, LOW);
delay(100);
}
// end of code.
|
Stepper Motor Control with Arduino and Rotary Encoder Video:
The video below shows a DIY hardware circuit of Arduino uno board with rotary encoder.