Arduino with rotary encoder and 7 segment display
Arduino with rotary encoder and 7 segment display
This topic shows how to connect Arduino UNO with rotary encoder and 7-segment display. Here the rotary encoder is an input device and the 7-segment display is an output device.
The 7-segment display prints the values of the rotary encoder (positive or negative) on 4 digits where the first digit (most left) is used for the minus sign ( -).
To see how to connect Arduino with 7-segment display visit the following post:
Interfacing Arduino with 7-segment display | 4-Digit counter example
To see how the rotary encoder works and how to interface it with Arduino in order to control a DC motor speed, take a look at the project below:
DC Motor control with rotary encoder and Arduino
Parts Required:
- Arduino UNO board —> ATmega328P datasheet
- 4-Digit common anode 7-segment display
- 4 x PNP transistor (2SA1015, 2S9015, 2N3906 …)
- Rotary encoder
- 7 x 100 ohm resistor
- 4 x 4.7k ohm resistor
- Breadboard
- Jumper wires
Arduino with rotary encoder and 7-segment display circuit:
The image below shows example circuit schematic diagram.
The rotary encoder board 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)
The 4 transistors are of the same type (PNP).
Arduino with rotary encoder and 7 segment display code:
The Arduino code below doesn’t use any library for the 7-segment display.
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)
|
Since the 4 digits are multiplexed we need to refresh the display very quickly (display one digit at a time, others are off). For that I used Timer1 module interrupt with the following configuration:
1
2
3
4
5
|
// Timer1 module overflow interrupt configuration
TCCR1A = 0;
TCCR1B = 1; // enable Timer1 with prescaler = 1 ( 16 ticks each 1 µs)
TCNT1 = 0; // set Timer1 preload value to 0 (reset)
TIMSK1 = 1; // enable Timer1 overflow interrupt
|
With the above configuration Timer1 module overflows every 4096 microseconds (4096 = 65536/16).
Note that Timer1 module is 16-bit timer, prescaler = 1 (TCCR1B = 1) and Arduino UNO clock = 16MHz.
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
/*
* Interfacing Arduino with common anode 7-segment display.
* Print rotary encoder values on 4-digit 7-segment display.
* This is a free software with NO WARRANTY.
* http://simple-circuit.com/
*/
// segment pin definitions
#define SegA 12
#define SegB 11
#define SegC 10
#define SegD 9
#define SegE 8
#define SegF 7
#define SegG 6
// common pins of the four digits definitions
#define Dig1 5
#define Dig2 4
#define Dig3 3
#define Dig4 2
// variable declarations
byte current_digit, last_read;
int8_t quad = 0, change;
int enc_value = 0;
void setup()
{
pinMode(SegA, OUTPUT);
pinMode(SegB, OUTPUT);
pinMode(SegC, OUTPUT);
pinMode(SegD, OUTPUT);
pinMode(SegE, OUTPUT);
pinMode(SegF, OUTPUT);
pinMode(SegG, OUTPUT);
pinMode(Dig1, OUTPUT);
pinMode(Dig2, OUTPUT);
pinMode(Dig3, OUTPUT);
pinMode(Dig4, OUTPUT);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);
last_read = digitalRead(A5) << 1 | digitalRead(A4);
disp_off(); // turn off the display
// Timer1 module overflow interrupt configuration
TCCR1A = 0;
TCCR1B = 1; // enable Timer1 with prescaler = 1 ( 16 ticks each 1 µs)
TCNT1 = 0; // set Timer1 preload value to 0 (reset)
TIMSK1 = 1; // enable Timer1 overflow interrupt
// 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(TIMER1_OVF_vect) // Timer1 interrupt service routine (ISR)
{
disp_off(); // turn off the display
uint16_t abs_value = abs(enc_value); // abs: absolute value
switch (current_digit)
{
case 1:
if(enc_value < 0) // if negative value
{ // print minus sign (-) on digit 1 (most left digit)
disp(10); // prepare to display digit 1
digitalWrite(Dig1, LOW); // turn on digit 1
}
break;
case 2:
disp( (abs_value / 100) % 10); // prepare to display digit 2
digitalWrite(Dig2, LOW); // turn on digit 2
break;
case 3:
disp( (abs_value / 10) % 10); // prepare to display digit 3
digitalWrite(Dig3, LOW); // turn on digit 3
break;
case 4:
disp(abs_value % 10); // prepare to display digit 4 (most right)
digitalWrite(Dig4, LOW); // turn on digit 4
}
current_digit = (current_digit % 4) + 1;
}
ISR (PCINT1_vect) // ISR for Arduino A4 (PCINT12) and A5 (PCINT13) pins
{
uint8_t encoderRead = 0;
encoderRead = digitalRead(A5) << 1 | digitalRead(A4);
if(encoderRead == last_read)
return;
if(bitRead(encoderRead, 0) == bitRead(last_read, 1))
quad -= 1;
else
quad += 1;
last_read = encoderRead;
}
int8_t EncoderGet(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()
{
change = EncoderGet();
if(change)
enc_value += change;
delay(100); // wait 100 milliseconds
}
void disp(byte number)
{
switch (number)
{
case 0: // print 0
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, LOW);
digitalWrite(SegF, LOW);
digitalWrite(SegG, HIGH);
break;
case 1: // print 1
digitalWrite(SegA, HIGH);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, HIGH);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, HIGH);
digitalWrite(SegG, HIGH);
break;
case 2: // print 2
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, HIGH);
digitalWrite(SegD, LOW);
digitalWrite(SegE, LOW);
digitalWrite(SegF, HIGH);
digitalWrite(SegG, LOW);
break;
case 3: // print 3
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, HIGH);
digitalWrite(SegG, LOW);
break;
case 4: // print 4
digitalWrite(SegA, HIGH);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, HIGH);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, LOW);
digitalWrite(SegG, LOW);
break;
case 5: // print 5
digitalWrite(SegA, LOW);
digitalWrite(SegB, HIGH);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, LOW);
digitalWrite(SegG, LOW);
break;
case 6: // print 6
digitalWrite(SegA, LOW);
digitalWrite(SegB, HIGH);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, LOW);
digitalWrite(SegF, LOW);
digitalWrite(SegG, LOW);
break;
case 7: // print 7
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, HIGH);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, HIGH);
digitalWrite(SegG, HIGH);
break;
case 8: // print 8
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, LOW);
digitalWrite(SegF, LOW);
digitalWrite(SegG, LOW);
break;
case 9: // print 9
digitalWrite(SegA, LOW);
digitalWrite(SegB, LOW);
digitalWrite(SegC, LOW);
digitalWrite(SegD, LOW);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, LOW);
digitalWrite(SegG, LOW);
break;
case 10: // print –
digitalWrite(SegA, HIGH);
digitalWrite(SegB, HIGH);
digitalWrite(SegC, HIGH);
digitalWrite(SegD, HIGH);
digitalWrite(SegE, HIGH);
digitalWrite(SegF, HIGH);
digitalWrite(SegG, LOW);
}
}
void disp_off()
{
digitalWrite(Dig1, HIGH);
digitalWrite(Dig2, HIGH);
digitalWrite(Dig3, HIGH);
digitalWrite(Dig4, HIGH);
}
// end of code.
|
The following small video shows a test circuit of this project: