-
Notifications
You must be signed in to change notification settings - Fork 69
/
SevSeg.cpp
301 lines (268 loc) · 10.6 KB
/
SevSeg.cpp
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
/*
This library allows an Arduino to easily display numbers and characters on a 4 digit 7-segment
display without a separate 7-segment display controller.
If you have feature suggestions or need support please use the github support page: https://github.com/sparkfun/SevSeg
Original Library by Dean Reading (deanreading@hotmail.com: http://arduino.cc/playground/Main/SevenSegmentLibrary), 2012
Improvements by Nathan Seidle, 2012
Now works for any digital pin arrangement, common anode and common cathode displays.
Added character support including letters A-F and many symbols.
Hardware Setup: 4 digit 7 segment displays use 12 digital pins. You may need more pins if your display has colons or
apostrophes.
There are 4 digit pins and 8 segment pins. Digit pins are connected to the cathodes for common cathode displays, or anodes
for common anode displays. 8 pins control the individual segments (seven segments plus the decimal point).
Connect the four digit pins with four limiting resistors in series to any digital or analog pins. Connect the eight segment
pins to any digital or analog pins (no limiting resistors needed). See the SevSeg example for more connection information.
SparkFun has a large, 1" 7-segment display that has four digits.
https://www.sparkfun.com/products/11408
Looking at the display like this: 8.8.8.8. pin 1 is on the lower row, starting from the left.
Pin 12 is the top row, upper left pin.
Pinout:
1: Segment E
2: Segment D
3: Segment DP
4: Segment C
5: Segment G
6: Digit 4
7: Segment B
8: Digit 3
9: Digit 2
10: Segment F
11: Segment A
12: Digit 1
Software:
Call SevSeg.Begin in setup.
The first argument (boolean) tells whether the display is common cathode (0) or common
anode (1).
The next four arguments (bytes) tell the library which arduino pins are connected to
the digit pins of the seven segment display. Put them in order from left to right.
The next eight arguments (bytes) tell the library which arduino pins are connected to
the segment pins of the seven segment display. Put them in order a to g then the dp.
In summary, Begin(type, digit pins 1-4, segment pins a-g, dp)
The calling program must run the DisplayString() function repeatedly to get the number displayed.
Any number between -999 and 9999 can be displayed.
To move the decimal place one digit to the left, use '1' as the second
argument. For example, if you wanted to display '3.141' you would call
myDisplay.DisplayString("3141", 1);
*/
#include "SevSeg.h"
SevSeg::SevSeg()
{
//Initial values
DecAposColon = 0; //This variable tracks the decimal place, apostrophe, and colon (if the display has support)
}
void SevSeg::Begin(boolean mode_in, byte numOfDigits,
byte dig1, byte dig2, byte dig3, byte dig4,
byte digitCol, byte digitApos,
byte segA, byte segB, byte segC, byte segD, byte segE, byte segF, byte segG,
byte segDP,
byte segCol, byte segApos)
{
//Bring all the variables in from the caller
numberOfDigits = numOfDigits;
digit1 = dig1;
digit2 = dig2;
digit3 = dig3;
digit4 = dig4;
digitApostrophe = digitApos;
digitColon = digitCol;
segmentA = segA;
segmentB = segB;
segmentC = segC;
segmentD = segD;
segmentE = segE;
segmentF = segF;
segmentG = segG;
segmentDP = segDP;
segmentApostrophe = segApos;
segmentColon = segCol;
//Assign input values to variables
//mode is what the digit pins must be set at for it to be turned on. 0 for common cathode, 1 for common anode
mode = mode_in;
if(mode == COMMON_ANODE)
{
DigitOn = HIGH;
DigitOff = LOW;
SegOn = LOW;
SegOff = HIGH;
}
else
{
DigitOn = LOW;
DigitOff = HIGH;
SegOn = HIGH;
SegOff = LOW;
}
DigitPins[0] = digit1;
DigitPins[1] = digit2;
DigitPins[2] = digit3;
DigitPins[3] = digit4;
SegmentPins[0] = segmentA;
SegmentPins[1] = segmentB;
SegmentPins[2] = segmentC;
SegmentPins[3] = segmentD;
SegmentPins[4] = segmentE;
SegmentPins[5] = segmentF;
SegmentPins[6] = segmentG;
SegmentPins[7] = segmentDP;
//Turn everything Off before setting pin as output
//Set all digit pins off. Low for common anode, high for common cathode
for (byte digit = 0 ; digit < numberOfDigits ; digit++)
{
digitalWrite(DigitPins[digit], DigitOff);
pinMode(DigitPins[digit], OUTPUT);
}
//Set all segment pins off. High for common anode, low for common cathode
for (byte seg = 0 ; seg < 8 ; seg++)
{
digitalWrite(SegmentPins[seg], SegOff);
pinMode(SegmentPins[seg], OUTPUT);
}
if (digitColon != 255)
{
digitalWrite(digitColon, DigitOff);
pinMode(digitColon, OUTPUT);
digitalWrite(segmentColon, SegOff);
pinMode(segmentColon, OUTPUT);
}
if (digitApostrophe != 255)
{
digitalWrite(digitApostrophe, DigitOff);
pinMode(digitApostrophe, OUTPUT);
digitalWrite(segmentApostrophe, SegOff);
pinMode(segmentApostrophe, OUTPUT);
}
}
//Begin
/*******************************************************************************************/
//Set pin modes and turns all displays off
//This second begin is used when the display does not support a colon and apostrophe
//The digitApostrophe, segmentApostrophe, and dig/segColon are set to 255 and the normal .Begin is called
void SevSeg::Begin(boolean mode_in, byte numOfDigits,
byte dig1, byte dig2, byte dig3, byte dig4,
byte segA, byte segB, byte segC, byte segD, byte segE, byte segF, byte segG,
byte segDP)
{
Begin(mode_in, numOfDigits, dig1, dig2, dig3, dig4, 255, 255, segA, segB, segC,
segD, segE, segF, segG, segDP, 255, 255);
}
//Set the display brightness
/*******************************************************************************************/
//Given a value between 0 and 100 (0% and 100%), set the brightness variable on the display
//We need to error check and map the incoming value
void SevSeg::SetBrightness(byte percentBright)
{
//Error check and scale brightnessLevel
if(percentBright > 100) percentBright = 100;
brightnessDelay = map(percentBright, 0, 100, 0, FRAMEPERIOD); //map brightnessDelay to 0 to the max which is framePeriod
}
//Refresh Display
/*******************************************************************************************/
//Given a string such as "-A32", we display -A32
//Each digit is displayed for ~2000us, and cycles through the 4 digits
//After running through the 4 numbers, the display is turned off
//Will turn the display on for a given amount of time - this helps control brightness
void SevSeg::DisplayString(const char* toDisplay, byte DecAposColon)
{
//For the purpose of this code, digit = 1 is the left most digit, digit = 4 is the right most digit
for(byte digit = 1 ; digit < (numberOfDigits+1) ; digit++)
{
switch(digit)
{
case 1:
digitalWrite(digit1, DigitOn);
break;
case 2:
digitalWrite(digit2, DigitOn);
break;
case 3:
digitalWrite(digit3, DigitOn);
break;
case 4:
digitalWrite(digit4, DigitOn);
break;
//This only currently works for 4 digits
}
//Here we access the array of segments
//This could be cleaned up a bit but it works
//displayCharacter(toDisplay[digit-1]); //Now display this digit
// displayArray (defined in SevSeg.h) decides which segments are turned on for each number or symbol
unsigned char characterToDisplay = toDisplay[digit-1];
if (characterToDisplay & 0x80) // bit 7 enables bit-per-segment control
{ // Each bit of characterToDisplay turns on a single segment (from A-to-G)
if (characterToDisplay & 0x01) digitalWrite(segmentA, SegOn);
if (characterToDisplay & 0x02) digitalWrite(segmentB, SegOn);
if (characterToDisplay & 0x04) digitalWrite(segmentC, SegOn);
if (characterToDisplay & 0x08) digitalWrite(segmentD, SegOn);
if (characterToDisplay & 0x10) digitalWrite(segmentE, SegOn);
if (characterToDisplay & 0x20) digitalWrite(segmentF, SegOn);
if (characterToDisplay & 0x40) digitalWrite(segmentG, SegOn);
}
else
{
const uint8_t chr = pgm_read_byte(&characterArray[characterToDisplay]);
if (chr & (1<<6)) digitalWrite(segmentA, SegOn);
if (chr & (1<<5)) digitalWrite(segmentB, SegOn);
if (chr & (1<<4)) digitalWrite(segmentC, SegOn);
if (chr & (1<<3)) digitalWrite(segmentD, SegOn);
if (chr & (1<<2)) digitalWrite(segmentE, SegOn);
if (chr & (1<<1)) digitalWrite(segmentF, SegOn);
if (chr & (1<<0)) digitalWrite(segmentG, SegOn);
}
//Service the decimal point, apostrophe and colon
if ((DecAposColon & (1<<(digit-1))) && (digit < 5)) //Test DecAposColon to see if we need to turn on a decimal point
digitalWrite(segmentDP, SegOn);
delayMicroseconds(brightnessDelay + 1); //Display this digit for a fraction of a second (between 1us and 5000us, 500-2000 is pretty good)
//The + 1 is a bit of a hack but it removes the possible zero display (0 causes display to become bright and flickery)
//If you set this too long, the display will start to flicker. Set it to 25000 for some fun.
//Turn off all segments
digitalWrite(segmentA, SegOff);
digitalWrite(segmentB, SegOff);
digitalWrite(segmentC, SegOff);
digitalWrite(segmentD, SegOff);
digitalWrite(segmentE, SegOff);
digitalWrite(segmentF, SegOff);
digitalWrite(segmentG, SegOff);
digitalWrite(segmentDP, SegOff);
//Turn off this digit
switch(digit)
{
case 1:
digitalWrite(digit1, DigitOff);
break;
case 2:
digitalWrite(digit2, DigitOff);
break;
case 3:
digitalWrite(digit3, DigitOff);
break;
case 4:
digitalWrite(digit4, DigitOff);
break;
//This only currently works for 4 digits
}
// The display is on for microSeconds(brightnessLevel + 1), now turn off for the remainder of the framePeriod
delayMicroseconds(FRAMEPERIOD - brightnessDelay + 1); //the +1 is a hack so that we can never have a delayMicroseconds(0), causes display to flicker
}
//After we've gone through the digits, we control the colon and apostrophe (if the display supports it)
//Turn on the colon and/or apostrophe
if ((digitColon != 255) || (digitApostrophe != 255))
{
if (DecAposColon & (1<<4)) //Test to see if we need to turn on the Colon
{
digitalWrite(digitColon, DigitOn);
digitalWrite(segmentColon, SegOn);
}
if (DecAposColon & (1<<5)) //Test DecAposColon to see if we need to turn on Apostrophe
{
digitalWrite(digitApostrophe, DigitOn);
digitalWrite(segmentApostrophe, SegOn);
}
delayMicroseconds(brightnessDelay + 1); //Display this digit for a fraction of a second (between 1us and 5000us, 500-2000 is pretty good)
//Turn off the colon and/or apostrophe
digitalWrite(digitColon, DigitOff);
digitalWrite(segmentColon, SegOff);
digitalWrite(digitApostrophe, DigitOff);
digitalWrite(segmentApostrophe, SegOff);
delayMicroseconds(FRAMEPERIOD - brightnessDelay + 1); //the +1 is a hack so that we can never have a delayMicroseconds(0), causes display to flicker
}
}