Posted on Tuesday, October 12th, 2010
I decided to send one of my good friends in Germany an Arduino starter kit for his birthday. Instead of the usual birthday card, I thought that it could be cool to have a single 7-segment LED pre-wired to the Arduino so it can display something like “Happy Birthday!” as soon as he plugs it in.
Since I didn’t want to break in his brand new starter kit, I decided to use one of my spare Proto Shields and a bunch of other spare parts (1 x 74HC595 8-bit Shift Register, 8 x 220 Ω resistors, 1 x 7-segment common anode display) and started building a circuit that is very similar to the one in theArduino ShiftOut Tutorial.
The main difference is that due to the common anode display, we’re dealing with an active-low circuit as opposed to an active-high circuit as described in the tutorial. That basically means that everything works exactly “the other way round”, meaning that we have to wire the individual cathodes to the output of the shift-register and send a low-bit in order to activate an LED segment of the display and a high-bit to deactivate it.
To make the transition between the individual 7-segment characters more visually pleasing, I also wired the display’s anode to one of the Arduino’s analog pins. This allows me to control the brightness of the 7-segment display via PWM.
The code example is pretty straight forward: it cycles through the 128-characters of the 7-segment character set, inverts the bits (remember the cathodes of the LEDs are connected to the 74HC595) and shifts them out to the register using Arduino’s built-in shiftOut() function. Between each character, it fades the display’s brightness down to 0% and than back up to 100% using analogWrite().
There’s a good article on 7-segment display character representations at Wikipedia, but I decided to use the 7-segment character set (which is pretty nice, btw) from Eli McIlveen. He was nice enough to put it in the public domain. The really nice thing about his character set is, that the character positions in the array match their ASCII representation: for example A can be found at ledCharSet['A'], B at ledCharSet['B'] and so on. That way it was really a no-brainer to display my “Happy Birthday” message. Here’s the source code and wiring diagrams:
/* Example code for driving a single 7-segment display with
a 74HC595 8-bit shift register
The code cycles through the the entire 7-segment character
set that was written by Eli McIlveen:
(http://www.forgeryleague.com/lab/entry/arduino_7_segment_output/)
In case of a COMMON ANODE display the bytes need to be inverted
as shown in the loop() function: bitsToSend = bitsToSend ^ B11111111
Hardware:
* 74HC595 shift register attached to pins 2, 3, and 4 of the Arduino,
as detailed below.
* Pins to connect to common-cathode LED display via a 74HC595:
DP-15, A-1, B-2, C-3, D-4, E-5, F-6, G-7 (shiftOut using LSBFIRST)
Or:
DP-7, A-6, B-5, C-4, D-3, E-2, F-1, G-15 (shiftOut using MSBFIRST)
Created 12 October 2010
by Ole Weidner (http://www.oleweidner.com/?p=434)
*/
const byte ledCharSet[128] =
{
// 00-0F: Hex digits
B01111110, B00110000, B01101101, B01111001, // 0123
B00110011, B01011011, B01011111, B01110000, // 4567
B01111111, B01111011, B01110111, B00011111, // 89AB
B01001110, B00111101, B01001111, B01000111, // CDEF
// 10-1F: Figure-8 drawing (8-character cycle)
B01000000, B00100000, B00000001, B00000100, // 1-segment
B00001000, B00010000, B00000001, B00000010,
B01100000, B00100001, B00000101, B00001100, // 2-segment
B00011000, B00010001, B00000011, B01000010,
// 20-2F: Punctuation (barely recognizable!)
B00000000, B10100000, B00100010, B00111111, // !"#
B01011010, B01001001, B00000111, B00000010, // $%&'
B01001110, B01111000, B01100011, B00110001, // ()*+
B00010000, B00000001, B10000000, B00100101, // ,-./
// 30-3F: Decimal digits (alternate) and more punctuation
B01111110, B00110000, B01101101, B01111001, // 0123
B00110011, B01011011, B00011111, B01110010, // 4567
B01111111, B01110011, B01001000, B01010000, // 89:;
B00001101, B00001001, B00011001, B11100000, // <=>?
// 40-5F: Capital letters and punctuation
B01101110, B01110111, B00011111, B01001110, // @ABC
B01111100, B01001111, B01000111, B01011110, // DEFG
B00110111, B00000110, B00111100, B01010111, // HIJK
B00001110, B01110110, B00010101, B01111110, // LMNO
B01100111, B01110011, B01000110, B01011011, // PQRS
B01110000, B00111110, B00111110, B00101011, // TUVW
B01110101, B00111011, B01101101, B01001110, // XYZ[
B00010011, B01111000, B01100010, B00001000, // \]^_
// 60-7F: Lowercase letters and punctuation
B01100000, B01111101, B00011111, B00001101, // `abc
B00111101, B01101111, B01000111, B01111011, // defg
B00010111, B00010000, B00011000, B00101111, // hijk
B00001100, B01010101, B01101010, B00011101, // lmno
B01100111, B01110011, B00000101, B00010011, // pqrs
B00001111, B00011100, B00100011, B01011101, // tuvw
B01101100, B00111011, B00100101, B01000011, // xyz{
B00110110, B01100001, B01000000, B11111111 // |}~
};
//// Pin connected to latch pin (ST_CP) of 74HC595
const int latchPin = 8;
//// Pin connected to clock pin (SH_CP) of 74HC595
const int clockPin = 12;
//// Pin connected to Data in (DS) of 74HC595
const int dataPin = 11;
//// Pin connected to display's common annode
const int faderPin = 10;
/////////////////////////////////////////////////////////////////////////////////
//
void setup()
{
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(faderPin, OUTPUT);
}
/////////////////////////////////////////////////////////////////////////////////
//
void loop()
{
for(int i=0; i <= 128; ++i)
{
byte bitsToSend = ledCharSet[i];
// invert bitmas - we're using a common ANODE display.
// for common cathode, comment out the following line.
bitsToSend = bitsToSend ^ B11111111;
// turn off the output so the pins don't light up
// while you're shifting bits:
digitalWrite(latchPin, LOW);
// shift the bits out:
shiftOut(dataPin, clockPin, MSBFIRST, bitsToSend);
// turn on the output so the LEDs can light up:
digitalWrite(latchPin, HIGH);
fadeInOut();
}
}
/////////////////////////////////////////////////////////////////////////////////
//
void fadeInOut()
{
for(int i = 0; i < 255; ++i)
{
analogWrite(faderPin, i);
delay(1);
}
for(int i = 255; i > 0; --i)
{
analogWrite(faderPin, i);
delay(1);
}
}
Download Source Code: SevenSeg_CommonAnnode_74HC595.pde
-
Thank you for your write up. There are 3 errors in your posted code, simply due to html. Lines 99, 125 should have
-
[...] Dimmable 7-Segment Common Anode Display with Arduino & 74HC595 Shift-Register by Ole Weidner. Deals with a 7-segment common anode display AND uses a shift register, yay. [...]
-
Hey,
Nice little tutorial, Thanks.I’m a bit of a newby at this game and I’m trying to understand what is going on inside the shift register. Given that we were able to hook the display up ‘backwards’ due to the common anode, does this mean that the shift register output pins are essentially grounded when pulled low (lighting the LED), and 5V when high (going against the diode and so it is off)?
-
I may be getting this wrong, but do you have a transistor between your common anode and your arduino?
if the voltage drop on a segment of the red LED display is around 1.7V then with a 220 R resistor you have 15mA per segment – fine for one segment, but if you light all eight (including the decimal point) then you will draw 120 mA, or 3 times the max that an Ardu’ can safely supply. Put a transistor in there and you’re fine but I can’t see how you do this direct from the board.
Any thoughts?


5 Responses to Dimmable 7-Segment Common Anode Display with Arduino & 74HC595 Shift-Register