ATMega328/Arduino Uno/Nano/Pro Micro driving a 4 digit, 7 segment led display

Demonstration of how to use an ATMega328 or Arduino Uno/Nano/Pro Micro etc to drive a 4 digit, 7 segment led display with colon etc.

Achieved with simply 5 ordinary npn transistors, 8 series resistors and 13 Arduino outputs.

This circuit uses most of the outputs of an ATmega328/Nano/Pro Micro Arduino, but if the chip is doing little or nothing else, why not use it to drive a display directly rather than use shift registers (e.g. 75hc595, not a great choice because of limited current, or tip6c595, a better option) or an led driver chip such as max7219 (best option if you need to use the Arduino outputs for other functions).

This particular display is common anode, but common-cathode is also achievable with some minor changes to the circuit & sketch.

If no colon or other segments are present/needed on the display, transistor T5 can be omitted. Alternatively, 6 more separate leds could be added as shown in the schematic.

Schematic shows 150R resistors, calculated to allow maximum current/brightness without overloading the Arduino’s outputs, but I used 330R and brightness was still excellent (although maybe not great in bright sunlight).



const byte segmentPin[8] = {2, 3, 4, 5, 8, 9, 10, 11};
const byte digitPin[5] = {6, 7, 14, 13, 12};

const byte digitPattern[10] = {
  B11000000 };

unsigned long updateDisplay;
byte currAnode;
byte digit[5];

void setup() {
  for (byte i=0; i<8; i++) {
    pinMode(segmentPin[i], OUTPUT);
  for (byte i=0; i<5; i++) {
    pinMode(digitPin[i], OUTPUT);

void loop() {
  unsigned long now = millis();
  int n = now / 100;
  digit[0] = digitPattern[n % 10];
  digit[1] = digitPattern[(n / 10) % 10];
  digit[2] = digitPattern[(n / 100) % 10];
  digit[3] = digitPattern[(n / 1000) % 10];
  digit[4] = B11111110 | ((n / 5) & 1);
  if (now - updateDisplay >= 3) {
    updateDisplay = now;
    digitalWrite(digitPin[currAnode], LOW);
    if (currAnode++ >= 4) currAnode = 0;
    for (byte i=0; i<8; i++) {
      digitalWrite(segmentPin[i], bitRead(digit[currAnode], i));
    digitalWrite(digitPin[currAnode], HIGH);

Apologies if this is all a bit brief, if you ask I will be happy to explain any particular points further.




Got a schematic to go with that?

CrossRoads: Got a schematic to go with that?

Sorry Bob, still editing. Schematic is there now.

The BC337 should really be PNP transistors, with gate resistors from the arduino.

CrossRoads: The BC337 should really be PNP transistors, with gate resistors from the arduino.

That would work too, and would be preferable if the display's segments have a high forward voltage. For example, blue segments might have a forward voltage of 3.5V compared to only 1.9V that those red ones do.

I went with npn in emitter-follower configuration, which needs no base resistor. The transistor drops 0.7V (vs 0.3V for a pnp), but that's not a problem in this case.