Seven segment display multiplexing [duplicate]

I have written a code that displays a number into a seven segment display without manually setting the Arduino pins HIGH/LOW for each number. Now, my problem is how can I display a number larger than 9? This is my code and it works for only 1 digit number: (The seven segment display truth table is inverted because I'm using common anode 7seg)

``````#define SEG_A 2
#define SEG_B 3
#define SEG_C 4
#define SEG_D 5
#define SEG_E 6
#define SEG_F 7
#define SEG_G 8
#define DEC_P 12

#define SET1 9 // [!][!][x]
#define SET2 10// [!][x][!]
#define SET3 11// [x][!][!]

struct segmentmap {
uint8_t num;
const int segment[7];
};

const struct segmentmap segments[] = {
// n   A  B  C  D  E  F  G
{0, {0, 0, 0, 0, 0, 0, 1}},
{1, {1, 0, 0, 1, 1, 1, 1}},
{2, {0, 0, 1, 0, 0, 1, 0}},
{3, {0, 0, 0, 0, 1, 1, 0}},
{4, {1, 0, 0, 1, 1, 0, 0}},
{5, {0, 1, 0, 0, 1, 0, 0}},
{6, {0, 1, 0, 0, 0, 0, 0}},
{7, {0, 0, 0, 1, 1, 1, 1}},
{8, {0, 0, 0, 0, 0, 0, 0}},
{9, {0, 0, 0, 1, 1, 0, 0}}
};

void setup() {
Serial.begin(9600);
for (int x = 2; x <= 8; x++) {
pinMode(x, OUTPUT);
Serial.print("Segment pin: ");
Serial.print(x);
Serial.println(" is set to OUTPUT mode.");
digitalWrite(x, HIGH);
}
pinMode(DEC_P, OUTPUT);
pinMode(SET1, OUTPUT);
pinMode(SET2, OUTPUT);
pinMode(SET3, OUTPUT);
digitalWrite(SET1, 1);
}
int x = 0;
void loop() {
if (x > 9) {
x = 0;
}
updateDisplay(x);
delay(1000);
x++;
}

void updateDisplay(int input) {
for (int x = 0; x <= 9; x++) {
//Serial.println(segments[x].num);
if (segments[x].num == input) {
Serial.println(segments[x].segment[0]);
////////////Simplify this part//////////////
digitalWrite(SEG_A, segments[x].segment[0]);
digitalWrite(SEG_B, segments[x].segment[1]);
digitalWrite(SEG_C, segments[x].segment[2]);
digitalWrite(SEG_D, segments[x].segment[3]);
digitalWrite(SEG_E, segments[x].segment[4]);
digitalWrite(SEG_F, segments[x].segment[5]);
digitalWrite(SEG_G, segments[x].segment[6]);
////////////////////////////////////////////
//Multiplex here?//
}
}
}
``````

my problem is how can I display a number larger than 9?

your first problem can be solved by pulling down / up, depending on your led configuration, the right digit pins.

your second problem would be to write your code so that it is actually usable. think about a generic module where digit / segment pins can be user defined and the routine is called periodically update the segments / digits to display the content in a buffer.

It looks like you are using a 3 digit common anode display. If your code currently works, fixed to display something on digit 0, then you could get it working for all 3 digits by adding/updating the following:

``````// globals:
byte display_buffer[3] ;  // representation of the display which you can change in loop()
byte anode_map[3] = { 9, 10, 11 } ;  // anode pins

void loop() {
if (millis() % 5 == 0 ) updateDisplay();  // every 5mS - better to use a timer
if ( millis() % 1000 == 0) {  // every second
if (x > 9) {
x = 0;
}
display_buffer[0] = x ;  // just for testing
display_buffer[1] = (x + 11) % 10 ;
display_buffer[2] = (x + 12) % 10 ;
x++;
}
}

void updateDisplay() {
// called every x Ms preferably with a timer
// selects next item from display_buffer_ptr and displays it
//
static byte display_buffer_ptr ;
display_buffer_ptr ++ ;
if ( byte display_buffer_ptr > 2 ) display_buffer_ptr = 0 ;
int input = display_buffer[display_buffer_ptr] ;
for ( int i = 0 ; i < 3 ; i++ ) {
digitalWrite( anode_map[i], ( i == display_buffer_ptr ) ) ;  set current anode HIGH, rest LOW
}
// rest of your code to display the value of input

}
``````

This is not the most elegant solution but involves minimal changes to your code. It is more usual to use an array of byte for the mapping digits to segments. You may have to optimise the switching of the anodes to stop ghosting.