I would like to know how to simplify my seven segment display driver program

I have this several hundred lines long program which I would like to simplify without using SevSeg.h. I made this program to drive up to 6 such digits with multiplexing by the digit (one digit turns on, then another one, and so on.)
Here is the code:

// segment cathodes
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;

// digit anodes (driven by PNP transistors)
int one = 9;
int ten = 10;
int hund = 11;
int thou = 12;
int tetho = 13;
int hutho = A1;

  // <ignore these names>
int zobraz = 0;
unsigned long num = 0;
unsigned int cislo = 0;
unsigned int cislodesat = 0;
unsigned int cislodesat2 = 0;
unsigned int cislosto = 0;
unsigned int cislosto2 = 0;
unsigned int cislotisic = 0;
unsigned int cislotisic2 = 0;
unsigned int cislodesattisic = 0;
unsigned int cislodesattisic2 = 0;
unsigned int cislostotisic = 0;
unsigned int zobrazCislo = 0;
unsigned int intermid = 0;
unsigned int intermid2 = 0;
unsigned int intermid3 = 0;
unsigned int intermid4 = 0;
unsigned int intermid5 = 0;
unsigned long present = 0;
unsigned long past = 0;
unsigned long present2 = 0;
unsigned long past2 = 0;
  // </ignore these names>


void setup() {

  pinMode(a, OUTPUT);
  pinMode(b, OUTPUT);
  pinMode(c, OUTPUT);
  pinMode(d, OUTPUT);
  pinMode(e, OUTPUT);
  pinMode(f, OUTPUT);
  pinMode(g, OUTPUT);

  // digit anodes are driven by PNP transistors
  pinMode(one, OUTPUT);
  pinMode(ten, OUTPUT);
  pinMode(hund, OUTPUT);
  pinMode(thou, OUTPUT);
  pinMode(tetho, OUTPUT);
  pinMode(hutho, OUTPUT);

  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);

}

void loop() {
  present2 = micros();
  present = millis();

  if (num > 9) {
    cislodesat = num / 10;
    cislosto = num / 100;
    cislotisic = num / 1000;
    cislodesattisic = num / 10000;
    cislostotisic = num / 100000;
    intermid = cislodesat * 10;
    intermid2 = cislosto * 10;
    intermid3 = cislotisic * 10;
    intermid4 = cislodesattisic * 10;
    intermid5 = cislostotisic * 10;
  }

  if (num <= 9) {
    cislodesat = 0;
    cislodesat2 = 0;
    cislosto = 0;
    cislosto2 = 0;
    cislotisic = 0;
    cislotisic2 = 0;
    cislodesattisic = 0;
    cislodesattisic2 = 0;
    cislostotisic = 0;
    cislo = num;
  }

  if (num > 9 && num <= 99) {
    cislodesat2 = cislodesat - intermid2;
    cislosto2 = cislosto - intermid3;
    cislotisic2 = cislotisic - intermid4;
    cislodesattisic2 = cislodesattisic - intermid5;
    cislo = num - intermid;
  }

  if (num > 99 && num <= 999) {
    cislodesat2 = cislodesat - intermid2;
    cislosto2 = cislosto - intermid3;
    cislotisic2 = cislotisic - intermid4;
    cislodesattisic2 = cislodesattisic - intermid5;
    cislo = num - intermid;
  }

  if (num >= 999) {
    cislodesat2 = cislodesat - intermid2;
    cislosto2 = cislosto - intermid3;
    cislotisic2 = cislotisic - intermid4;
    cislodesattisic2 = cislodesattisic - intermid5;
    cislo = num - intermid;
  }

  if (present2 - past2 >= 6600) {
    nezobraz();
    zobraz = zobraz + 1;

    switch (zobraz) {

      case 0:
        zobrazCislo = cislostotisic;
        zsts();
        break;

      case 1:
        zobrazCislo = cislodesattisic2;
        zdts();
        break;

      case 2:
        zobrazCislo = cislotisic2;
        ztis();
        break;

      case 3:
        zobrazCislo = cislosto2;
        zsto();
        break;

      case 4:
        zobrazCislo = cislodesat2;
        zdst();
        break;

      case 5:
        zobrazCislo = cislo;
        zjdn();
        break;

    }

    past2 = present2;

    if (zobraz >= 6) {
      zobraz = -1;
    }

  }


  switch (zobrazCislo) {

    case 0:
      z0();
      break;

    case 1:
      z1();
      break;

    case 2:
      z2();
      break;

    case 3:
      z3();
      break;

    case 4:
      z4();
      break;

    case 5:
      z5();
      break;

    case 6:
      z6();
      break;

    case 7:
      z7();
      break;

    case 8:
      z8();
      break;

    case 9:
      z9();
      break;

  }

}

void z1() {
  digitalWrite(a, HIGH);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void z2() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, HIGH);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, HIGH);
  digitalWrite(g, LOW);
}

void z3() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, LOW);
}

void z4() {
  digitalWrite(a, HIGH);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void z5() {
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void z6() {
  digitalWrite(a, LOW);
  digitalWrite(b, HIGH);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void z7() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
}

void z8() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void z9() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, HIGH);
  digitalWrite(f, LOW);
  digitalWrite(g, LOW);
}

void z0() {
  digitalWrite(a, LOW);
  digitalWrite(b, LOW);
  digitalWrite(c, LOW);
  digitalWrite(d, LOW);
  digitalWrite(e, LOW);
  digitalWrite(f, LOW);
  digitalWrite(g, HIGH);
}

void zjdn() {
  digitalWrite(one, LOW);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);
}

void zdst() {
  digitalWrite(one, HIGH);
  digitalWrite(ten, LOW);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);
}

void zsto() {
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, LOW);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);
}

void ztis() {
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, LOW);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);
}

void zdts() {
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, LOW);
  digitalWrite(hutho, HIGH);
}

void zsts() {
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, LOW);
}

void nezobraz() {
  digitalWrite(a, HIGH);
  digitalWrite(b, HIGH);
  digitalWrite(c, HIGH);
  digitalWrite(d, HIGH);
  digitalWrite(e, HIGH);
  digitalWrite(f, HIGH);
  digitalWrite(g, HIGH);
  digitalWrite(one, HIGH);
  digitalWrite(ten, HIGH);
  digitalWrite(hund, HIGH);
  digitalWrite(thou, HIGH);
  digitalWrite(tetho, HIGH);
  digitalWrite(hutho, HIGH);
}

If you get confused anywhere, message me, I will try my best to explain whatever part of this program confused you.

In principle, you use an array of 10 single bytes to represent the segments which should be lit for each digit 0 to 9.
You use an array of 6 integers to represent what should appear in the display.
You set a hardware timer at about *250Hz to handle the multiplexing. Each time its ISR is called, you display the next digit in the cycle from the display array by setting the segments for the selected digit postion.
When new contents should appear in the display, simply fill the 6 integer display array with the new data.

Done correctly, it should be less than 100 lines of code and that without using a display library.

*250 Hz is chosen for low flicker and low switching losses.

1 Like

int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;

// digit anodes (driven by PNP transistors)
int one = 9;
int ten = 10;
int hund = 11;
int thou = 12;
int tetho = 13;
int hutho = A1;

unsigned long num = 0;
int zobraz = 0;
unsigned long present2 = 0;
unsigned long past2 = 0;

const int segments[10][7] = {
{LOW, LOW, LOW, LOW, LOW, LOW, HIGH}, // 0
{HIGH, LOW, LOW, HIGH, HIGH, HIGH, HIGH}, // 1
{LOW, LOW, HIGH, LOW, LOW, HIGH, LOW}, // 2
{LOW, LOW, LOW, LOW, HIGH, HIGH, LOW}, // 3
{HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW}, // 4
{LOW, HIGH, LOW, LOW, HIGH, LOW, LOW}, // 5
{LOW, HIGH, LOW, LOW, LOW, LOW, LOW}, // 6
{LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH}, // 7
{LOW, LOW, LOW, LOW, LOW, LOW, LOW}, // 8
{LOW, LOW, LOW, LOW, HIGH, LOW, LOW} // 9
};

const int digitPins[6] = {one, ten, hund, thou, tetho, hutho};

void setup() {
for (int pin : {a, b, c, d, e, f, g}) {
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}

for (int pin : digitPins) {
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
}

void loop() {
present2 = micros();

if (present2 - past2 >= 6600) {
turnOffAllDigits();
zobraz = (zobraz + 1) % 6;
displayDigit(zobraz, getDigitValue(zobraz));
past2 = present2;
}
}

int getDigitValue(int position) {
unsigned long divisor = pow(10, position);
return (num / divisor) % 10;
}

void displayDigit(int position, int value) {
for (int i = 0; i < 7; i++) {
digitalWrite(a + i, segments[value][i]);
}
digitalWrite(digitPins[position], LOW);
}

void turnOffAllDigits() {
for (int pin : digitPins) {
digitalWrite(pin, HIGH);
}
for (int i = 0; i < 7; i++) {
digitalWrite(a + i, HIGH);
}
}

The refactored code simplifies your logic and reduces redundancy by using arrays to map segment states for digits and handling digit display dynamically. Let me know that works.

Please format code with menu Tools/Auto Format and post in code tags.

int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;

// digit anodes (driven by PNP transistors)
int one = 9;
int ten = 10;
int hund = 11;
int thou = 12;
int tetho = 13;
int hutho = A1;

unsigned long num = 0;
int zobraz = 0;
unsigned long present2 = 0;
unsigned long past2 = 0;

const int segments[10][7] = {
{ LOW, LOW, LOW, LOW, LOW, LOW, HIGH }, // 0
{ HIGH, LOW, LOW, HIGH, HIGH, HIGH, HIGH }, // 1
{ LOW, LOW, HIGH, LOW, LOW, HIGH, LOW }, // 2
{ LOW, LOW, LOW, LOW, HIGH, HIGH, LOW }, // 3
{ HIGH, LOW, LOW, HIGH, HIGH, LOW, LOW }, // 4
{ LOW, HIGH, LOW, LOW, HIGH, LOW, LOW }, // 5
{ LOW, HIGH, LOW, LOW, LOW, LOW, LOW }, // 6
{ LOW, LOW, LOW, HIGH, HIGH, HIGH, HIGH }, // 7
{ LOW, LOW, LOW, LOW, LOW, LOW, LOW }, // 8
{ LOW, LOW, LOW, LOW, HIGH, LOW, LOW } // 9
};

const int digitPins[6] = { one, ten, hund, thou, tetho, hutho };

void setup() {
for (int pin : { a, b, c, d, e, f, g }) {
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}

for (int pin : digitPins) {
pinMode(pin, OUTPUT);
digitalWrite(pin, HIGH);
}
}

void loop() {
present2 = micros();

if (present2 - past2 >= 6600) {
turnOffAllDigits();
zobraz = (zobraz + 1) % 6;
displayDigit(zobraz, getDigitValue(zobraz));
past2 = present2;
}
}

int getDigitValue(int position) {
unsigned long divisor = pow(10, position);
return (num / divisor) % 10;
}

void displayDigit(int position, int value) {
for (int i = 0; i < 7; i++) {
digitalWrite(a + i, segments[value][i]);
}
digitalWrite(digitPins[position], LOW);
}

void turnOffAllDigits() {
for (int pin : digitPins) {
digitalWrite(pin, HIGH);
}
for (int i = 0; i < 7; i++) {
digitalWrite(a + i, HIGH);
}
}

Please read the pinned post re How to get the most from the forum. Step 1 is to go to the Tools menu in the IDE and select Auto Format. Then do the next steps.

I never learned how to do arrays, but let's hope it works. I'll try it tomorrow.

1 Like

See if this code helps.

I know that at first glance it may seem complex, but I tried to comment on several lines to make the code easier to understand.

It is simulated in:

Since there is no transistor in the simulator, I used !LOW and !HIGH (inverter) in the line of the digit pins.

// segment cathodes
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
// digit anodes (driven by PNP transistors)
int one = 9;
int ten = 10;
int hund = 11;
int thou = 12;
int tetho = 13;
int hutho = A1;
// <ignore these names>
unsigned long num = 0;
unsigned int cislo = 0;
unsigned int cislodesat = 0;
unsigned int cislosto = 0;
unsigned int cislotisic = 0;
unsigned int cislodesattisic = 0;
unsigned int cislostotisic = 0;
// </ignore these names>
unsigned long myTime = 0;
int position[6];                                  // converted value
int digit_pin[] {9, 10, 11, 12, 13, 14};          // Digit pins
//--------------------------------------------------------------
void setup() {
  for (int x = 2; x < 15; x++) {                    // Define mode pins as OUTUT
    pinMode(x, OUTPUT);
  }
  // digit anodes are driven by PNP transistors   // HIGH all Pins
  for (int y = 2; y < 15; y++) {
    digitalWrite(y, HIGH);
  }
}ten hundred thousand million
//-------------------------------------------------------------
void loop() {
  if (millis() - myTime >= 400) {               // Time to increment num
    num++;                                      // Increment num
    myTime = millis();                          // Refresh myTime
    cislo = num % 10;                           // Module num  calculet unit
    converter(0, cislo );                       // Call convert to convert 7 seg pins
    cislodesat = (num / 10) % 10;               // module num/10 ten
    converter(1, cislodesat );                  // Call convert to convert 7 seg pins
    cislosto = (num / 100) % 10;                // module num/10 hundred
    converter(2, cislosto );                    // Call convert to convert 7 seg pins
    cislotisic = (num / 1000) % 10;             // module num/10 thousand
    converter(3, cislotisic );                  // Call convert to convert 7 seg pins
    cislodesattisic = (num / 10000) % 10;       // module num/10 million
    converter(4, cislodesattisic );             // Call convert to convert 7 seg pins
    cislostotisic = (num / 100000) % 10;        // module num/10 Billion
    converter(5, cislostotisic );               // Call convert to convert 7 seg pins
  }
  for (int k = 0; k < 6; k++) {                 // Turn on/off 7seg pins by convert
    int p = 2;
    for (int t = 6; t >= 0; t--) {             // turn on/off pins (2 to 8)
      digitalWrite(p, bitRead(position[k], t));
      p++;                                       // increment pin number
    }
    digitalWrite(digit_pin[k], LOW);           // define digit pin turn LOW
    for (int m = 9; m < 15; m++) {
      digitalWrite(m, HIGH);                    // Turn all pin HIGH
    }
  }
}
//------------------------------------------------------------------
void converter(int j, int newNum ) {
  // Serial.print(newNum); Serial.print(" ");
  if (newNum == 0) position[j] = 0x01;     // 00 = 01
  if (newNum == 1) position[j] = 0x4F;     // 01 = 4F
  if (newNum == 2) position[j] = 0x12;     // 02 = 12
  if (newNum == 3) position[j] = 0x06;     // 03 = 06
  if (newNum == 4) position[j] = 0x4C;     // 04 = 4C
  if (newNum == 5) position[j] = 0x24;     // 05 = 24
  if (newNum == 6) position[j] = 0x20;     // 06 = 20
  if (newNum == 7) position[j] = 0x0F;     // 07 = 0F
  if (newNum == 8) position[j] = 0x00;     // 08 = 00
  if (newNum == 9) position[j] = 0x04;     // 09 = 04
  //  Serial.print(position[j],HEX); Serial.println(" ");
}

Wokwi has NOT gates.

The solution could be even simpler since the original code appears simply to display six zeros.

It displays six zeores because num is zero. Set num to 123456 and that will show on the display.

Try this code.
It clear the leading zeros from the number.
Note: I changed the sixth digit pin from A1 to A0.
"6xSegments Copy - Wokwi ESP32, STM32, Arduino Simulator

// segment cathodes
int a = 2;
int b = 3;
int c = 4;
int d = 5;
int e = 6;
int f = 7;
int g = 8;
// digit anodes (driven by PNP transistors)
int one = 9;
int ten = 10;
int hund = 11;
int thou = 12;
int tetho = 13;
int hutho = A1;
// <ignore these names>
unsigned long num = 0;
unsigned int cislo = 0;
unsigned int cislodesat = 0;
unsigned int cislosto = 0;
unsigned int cislotisic = 0;
unsigned int cislodesattisic = 0;
unsigned int cislostotisic = 0;
// </ignore these names>
unsigned long myTime = 0;
int position[6];                                  // converted value
int digit_pin[] {9, 10, 11, 12, 13, 14};        // Digit pins
int blank =  0;
//--------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  for (int x = 2; x < 15; x++) {                    // Define mode pins as OUTUT
    pinMode(x, OUTPUT);
  }
  // digit anodes are driven by PNP transistors   // HIGH all Pins
  for (int y = 2; y < 15; y++) {
    digitalWrite(y, HIGH);
  }
}
//-------------------------------------------------------------
void loop() {
  if (millis() - myTime >= 400) {               // Time to increment num
    num++;                                      // Increment num
    //num = 599999;
    String myString = String(num);
    blank = myString.length();
    myTime = millis();                          // Refresh myTime
    cislo = num % 10;                           // Module num  calculet unit
    converter(0, cislo );                       // Call convert to convert 7 seg pins
    cislodesat = (num / 10) % 10;               // module num/10 ten
    converter(1, cislodesat );                  // Call convert to convert 7 seg pins
    cislosto = (num / 100) % 10;                // module num/10 hundred
    converter(2, cislosto );                    // Call convert to convert 7 seg pins
    cislotisic = (num / 1000) % 10;             // module num/10 thousand
    converter(3, cislotisic );                  // Call convert to convert 7 seg pins
    cislodesattisic = (num / 10000) % 10;       // module num/10 million
    converter(4, cislodesattisic );             // Call convert to convert 7 seg pins
    cislostotisic = (num / 100000) % 10;        // module num/10 Billion
    converter(5, cislostotisic );               // Call convert to convert 7 seg pins
  }
  for (int k = 0; k < blank; k++) {                 // Turn on/off 7seg pins by convert
    int p = 2;
    for (int t = 6; t >= 0; t--) {             // turn on/off pins (2 to 8)
      digitalWrite(p, bitRead(position[k], t));
      p++;                                       // increment pin number
    }
    digitalWrite(digit_pin[k], LOW);           // define digit pin turn LOW
    for (int m = 9; m < 15; m++) {
      digitalWrite(m, HIGH);                    // Turn all pin HIGH
    }
  }
}
//------------------------------------------------------------------
void converter(int j, int newNum ) {
  // Serial.print(newNum); Serial.print(" ");
  if (newNum == 0) position[j] = 0x01;     // 00 = 01
  if (newNum == 1) position[j] = 0x4F;     // 01 = 4F
  if (newNum == 2) position[j] = 0x12;     // 02 = 12
  if (newNum == 3) position[j] = 0x06;     // 03 = 06
  if (newNum == 4) position[j] = 0x4C;     // 04 = 4C
  if (newNum == 5) position[j] = 0x24;     // 05 = 24
  if (newNum == 6) position[j] = 0x20;     // 06 = 20
  if (newNum == 7) position[j] = 0x0F;     // 07 = 0F
  if (newNum == 8) position[j] = 0x00;     // 08 = 00
  if (newNum == 9) position[j] = 0x04;     // 09 = 04
  //  Serial.print(position[j],HEX); Serial.println(" ");
}

That is some good and working code you wrote there.

It may work but I think "good" is too generous. It has potential to be good.

It may work but I think "good" is too generous. It has potential to be good.

Tell that to my original code which gets the job done despite being uglier than what most people are used to

Fine.

By my prevoius reply I meant that your code is most likely better than mine

Hi, @ardurider50hz

Hope you enjoyed the exercise, is there a project you are aiming at, or was this just a learning curve?
The reason I ask is if you also want your code to do any other activity then the display will flicker while your code does other things.

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

I made this code as a stitch in for basically anything that doesn't require more than 4 milliseconds to do. I wrote a thermometer program and a speedometer program, and I wrote this program as a foundation for any future 7 segment display projects that don't require more than 6 digits. I can easily expand the code to as many digits as I can fit into the GPIO.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.