Introduction: Different Methods of Driving 7 Segment LED Displays With Arduino

I would just like to show a few different methods of connecting 7 segment LED displays to an Arduino or Atmega 328 IC. They are only simple counter codes either automatically counting via the code or incremented / decremented via a pair of push button switches or a potentiometer . I have used 220 Ω resistors in all these circuits but you would be advised to calculate the correct ones required for the particular 7 segment displays that your are using. This will ensure that you do not damage the IO pins of the 328 IC. The constraints to these maximum currents, courtesy of
http://www.gammon.com.au/forum/?id=11473
are -
- The IO pins have an absolute maximum rating of 40 mA per pin.
- Also the following groups of pins should not have more than 100 mA drawn from them
* Digital pins 0 to 4
* Digital pins 5 to 1
* Analog pins A0 to A5
- In addition to that, the entire processor chip has a maximum rating of 200 mA current consumption.

The 7 segment LED displays are common cathode and the shift register is a 74HC595. I have included a photo of the 7 segment LED from the front showing the relationship between the pin numbers and the corresponding LED segment that the pin controls.

I also have this same content on a hand coded website at

http://www.pedrosdigitalsolutions.com/7SegLEDcircu...

It is not a responsive site so it is best viewed on a laptop or desktop computer. The Arduino code is nicely formatted by some Javascript that a friend wrote and overall it is just much more aesthetically pleasing content IMO. Thanks for dropping by :)



Step 1:

  1. Directly from Arduino / Atmega 328
  2. Via shift register from Arduino / Atmega 328
  3. Directly from Arduino / Atmega 328 with direct port manipulation
  4. Multiplexed via shift register from Arduino / Atmega 328 / Pushbutton counter
  5. Multiplexed via shift register from Arduino / Atmega 328 / Potentiometer counter

1 - Directly from Arduino / Atmega 328
Counts automatically from zero to nine and then repeats


Code
// Thanks to Grumpy Mike http://www.thebox.myzen.co.uk/Tutorial/Arrays.html
// LED Segment allocation within byte = {DP ABCDEFG }
int pins [] = {2, 3, 4, 5, 6, 7, 8, 9 }; // pin 9 allocated to DP but not used (first element of binary array in char tenCode)
int digit[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int counter = 0; // initialise counter as zero
int timer = 1000; // delay timer interval
char tenCode[] = {B01111110, B00110000, B01101101, B01111001, B00110011, B01011011, B01011111, B01110000, B01111111, B01111011 };
void setup()
{
for(int i = 0; i < 8; i++) // set digital pins as OUTPUTS
pinMode(pins[i], OUTPUT);
}
void loop()
{
for(int j = 0; j < 10; j++)
{
displayEleven(digit[j]);
delay(timer);
}
}
void displayEleven(int num)
{
int mask = 1;
for(int i = 0; i < 8; i++)
{
if((mask & tenCode[num]) == 0)
digitalWrite(pins[i], LOW);
else digitalWrite(pins[i], HIGH);
mask = mask << 1;
}
}


Step 2:

2 - Via shift register from Arduino / Atmega 328

Counts automatically from zero to nine and then repeats

Code

// LED Segment allocation within byte = {ABCDEFG DP}

int latchPin = 8;    // connect to pin 12 on the shift register

int dataPin  = 11;   // connect to pin 14 on the shift register

int clockPin = 12;   // connect to pin 11 on the shift register

int i = 0;

byte digit[] = {B11111100,B01100000,B11011010,B11110010,B01100110,B10110110,B10111110,

B11100000,B11111110,B11110110};

void setup()

{

pinMode(dataPin, OUTPUT);       // Configure dataPin  as OUTPUT

pinMode(latchPin, OUTPUT);      // Configure latchPin as OUTPUT

pinMode(clockPin, OUTPUT);      // Configure clockPin as OUTPUT

}

void loop()

{

for (i = 0; i < 10; i++)

{

digitalWrite(latchPin, LOW);                                           // Pull latch LOW to start sending data

shiftOut(dataPin, clockPin, LSBFIRST,digit[i]);         // Send the data

digitalWrite(latchPin, HIGH);                                        // Pull latch HIGH to stop sending data

delay(1000);

}

}



Step 3:

3 - Directly from Arduino / Atmega 328 with direct port manipulation

Counts automatically from zero to nine and then repeats


Code

// Because Direct Port Manipulation uses pins 0 and 1, which are the RX and TX

// pins respectively, you have to disconnect these pins when uploading the code

// LED Segment allocation within byte = {DP ABCDEFG }

byte i = 0;

byte digit[10] = {B01111110, B00110000, B01101101, B01111001, B00110011, B01011011, B01011111, B01110000, B01111111, B01111011 };

void setup()

{

DDRD = B11111111; // set PORTD (digital 7~0) to outputs

}

void count()

{

for(i = 0; i <10; i++)

{

PORTD = digit[i];

delay(1000);

PORTD = 0;

}

}

void loop()

{

count();

}


Step 4:

4 - Multiplexed Via shift register from Arduino / Atmega 328 / Pushbutton counter

Push buttons increment and decrement a counter between zero and eight


Code

//  7-Segment LED counter, multiplexing using 74HC595 8-bit shift register, increment counter zero to eight to zero via push button switches

// Code mangled together from these sources - thanks fellas

//  http://www.sweeting.org/mark/blog/2011/11/27/arduino-74hc595-shift-register-and-a-7-segment-led-display

//  http://thecustomgeek.com/2011/06/29/multiplexing-for-a-7-year-old/

const int latchPin = 5;  // Pin connected to Pin 12 of 74HC595 (Latch)

const int dataPin  = 6;  // Pin connected to Pin 14 of 74HC595 (Data)

const int clockPin = 7;  // Pin connected to Pin 11 of 74HC595 (Clock)

int upPin = 12;      // pushbutton attached to pin 12

int downPin = 13;      // pushbutton attached to pin 12

int currUpState = 1;   // initialise currUpState as HIGH

int currDownState = 1;   // initialise currDownState as HIGH

int prevUpState = 0;

int prevDownState = 0;

int counter = 0;          // initialise counter as zero

const byte numbers[10] =  // Describe each digit in terms of display segments  0, 1, 2, 3, 4, 5, 6, 7, 8, 9

{

B11111100,

B01100000,

B11011010,

B11110010,

B01100110,

B10110110,

B10111110,

B11100000,

B11111110,

B11100110,

};

void setup()

{

pinMode(latchPin, OUTPUT);   // set SR pins to output

pinMode(clockPin, OUTPUT);

pinMode(dataPin, OUTPUT);

pinMode(upPin, INPUT);   // sets pin 12 as pushbutton INPUT

pinMode(downPin, INPUT);   // sets pin 13 as pushbutton INPUT

}

void loop()

{

currUpState = digitalRead(upPin);

if (prevUpState != currUpState)             // has the state changed from

{                                           // HIGH to LOW or vice versa

prevUpState = currUpState;

if (currUpState == HIGH)                  // If the button was pressed

counter++;          // increment the counter by one

//delay(1);

}

if(counter > 8)

counter-=1;

show(numbers[counter]); // display the current digit

currDownState = digitalRead(downPin);

if (prevDownState != currDownState)         // has the state changed from

{                                           // HIGH to LOW or vice versa

prevDownState = currDownState;

if (currDownState == HIGH)                // If the button was pressed

counter-=1;                              // decrement the counter by one

//delay(1);

}

if(counter < 0)

counter++;

show(numbers[counter]); // display the current digit

}

void show( byte number)

{

// Use a loop and a bitwise AND to move over each bit that makes up

// the seven segment display (from left to right, A => G), and check

// to see if it should be on or not

for(int j = 0; j <= 7; j++)

{

byte toWrite = number & (B10000000 >> j);

if(!toWrite) {

continue;

}  // If all bits are 0 then no point writing it to the shift register,so break out and move on to next segment.

shiftIt(toWrite); // Otherwise shift it into the register

}

}

void shiftIt (byte data)

{

digitalWrite(latchPin, LOW); // Set latchPin LOW while clocking these 8 bits in to the register

for (int k=0; k <= 7; k++)

{

digitalWrite(clockPin, LOW); // clockPin LOW prior to sending a bit

if ( data & (1 << k) )

{

digitalWrite(dataPin, HIGH); // turn “On”

}

else

{

digitalWrite(dataPin, LOW); // turn “Off”

}

digitalWrite(clockPin, HIGH); // and clock the bit in

}

digitalWrite(clockPin, LOW);  //stop shifting out data

digitalWrite(latchPin, HIGH); //set latchPin to high to lock and send data

}

Step 5:

5 - Multiplexed via shift register from Arduino / Atmega 328 / Potentiometer counter

    Potentiometer used to increment and decrement a counter between zero and eight


Code

//  7-Segment LED counter, multiplexing using 74HC595 8-bit shift register, increment counter zero to eight to zero via potentiometer
// Code mangled together from these sources - thanks fellas
//  http://www.sweeting.org/mark/blog/2011/11/27/arduino-74hc595-shift-register-and-a-7-segment-led-display
//  http://thecustomgeek.com/2011/06/29/multiplexing-for-a-7-year-old/

const int latchPin = 5;  // Pin connected to Pin 12 of 74HC595 (Latch)
const int dataPin  = 6;  // Pin connected to Pin 14 of 74HC595 (Data)
const int clockPin = 7;  // Pin connected to Pin 11 of 74HC595 (Clock)

int counter = 0;          // initialise counter as zero
int potReading =0;

const byte numbers[10] =  // Describe each digit in terms of display segments  0, 1, 2, 3, 4, 5, 6, 7, 8, 9

{
B11111100,
B01100000,
B11011010,
B11110010,
B01100110,
B10110110,
B10111110,
B11100000,
B11111110,
B11100110,
};
void setup()
{

pinMode(latchPin, OUTPUT);   // set SR pins to output
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);

}
void loop()

{
potReading = analogRead (A0);
potReading = map(potReading, 0, 1023, 0, 8);
{
if(potReading > 8)
potReading --;
show(numbers[potReading]);

}

{
if(potReading < 0)
potReading ++;
show(numbers[potReading]);

}
}

void show( byte number)
{
// Use a loop and a bitwise AND to move over each bit that makes up
// the seven segment display (from left to right, A => G), and check
// to see if it should be on or not
for(int j = 0; j <= 7; j++)
{
byte toWrite = number & (B10000000 >> j);

if(!toWrite) {
continue;
}  // If all bits are 0 then no point writing it to the shift register,so break out and move on to next segment.

shiftIt(toWrite); // Otherwise shift it into the register
}
}
void shiftIt (byte data)
{
digitalWrite(latchPin, LOW); // Set latchPin LOW while clocking these 8 bits in to the register

for (int k=0; k <= 7; k++)
{
digitalWrite(clockPin, LOW); // clockPin LOW prior to sending a bit

// Note that in our case, we need to set pinState to 0 (LOW) for
// “On” as the 74HC595 is sinking current when using a common
// anode display. If you want to use a common cathode display then
// switch this around.
if ( data & (1 << k) )
{
digitalWrite(dataPin, HIGH); // turn “On”
}
else
{
digitalWrite(dataPin, LOW); // turn “Off”
}
digitalWrite(clockPin, HIGH); // and clock the bit in
}
digitalWrite(clockPin, LOW);  //stop shifting out data
digitalWrite(latchPin, HIGH); //set latchPin to high to lock and send data
}