Go Down

Topic: Arduino +Sparkfuns 4-digit 7-segment 16pin display (Read 26 times) previous topic - next topic


I just received the following 2 4-digit, 7-segment displays from sparkfun:

The only difference between the 2 is the color and the voltage is 2.1V vs 3.4V.

So normally, a quick google search yields me pages of guidance, tutorials, schematics, and code.  I can't seem to find much on these displays, I suppose they are relatively new.

Has anyone successfully been able to use these displays?  If so, can you please supply your code, a schematic, and/or advice/tips?  

Any help is greatly appreciated!!



I was about to send the same post as you...

Did someone successfully used these 4digit 7segment 16 pin displays ?




Don't have one, but looks easy enough.  Connect the common anode digits contacts through transistors to individual arduino pins.  Connect the seven segments (A - G) and the decimal contact through resistors to arduino pins.  If you want to use the colon and/or apostrophe, connect the cathode through a resistor to +5 and the anode to an arduino pin.

Takes a bunch of pins of course.  You could use shift registers if you want.  

Look in the forum for threads on driving seven segment displays.  You are multiplexing (one digit at a time).  You drive a digit pin high (which drives the anode low).  You drive the segment pins high to light a segment.  You pause, drive the anode pin low, and move on to the next digit.  You might use  100hz, so each digit is on for 2.5ms

If you use the colon/apostrophe, drive it during one of the digits, so it has the same on time as a digit.


Feb 21, 2010, 06:19 am Last Edit: Mar 26, 2011, 09:00 pm by hari Reason: 1
In case you missed it, the PINOUTS IN THE DATASHEET IS WRONG!  You can get the correct pinout from SparkFun's product page.

I'm a n00b too and I was able to get it to work using the corrected info. As brtech said, I just wired up Arduino digital pins 0 thru 6 to drive segments A thru G (via 1K resistors), and pins 10 thru 13 to drive the digits.

Before someone yells at me, I know, I know... it is terribly wasteful to use so many Arduino pins to drive this display directly.  In "real life" one should use a 7-segment display driver.

Here are the two sketches that I saved while playing with it last week. I have since disassembled the circuit so I can't test it now.  It should work.  :)

This one simply tests each digit in turn (no multiplexing).  I used this sketch to test that I've wired everything up correctly before I worked on trying to get them all lit up "at the same time".

Code: [Select]
 Testing SparkFun's 4-digit 7-Segment Display (Blue)

int segmentA = 0;
int segmentB = 1;
int segmentC = 2;
int segmentD = 3;
int segmentE = 4;
int segmentF = 5;
int segmentG = 6;
int segmentP = 7;

int digit1 = 10;
int digit2 = 11;
int digit3 = 12;
int digit4 = 13;

10 digits:
Each defines which segments should be on/off for that digit: A,B,C,D,E,F,G,P
byte numbers[10] =
 B11000000, // 0
 B11111001, // 1
 B10100100, // 2
 B10110000, // 3
 B10011001, // 4
 B10010010, // 5
 B10000010, // 6
 B11111000, // 7
 B10000000, // 8
 B10010000  // 9

void setup()


void loop()
 for (int digitPosition=0; digitPosition < 4; digitPosition++)
   digitalWrite(digit1 + digitPosition,HIGH);

   for (int numIndex=0; numIndex <= 9; numIndex++)
     int number =  numbers[numIndex];
     digitalWrite(segmentA, bitRead(number, 0) );
     digitalWrite(segmentB, bitRead(number, 1) );
     digitalWrite(segmentC, bitRead(number, 2) );
     digitalWrite(segmentD, bitRead(number, 3) );
     digitalWrite(segmentE, bitRead(number, 4) );
     digitalWrite(segmentF, bitRead(number, 5) );
     digitalWrite(segmentG, bitRead(number, 6) );
     digitalWrite(segmentP, bitRead(number, 7) );

   digitalWrite(digit1 + digitPosition,LOW);

I am not sure if this is the best way to multiplex a 4-digit 7-segment display, but this is what I came up with.  It displays 4 digits counting up as seen in the photo above.
Code: [Select]

 Testing SparkFun's 4-digit 7-Segment Display (Blue)

int segmentA = 0; // Segments A thru P == pins 0 thru 7
int digit0 = 10; // Digits 3 thru 0 == pins 10 thru 13 (0 is LEFT most digit)

10 digits:
Each defines which segments should be on/off for that digit: A,B,C,D,E,F,G,P
byte numbers[10] =
 B11000000, // 0
 B11111001, // 1
 B10100100, // 2
 B10110000, // 3
 B10011001, // 4
 B10010010, // 5
 B10000010, // 6
 B11111000, // 7
 B10000000, // 8
 B10010000  // 9

void setup()
 for (byte segment = 0; segment < 8; segment++)

 for (byte digit = 0; digit < 4; digit++)

int perDigitTime = 100;
int digitPosition = 1;  // Start anywhere but zero so we won't crash when we try to turn off previous digit.
unsigned long previousMillis = 0;

int value = 0;
int powerOfTen[] = {

void RefreshDisplay()
 digitalWrite(digit0 + digitPosition, LOW);  // Turn off previous digit

 if (digitPosition > 3) digitPosition = 0;

 int digitValue = value % powerOfTen[ digitPosition+1 ] / powerOfTen[digitPosition];
 int number =  numbers[ digitValue ];
 if ((number > 0) || (value < powerOfTen[ digitPosition+1 ]))
 for (byte seg = 0; seg < 8; seg++)
   digitalWrite(segmentA+seg, bitRead(number, seg) );

 digitalWrite(digit0 + digitPosition, HIGH);

void loop()
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis > perDigitTime)
   previousMillis = currentMillis;


I'd be happy to try to answer your questions if this is still unclear.


Hi All.

After my fisrt post, I got deeper in the net and found some example here : http://nootropicdesign.com/projectlab/2009/10/.

I managed to use the display. Here is the code and a picture of the "beast" with pins explanation (actually, it only displays 1 2 3 4 but from my point of view a good example to understand how it works).
(Note : I can't manage to post a picture. If someone explain me how to do it, i'll post the picture...)

The code does not use decimal points and colons but as soon as you will have understand the code, you will agree that it is easy to add.

A question for hari : I don't understand why you got so many resistances ? I only used 1 resistance per digit positive entry (not for A, B, C, D, E, F, G...). Is it a mistake ?

If any questions, feel free.


------------------ CODE TESTED OK ------------------------
// These are indexes into the groundPins array
#define G 6
#define F 5
#define E 4
#define D 3
#define C 2
#define B 1
#define A 0

int groundPins[8] = {0, 1, 2, 3, 4, 5, 6, 7};
int digitPins[4] = {8, 12, 10, 11}; // positive voltage supply for each of the 4 digits
int ON = HIGH;
int OFF = LOW;
int number[10][7]; // holds information about which segments are needed for each of the 10 numbers
int digit[4]; // holds values for each of the 4 display digits

void setup()
 // Fill the numbers array
 // Set ground pin to output/high
 for(int i=0; i < 8; i++)
   pinMode(groundPins, OUTPUT);
   digitalWrite(groundPins, HIGH);
 } // end  for(int i=0; i < 8; i++)

 // Set digit pin to output/low
 for(int i=0; i < 4; i++)
   pinMode(digitPins, OUTPUT);
   digitalWrite(digitPins, LOW);
 } // end for(int i=0; i < 2; i++)

} // end void setup()

void loop()
 digit[0] = 1;
 digit[1] = 2;
 digit[2] = 3;
 digit[3] = 4;

} // end void loop()

void DisplayNumber()
 for(int g=0; g < 7; g++)
   digitalWrite(groundPins[g], LOW);
   for(int i=0; i < 4; i++)
     if (digit < 0)
     digitalWrite(digitPins, number[digit][g]);
  // delay(getDelay());
   delay(1); // Don't understand why I Have to set a delay
   digitalWrite(groundPins[g], HIGH);
} // end void DisplayNumber()

int getDelay() {
 if (millis() > 10000) {
   return 0;
 } else {
   return (int) (((10000 - millis()) / 10000.0) * 125);

void initNumber()
// Fill an array (declared as global variable) with high/low values for numbers
 number[0][G]  = OFF;
 number[0][F] = ON;
 number[0][E] = ON;
 number[0][D]  = ON;
 number[0][C] = ON;
 number[0] = ON;
 number[0][A]     = ON;

 number[1][G]  = OFF;
 number[1][F] = OFF;
 number[1][E] = OFF;
 number[1][D]  = OFF;
 number[1][C] = ON;
 number[1] = ON;
 number[1][A]     = OFF;

 number[2][G]  = ON;
 number[2][F] = OFF;
 number[2][E] = ON;
 number[2][D]  = ON;
 number[2][C] = OFF;
 number[2] = ON;
 number[2][A]     = ON;

 number[3][G]  = ON;
 number[3][F] = OFF;
 number[3][E] = OFF;
 number[3][D]  = ON;
 number[3][C] = ON;
 number[3] = ON;
 number[3][A]     = ON;

 number[4][G]  = ON;
 number[4][F] = ON;
 number[4][E] = OFF;
 number[4][D]  = OFF;
 number[4][C] = ON;
 number[4] = ON;
 number[4][A]     = OFF;

 number[5][G]  = ON;
 number[5][F] = ON;
 number[5][E] = OFF;
 number[5][D]  = ON;
 number[5][C] = ON;
 number[5] = OFF;
 number[5][A]     = ON;

 number[6][G]  = ON;
 number[6][F] = ON;
 number[6][E] = ON;
 number[6][D]  = ON;
 number[6][C] = ON;
 number[6] = OFF;
 number[6][A]     = ON;

 number[7][G]  = OFF;
 number[7][F] = OFF;
 number[7][E] = OFF;
 number[7][D]  = OFF;
 number[7][C] = ON;
 number[7] = ON;
 number[7][A]     = ON;

 number[8][G]  = ON;
 number[8][F] = ON;
 number[8][E] = ON;
 number[8][D]  = ON;
 number[8][C] = ON;
 number[8] = ON;
 number[8][A]     = ON;

 number[9][G]  = ON;
 number[9][F] = ON;
 number[9][E] = OFF;
 number[9][D]  = ON;
 number[9][C] = ON;
 number[9] = ON;
 number[9][A]     = ON;


Feb 23, 2010, 01:17 am Last Edit: Feb 23, 2010, 01:18 am by ninjamastr Reason: 1
Hey guys,

Wow, I posted this a while back and didn't think any responses were coming.  Thanks to everyone who contributed!

I've managed to resolve my issues with this display and it's working nicely now.  

I also have this working with an 8-bit shift register (http://www.sparkfun.com/datasheets/IC/SN74HC595.pdf also from SparkFun).  So this might be of interest for you guys if you wanna use less arduino pins.

Please note: since my project involves temperature readings, this code is specifically for displaying temperature so digit 4 can be a 'C' or an 'F' and there are no decimals.

Here is the code along with pin descriptions.  I welcome any suggestions/questions/comments so please feel free to post:

Code: [Select]


4 Digit 7 Segment display from Sparkfun
1: Digit 1         16: B
2: Digit 2         15: G
3: D                 14: A
4: Colon Anode         13: C
5: E                 12: Colon Cathode
6: Digit 3         11: F
7: Decimal Point  10: Apostrophe Anode
8: Digit 4         9:  Apostrophe Cathode

8 Bit Shift Register

1: display's B    16: 5V    
2: display's C    15: display's A
3: display's D    14: arduino's dataPin
4: display's E    13: Gnd
5: display's F    12: arduino's latchPin
6: display's G    11: arduino's clockPin
7: display's DP   10: 5V
8: Gnd            9:  none

Display's Cathode goes to ground via resistor
Display's Anode goes to digital out
Digit pins go to digital out via resistor
Segment pins (A-G) go to digital out or shift register out (0 is on)

original shift reg code:

helpful schematic:


int latchPin = 8;  //Pin connected to ST_CP of 74HC595 (aka RCLK)
int clockPin = 12;  //Pin connected to SH_CP of 74HC595 (aka SRCLK)
int dataPin = 11;  //Pin connected to DS of 74HC595 (aka SER)

int digit1Pin = 5;  //can't use pin 1 since it's TX?
int digit2Pin = 2;
int digit3Pin = 3;
int digit4Pin = 4;

byte data;
byte dataArray[13];

const int MINUS_IDX = 10;
const int CELCIUS_IDX = 11;
const int FARENHEIT_IDX = 12;

void setup(){
 pinMode(digit1Pin, OUTPUT);
 pinMode(digit2Pin, OUTPUT);
 pinMode(digit3Pin, OUTPUT);
 pinMode(digit4Pin, OUTPUT);

 pinMode(latchPin, OUTPUT);


 //      A
 //    F   B
 //      G
 //    E   C
 //      D   dp (H)
 //  In binary representation, right most digit is A
 dataArray[0] = B11000000;
 dataArray[1] = B11111001;
 dataArray[2] = B10100100;
 dataArray[3] = B10110000;
 dataArray[4] = B10011001;
 dataArray[5] = B10010010;
 dataArray[6] = B10000010;
 dataArray[7] = B11111000;
 dataArray[8] = B10000000;
 dataArray[9] = B10010000;
 //temperature specific characters
 dataArray[MINUS_IDX] = B10111111;  // minus sign
 dataArray[CELCIUS_IDX] = B11000110;  // C
 dataArray[FARENHEIT_IDX] = B10001110;  // F

void loop(){

 setTemp(-23, 'C');
   //setDigit(digit1Pin, 3);
   //setDigit(digit2Pin, 4);
   //setDigit(digit3Pin, 5);
   //setDigit(digit4Pin, 6);

void setTemp(int temp, char scale){
 //temp must be between -99 and 999 in either scale to fit the display
 //put in a check here later
 boolean negative = false;
 if (temp < 0)
   negative = true;
 temp = abs(temp);
 if (scale == 'F'){
   setDigit(digit4Pin, FARENHEIT_IDX);
 } else if (scale == 'C'){
   setDigit(digit4Pin, CELCIUS_IDX);
 setDigit(digit3Pin, temp % 10);
 temp /= 10;
 if (temp >= 1){
   setDigit(digit2Pin, temp % 10);
   temp /= 10;
   if (temp >= 1){
     setDigit(digit1Pin, temp % 10);
 if (negative){
   setDigit(digit1Pin, MINUS_IDX);

void setDigit(int digitPin, int value){
   digitalWrite(latchPin, 0);
   shiftOut(dataPin, clockPin, dataArray[value]);  
   digitalWrite(latchPin, 1);
   digitalWrite(digitPin, HIGH);
   digitalWrite(digitPin, LOW);  

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
 // This shifts 8 bits out MSB first,
 //on the rising edge of the clock,
 //clock idles low

 //internal function setup
 int i=0;
 int pinState;
 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, OUTPUT);

 //clear everything out just in case to
 //prepare shift register for bit shifting
 digitalWrite(myDataPin, 0);
 digitalWrite(myClockPin, 0);

 //for each bit in the byte myDataOut[ch65533]
 //This means that %00000001 or "1" will go through such
 //that it will be pin Q0 that lights.
 for (i=7; i>=0; i--)  {
   digitalWrite(myClockPin, 0);

   //if the value passed to myDataOut and a bitmask result
   // true then... so if we are at i=6 and our value is
   // %11010100 it would the code compares it to %01000000
   // and proceeds to set pinState to 1.
   if ( myDataOut & (1<<i) ) {
     pinState= 1;
   else {      
     pinState= 0;

   //Sets the pin to HIGH or LOW depending on pinState
   digitalWrite(myDataPin, pinState);
   //register shifts bits on upstroke of clock pin  
   digitalWrite(myClockPin, 1);
   //zero the data pin after shift to prevent bleed through
   digitalWrite(myDataPin, 0);

 //stop shifting
 digitalWrite(myClockPin, 0);


By the way,
Like jeremytsl, I also used 1 resistor per digit instead of 1 per segment.  I'm not entirely sure but I think you can get away with that.


You want one resistor per segment, not per digit.

You are multiplexing digits: one digit at a time
You are parallelling segments: 1 to 7 segments at a time

You want the same current through each segment, no matter how many segments you drive.

So, you put a resistor per segment.

If you had a resistor per digit, then you would have lower current per segment with an 8 (all segments driven) then with a 1 (2 segments driven).  This would show up as different brightness for different numbers.

With a resistor per segment, each segment has the same current, no matter how many of them are lit.

You all are driving the digits directly.  That is okay as long as the resistor value is high enough.  You need the current through the digit (which is the sum of the current through each segment) to be less than 40 ma).

To drive this at high brightness, you would use something in the range of 220-470 ohms per segment, but that would be much more than 40 ma per digit.  With 1K @ 5V, you have max 5 ma per segment, and 8*5 = 40 ma per digit, so you are okay.  

If you used smaller series resistors on the segment drives, you would need to buffer the Arduino output with a transistor.

if you were to use something else to drive the digits (shift register), that 40 ma may not work.  Some shift registers can't sink 20 ma per segment either.


Thanks for the resistance / segment explanation.

I was using 1kOhms with 5V which explains I did not see the difference (I am lucky  :) )

Have a nice day.



Write up some code that switches a digit back and forth between "1" and "8".  I think you will see a brightness difference.  "1" will be brighter than "8".


Thanks for answering Jeremytsl question about the resistor.

Wow, the wiring on that clock you have on your blog is so much more compact than my breadboard. Nice...

Your code for figuring out the value of each digit is much easier to understand than my power of ten array.

I think this is part of what makes the Arduino cool.  There's a lot of sharing going on.


you're so right, the arduino community is amazingly helpful.  Our projects could combine to form some sort of super voltron clock display robot.

thanks for breaking this down for us.  Your explanation makes sense and I will experiment with changing digits and observing brightness.

I don't fully understand the 2nd part of your explanation tho, please bare with me and my questions:


You all are driving the digits directly.  That is okay as long as the resistor value is high enough.  You need the current through the digit (which is the sum of the current through each segment) to be less than 40 ma).

How did you figure out this 40ma limit?  The description on SF.com says "max forward current of 20mA"


If you used smaller series resistors on the segment drives, you would need to buffer the Arduino output with a transistor.

What would happen if you didn't, and your current on each digit exceeds 40ma?  Would the LED's burn out?


if you were to use something else to drive the digits (shift register), that 40 ma may not work.  Some shift registers can't sink 20 ma per segment either.

This part concerns me since I'm using a shift register (74HC595).  What would you recommend I do?  I've looked over the datasheet, but it makes little sense to me.  
it says "+/- 6ma Output Drive at 5 V".  Does that mean it's giving me 6ma per segment without any resistors?

Thanks in advance


40 ma is the max output of an Arduino pin, and you can't drive ALL of them at the same time at 40 ma.

If you go over it, you might burn out the microprocessor.

The 20 ma is the max current per segment i believe.  if you lit 8 segments at 20 ma, the digit would need 160ma.  Way more than the Arduino can supply.  A cheap npn transistor could do that tho.

The datasheet is a bit weird, but yes, 6ma is what their typical output current is going to be.  You can light a segment with that (not a digit), with the right value resistor, but the display won't be anywhere near as bright as it would closer to 20 ma per segment.  With this device driving an LED, you can tolerate the output voltages getting a bit out of spec, so you might push that 6 ma a bit.  8ma probably works, maybe even 10.

But keep in mind that you will be driving all 8 segments from one 595.  the max continuous current you can source/sink from the device is 70ma.  8 x 6 = 48, so you are okay there.  Trying to run 8 x 10 ma wouldn't work.  8 x 8 is 64, pretty close to the limit.  


Boy, do I have a lot to learn about electronics.  

Thanks brtech for shedding some light on this stuff.


I picked up one of those (the blue ones) and i'm looking for a driver for it.  I can't seem to find any decent digit multiplexing ICs for a CA display.

SAA1064 does pretty much everything I want it to (I2C, self multiplexing, small programing footprint, little processor overhead) but I don't figure I can get it working with that display (at least not for 4 unique digits).

I don't want to go with a BCD unless it'll output Hex as well (can't remember the proper name for them).

I figured out a decient solution using 4x 8 bit shift registers, a 4 bit (or and multiple of 4) an 8 channel mux, a few transistors and an oscillator.

Thus far, octopart has failed me in my search for a 7-segment 4 digit(+) driver w/ CA. Can I just use a chip made for CC and use some transistors?

Go Up