12 seven segment displays - Multiplexing

Guys, I am new in the Arduino world. I want to multiplex 12 digit seven segment displays with Arduino. I have connected them through a YouTube Tutorial. But they didn't give code. I have fully connected them the diagram is attached, please give the code. Thanks.

Arduino MEGA 2560 And the code is to have a writing section where we can write the message and show it to seven segment displays through the Arduino as soon as it's connected to power

Note- The image shows only 1 common pin connected, I have connected common pins as Disp 1- D9 Disp 2 - D10 Disp 3 - D11 Disp 4 - D12 Disp 5 - D13 Disp 6 - D14 Disp 7 - D15 Disp 8 - D16 Disp 9 D17 Disp 10 - D18 Disp 11 - D19 Disp 12 - D20

Thanks, AB

Mods, please do not remove me :heart:

You need to find your COM pin. It could be common ANODE or common CATHODE. Your COM pin is connected to D9.

arduino is not LED driver, but control unit, it give signals to executing circuit.
12 digits are too much, only 1 can light at a time, so brightness will be poor and you will see flickering.
maybe this tutor is helpful for you:

1 Like

Some considerations on this circuit:

  • Doing multiplexing in Software
    -> Not easy to get this flicker free
  • Resistors on common pin
    -> Makes programming a bit more complicated
  • No driving transistors in segment pins
    -> Need to limit current to prevent overloading of the pin

You can make it work but I suggest to use a chip like Ht16K33 for this.

Hi @adrish2012realiam

welcome to the arduino-forum

Well ... ---- .... this is not how this forum works.

The microcontroller-world is not super-standardised like USB-devices.

You have to take care of more details than just

"does the plug fit into the socket?"

Depending on several details about what exact type of 7-segment-displays you use the code has to be different.

Making 12 seven-segment digits light up will become much more easier in programming if you use ready to connect modules like these ones.
https://de.aliexpress.com/item/1005004795836176.html

Still there is a learning-curve for

  • learn how to install a library that contains the code for controlling the 7-segement-display
  • learn what the most basic structure of all arduino-code is
  • learn some very elemental basics about ohms law

As long as you ask specific questions about whatever related to your project it is very likely that you get helpful answers.

What will not gonna happen is that somebody writes the complete code for you.

1 Like

There is a lot of rubbish on video Tutorials, and only a few good ones. The circuit you posted is from the rubbish ones. You can tell that because they wouldn't post the code.

So you should look for a better one. However, you don't say if you have a common anode or common cathode 7 segment display so maybe you could say what you have, or post a link to where you bought it from. This matters because the circuit for driving the two types are different.

Also you have not posted a schematic, what you have posted is a physical layout diagram, which is a bit useless for trying to understand you circuit. These are the circuit diagrams for the two types of 7 Segment displays.

The thick lines are called busses and stand for a bundled of wires which you pull out individual wires you want to make contact with. This shows only four displays which is about the limit for the output pins on an Arduino, and still be visible.

And this is the circuit for a Common Cathode display. Note this uses NPN type transistors and not the PNP type used in the first circuit. You can tell this from the direction of the arrow on the emitter pin.

seven seg bus

As mentioned before you are better off with a driver chip that does the multiplexing for you. A sort of set and forget driver.

1 Like

Wondering if a shift register per digit could do the job, given external power?

There is no attached file with your post that shows a 12-digit 7-segment Display Unit.

Hi, @adrish2012realiam
Welcome to the forum.

Will the 2560 be doing anything else in the code other than driving the display?
@Rintin and @StefanL38 have some very relevant information with respect to what you want to accomplished.

Tom.. :smiley: :+1: :coffee: :australia:

Hi @adrish2012realiam,

I would like to add something to all the answers you already received.
I agree with them as they all seem right:

  • You might get to display your message with a minimum flicker.
  • You might have to deal with a hell of patch cables.
  • You'll have to do the refreshing multiplexing on your own, but is feasible.
  • But you'll end up spending great part of your processor time doing nothing but keeping your display updated and running. And that's a great reason to use any commercially available 7 segments display drivers.

You can use the FourBitLedDigitalTube library as an example to develop your solution if you insist with your approach, as it was written to deal with the display modules that relay on simple shift registers, that gives not much of advantage over the approach you are taking.

Good Luck!
Gaby.//

hopefully it's obvious that such displays are multiplexed to minimize the use of pins. Multiplexed means that one digit is active at a time and each digit is repeatedly turned on quickly enough displayed just as tv screens were refreshed 60 times/sec

here's code for displays driven with shift registers and an interrupt on a Multi-function board.

// drive 7-seg displays on MultiFuction boardj

#include <TimerOne.h>

#include "seg7disp.h"

// -------------------------------------
//  constants for multiplexed 7-segment display
#define Latch   4
#define Clock   7
#define Data    8
#define LED0   10
#define LED1   11

byte pins [] = { Latch, Clock, Data, LED0, LED1 };

//    a      d
//   f b    c e
//    g      g
//   e c    b f
//    d h    a
//
//   h g f e d c b a

const byte SEGMENT_MAP_DIGIT[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0X80, 0X90
};

const byte SEGMENT_MAP_DIGIT_F [] = {
    0xC0, 0xCF, 0xA4, 0x86, 0x8B, 0x92, 0x90, 0xC7, 0x80, 0x82
};

const byte DISP_MAP [] = { 1, 2, 4, 8 };
#define N_DISP  sizeof(DISP_MAP)

byte disp [N_DISP] = {SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF, SEGMENT_OFF};

int flag;

// -----------------------------------------------------------------------------
// shift 16-bits from data into the shift register
void output (
    uint16_t  data)
{
    digitalWrite (Latch, LOW);

    for (unsigned i = 0; i < 16; i++, data <<= 1)  {
        digitalWrite (Data, 0 != (data & 0x8000));

        digitalWrite (Clock, HIGH);
        digitalWrite (Clock, LOW);
    }

    digitalWrite (Latch, HIGH);
}

// -----------------------------------------------------------------------------
// repeatedly display one digit
//      lower 8-bits selects the digit
//      upper 8-bits species the segments
void isr (void)
{
    static byte idx = 0;

    uint16_t val = (disp [idx] << 8) + DISP_MAP [idx];
    output (val);

    if (N_DISP <= ++idx)
        idx = 0;
}

// -----------------------------------------------------------------------------
// update the value of each digit
void seg7segs (
    int  val,
    byte segs )
{
    for (int i = N_DISP-1; i >= 0; i--, val /= 2)
        disp [i] = val & 1 ? segs : SEGMENT_OFF;
}

// -----------------------------------------------------------------------------
// update the value of each digit
void seg7disp (
    int  valX10,
    int  flip )
{
    Serial.println (__func__);

    int i;
    if (flip)  {
        for (i = 0; i < (int)N_DISP; i++, valX10 /= 10)
            disp [i] = SEGMENT_MAP_DIGIT_F [valX10 % 10];

        // blank leading zeros
        i = N_DISP-1;
        while (SEGMENT_MAP_DIGIT [0] == disp [i])
            disp [i--] = SEGMENT_OFF;
    }
    else  {
        for (i = N_DISP-1; i >= 0; i--, valX10 /= 10)
            disp [i] = SEGMENT_MAP_DIGIT [valX10 % 10];
        disp [N_DISP-2] &= SEGMENT_DEC;       // decimal pt

        // blank leading zeros
        i = 0;
        while (SEGMENT_MAP_DIGIT [0] == disp [i])
            disp [i++] = SEGMENT_OFF;
    }
}

// -----------------------------------------------------------------------------
// update the value of each digit
void seg7off (void)
{
    Serial.println (__func__);
    for (int i = N_DISP-1; i >= 0; i--)
        disp [i] = SEGMENT_OFF;
}

void seg7on (void)
{
    Serial.println (__func__);
    for (int i = N_DISP-1; i >= 0; i--)
        disp [i] = 0;
}

// -----------------------------------------------------------------------------
void seg7init (void)
{
    Serial.println (__func__);
    for (unsigned i = 0; i < sizeof(pins); i++)  {
        digitalWrite (pins [i], HIGH);
        pinMode      (pins [i], OUTPUT);
    }

    Timer1.initialize(5000);
    Timer1.attachInterrupt (isr); // blinkLED to run every 0.15 seconds
}
  • higher level function, seg7disp(), translates the digits in an integer value into the index of SEGMENT_MAP_DIGIT [] for displaying that digit on a display

  • an interrupt service routine copies the segment display value along with another 8-bit value indicating which digit to turn on into a 16-bit value, calls output() to shift that 16-bit value into to shift registers and then increments the index indicating whichdigit to display

  • output() just clocks out the bits from the 16-bit value

  • an interrupt is used in the above to determine when to "refresh" a digit, but a timer could be used as well

  • you're circuits uses individual i/o pins to turn on/off each segment. you can use an array of pins #s and a loop that sets each pin using the segment value for each digit being displayed

  • first turn off the current display, turn on/off the segment pins, then turn on the display being refreshed

there should be resistors in series with each segment (not each display).

since those resistors will typically be smaller in value to make the segment brighter. look at the values used on the multifunction shield

write code to

  • get a timer running at 50 hz (20 msec)
  • sequentially turn on/off each digit using the timer
  • sequence thru an array of differnt value for each display
  • write a function that maps the value to segments

I don't see the advantage of using shift registers with multiplexing.

I would rather use 12 shift register and get rid of the multiplexing.

that also means having resistors on each segment.
a little bit of software can reduce a lot of hardware (and visa versa)

Hi @Rintin,

Sure, you can also get modules already assembled with a shift register per digit, I have 2, 3 and 4 preassembled units arround here, and to avoid the excess of pins in use they relay on the cascading pins, in which case you have to transmit the whole display contents even to change a single segment of a single digit... For each alternative we have pros and cons, and that takes us back to @kolaha input: using a dedicated driver chip.

Gaby.//

It is possible to multiplex the displays by have one segment active at a time, and repeatedly cycling through the segments. As an example, only segment A would be turned on, and every digit that needed that segment lit would be made active. Then only segment B is turned on, again making active only the digits that need that segment lit. This reduces the scan to seven or eight steps (depending on whether you are using the decimal point), instead of the 12 steps when multiplexed by digit, and would work with the single resister per digit.

1 Like

If you like the following design (Fig-1), I may provide some codes to test the display unit.


Figure-1:

Interesting! I will experiment it.

sure. but i think figuring out which digits need to be turned on for each segment will be more complicated and time consuming.

why don't you start with the conventional approach first

1 Like

That's why I suggested shift regs.

Here's the loop I used in my code to multiplex by segment:

       //This section turns the CA or CC pins on/off per the patterns of the characters
       //If the CURSEG bit of the DIGIT[n] segment pattern is 1, turn on the CACCpin[n]

    for(i = 0; i < DIGITS; ++i) {
      if (DIGIT[i] & CURSEG) digitalWrite(CACCpin[i], CACCON);
      else digitalWrite(CACCpin[i], CACCOFF);
    }

Not so difficult.

But in the case of 12 digits, each segment driver must supply current for up to 12 segments at a time if that segment is lit in all 12 digits, which no GPIO would be able to do. In fact, using normal by-digit multiplexing, the circuit in post #16 might be pretty dim too since the common cathodes would have to sink current for up to 8 segments at a time. That's why you normally see transistors used on the common cathodes.