Converting 2-digit multiplexed 7-Segment LED signal to 128 x 64 OLED using Arduino NANO

Hi, I'm a newbie to Arduino and please bear with me as I'm new to this forum.

I want to modify an existing 2-digit 7-segment LED display into a 128 x 64 OLED display so instead of just showing numbers, the OLED will show messages (e.g. #10 = Text 10, #11 = Text 11, # 12 = Text 12, . . . . . , # 50 = Text 50). Both the Arduino Nano and OLED display are already working, I just need to know how to harness the data from the 7-segment LEDs. Hope you can share your expert advice and code if possible to make this project work.

Kindly refer to attached photo for further explanation and information about my project.

Thankfully Yours . . .

Just as 7seg LEDs use pre-defined patterns for displaying information, so can the OLED... but you can also display plain text with a print statement.

That will be a tough one. The 7 segment display will display any pattern you want using only the 7 segments. The OLED is a lot different and you communicate with it differently. You need to modify your function(s) that write to the LEDs to write to the OLED, it will not be a 1 for 1.

Thanks for your replies, highly appreciated.

I want to read what's from the 2-digit 7-segment LCD that is controlled by other device and input those signals to the Arduino Nano. . Those numbers range from 10 to around 50. Then the Nano will display corresponding messages/texts to the 192 x 64 OLED display. The 7-segment LCDs will be removed once the OLED is working.

Do you mean you want to display the same information on the OLED that some device that has seven segment LEDs is showing?

It looks like you are asking if the Arduino can listen to and decode the signals that whatever processor is in the device is supplying to its seven segment display.

Do you have a frequency meter or other way to measure the rate at which the multiplexing is taking place?

If the refresh rate is low enough, you can grab the signal by observation with no special tricks.

If it is too high for polling, you may be able to do it with interrupts. An interrupt from the digit selection signal could tell you when to grab the segment states.

Either polling or interrupts would use the digit selects (two inputs) to see which digit was being energize, and grab all eight segments drive signals.

Since there are eight and you'd like to be quick about it, I suggest to you "direct port manipulation", in which all eight digital signals can be grabbed up by 8 inputs on one port in very quick fashion. Then that one byte coukd be used to determine the digit displayed.

A table of ten patterns could be used to link a segments pattern with a digit.

If you look at the segment patterns, there may be a hack for figuring out a digit by process of elimination, but the gain in speed would not outweigh the loss of clarity and generality of a table base approach.

First step - determine the scanning frequency. You could do that with just the Arduino, not a difficult program. How much of a struggle to do just that would inform a decision to use polling or interrupts. Or, indeed, grab a towel and throw it in. :expressionless:

Imma bet it could be done without interrupts and if so that would be my preference.

HTH

a7

1 Like

I wonder which and how many of the segment signals would be needed to distinguish digits 0 to 9. That is, I wonder if any of them are not needed...

Segment e would be needed to distinguish between 8 and 9. Similarly, b would be needed to distinguish between 6 and 8, and g to distinguish 0 from 8

An exercise for the reader. :expressionless:

Don't work too hard on it until you know whether the '6' and '9' use the extra tail segment.

The table you show has them both, I think they should be used, but I've seen all four combinations of using and not using them.

a7

Hi, @CoJammer
Welcome to the forum.

What figures is the display showing, mmHg, %RH, RPM, VOLTS, AMPS?

What is the controller that the 7seg display is connected to?
What is its application?

Why is it needed on a small OLED display?

Thanks.. Tom.. :grinning: :+1: :coffee: :australia:

Well, I thought it was an interesting little problem and could not resist attempting to figure out the answer!

Here is the code I tried:

const byte segPattern[10] = {
  //abcdefg
  0b1111110, //0
  0b0110000, //1
  0b1101101, //2
  0b1111001, //3
  0b0110011, //4
  0b1011011, //5
  0b0011111, //6 with a "tail"
  0b1110000, //7
  0b1111111, //8
  0b1110011  //9 with a "tail"
};

void setup() {

  Serial.begin(115200);

  //test every possible combination of 7 segments
  for (byte segCombo = 0b0000000; segCombo <= 0b1111111; segCombo++) {

    bool duplicateFound = false;
    //test each decimal digit
    for (byte digit = 0; digit <= 9; digit++) {
      //check the resulting pattern has not already been seen
      for (byte testDigit = 0; testDigit < digit; testDigit++) {
        if ((segPattern[testDigit] & segCombo) == (segPattern[digit] & segCombo)) duplicateFound = true;
      }
    }

    if (!duplicateFound) {
      Serial.print("Segment combination ");
      for (byte s = 0; s <= 7; s++) {
        if (bitRead(segCombo, s) == 1) Serial.print((char) ('a' + s));
      }
      Serial.println(" could be used");
    }

  }
}

void loop() {
}

Results (for both 6 and 9 with tail segments):

Segment combination abcfg could be used
Segment combination abcdfg could be used
Segment combination abcefg could be used
Segment combination abcdefg could be used

According to this, only 5 segments are important: a, b, c, f, g

But this is not correct! If segments d, e are ignored, then digits 8 and 9 would be indistinguishable:

  //abcdefg
  0b111??10, //0
  0b011??00, //1
  0b110??01, //2
  0b111??01, //3
  0b011??11, //4
  0b101??11, //5
  0b001??11, //6
  0b111??00, //7
  0b111??11, //8
  0b111??11  //9

What did I get wrong?

I think you have correctly coded an algorithm that should work.

Your '6' and '9' binary constants are without tails.

That would solve the '8' / '9' issue?

I cannot run the code just now.

I'm remembering that you couldn't resist this…

a7

You've printed the combo wrong.

Segment combination 1001111
abcdg could be used

Should read

adefg could be used.

    if (!duplicateFound) {
//      Serial.print("Segment combination ");
//      Serial.print(segCombo, 2);
//      Serial.println();
    
      byte tempCombo = segCombo;
      for (byte s = 0; s <= 6; s++, tempCombo <<= 1) {
        if (tempCombo & 0x40) Serial.print((char) ('a' + s));
      }
      Serial.println(" could be used");
    }

Yields this:

adefg could be used
acdefg could be used
abefg could be used
abdefg could be used
abcefg could be used
abcdfg could be used
abcdeg could be used
abcdefg could be used

Check that while I do something else.

a7

1 Like

I think it is an LED, not an LCD.
Although I have done it with an LCD in an article that was published in 1987, it is quite complex.

An LED is much easer. However the problem is that what @CoJammer has picked is only one way of creating a multiplexed LED display. So what he must do is to first decide how his specific LED driver works.

I also did this when I wrote about interfacing a DVM chip to the computer, in 1985. The chip I used was designed to output the multiplex signals to drive an LED display, so in effect was the same problem. The only difference being is that you have to tap off the voltages from the hardware LED display. The trouble with that is that is they are not all 5V signals, and you might need a comparator to get a 5V digital signal from some points.

It is a project that is perfectly possible for an Arduino, because the computer I was using was much slower than an Arduino Uno or Nano. You won't even have to use interrupts.

However, unless you have an oscilloscope and know how to use it you can't even begin to tackle this project.

My bad, I changed the patterns during testing to cover all 4 tail/tail-less combinations and forgot to change the comments.

The results for the 4 tests were slightly different, but abcfg was incorrectly reported as useable in each test.

Ah, dang! Thanks @alto777 :slight_smile:

In my patterns, segment 'a' is bit 6, not bit 0.

So I think this would also fix it:

if (bitRead(segCombo, s) == 1) Serial.print((char) ('g' - s));

I'll re-test, including with/without tails later.

You only need to run the loop over 7 elements. But it's a hidden flaw as it harmlesssly never finds a 1 where it would be bad to do.

And that expression prints the letters sdrawkcab, which while no less informative is the kind thing that annoys me, and probably took longer to get right than the other stuff. :expressionless:

Of course you can "begin to tackle" this project without either an oscilloscope or the knowledge to use it.

@CoJammer has already done. I expect she could continue to make progress with code experiments, and indeed might well succeed without anything else.

If she had a frequency meter, some progress might be made faster. If it had a duty cycle readout, it would be that much better.

If she had a $15 logic analyser (and knew how to use it :wink: ) some more progress might be made faster.

Of course to the oscilloscope would be where one would turn, if one had one and knew how to use it.

Or maybe not. I've done things that looking back were absolute insanity to "tackle" with the tools (and knowledge) I brought to the task. As, I suspect, have many of us.

I have two oscilloscopes. One displays an analog chaos generator as its retirement gig, the other gathers dust.

I have three logic analysers. The expensive one is somewhere in the lab, the cheap ones are on permananet temporary (!) hardware test setups which I mostly use to look at noob code seen on the fora that I take an interest in.

TBH they too gather dust these days, given the existence of the wokwi simulator, which has largely supplanted actually wiring up real stuff to peek at code and stuff.

a7

1 Like

Are the LED segments driven by hardware or software? If software, can you edit it?

It seems a 128-byte lookup table would account for all possibilities.

I guess that's why you get the big bucks!

If there's room, that would be the fastest total solution to all 0..9 un-encoding.

With a bit of work the table would fit in 64 bytes as only a 4 bit binary number must be looked up.

This

Bit Array Library

handles groups of bits, and would make doing that easy.

I read through the code some time ago but do not use the library myself. Most of the time I have plenty of memory of all kinds to spare.

a7

Bucks? We get bucks?

Anyway, everytime I get bogged down in trying to code some complicated logic, I try to remember the advice I got from a TI coder years ago. "Just use a lookup table. Your mother never needs to know you used a lookup table."

1 Like

Good spot, thanks.

Huh?

Updated code:

const byte segPattern[10] = {
  //abcdefg
  0b1111110, //0
  0b0110000, //1
  0b1101101, //2
  0b1111001, //3
  0b0110011, //4
  0b1011011, //5
  0b1011111, //6 with a "tail"
  0b1110000, //7
  0b1111111, //8
  0b1111011  //9 with a "tail"
};

void setup() {

  Serial.begin(115200);

  //test every possible combination of 7 segments
  for (byte segCombo = 0b0000000; segCombo <= 0b1111111; segCombo++) {

    bool duplicateFound = false;
    //test each decimal digit
    for (byte digit = 0; digit <= 9; digit++) {
      //check the resulting pattern has not already been seen
      for (byte testDigit = 0; testDigit < digit; testDigit++) {
        if ((segPattern[testDigit] & segCombo) == (segPattern[digit] & segCombo)) duplicateFound = true;
      }
    }

    if (!duplicateFound) {
      Serial.print("Segment combination ");
      for (char s = 6; s >= 0; s--) {
        if (bitRead(segCombo, s) == 1) Serial.print((char) ('g' - s));
      }
      Serial.println(" could be used");
    }

  }
}

void loop() {
}

Results for 6 and 9 both having "tails":

Segment combination abefg could be used
Segment combination abdefg could be used
Segment combination abcefg could be used
Segment combination abcdefg could be used

Results for 6 with no tail and 9 with tail:

Segment combination abefg could be used
Segment combination abdefg could be used
Segment combination abcefg could be used
Segment combination abcdefg could be used

Results for 6 with tail and 9 with no tail:

Segment combination abefg could be used
Segment combination abdefg could be used
Segment combination abcefg could be used
Segment combination abcdeg could be used
Segment combination abcdefg could be used

Results for 6 with no tail and 9 with no tail:

Segment combination adefg could be used
Segment combination acdefg could be used
Segment combination abefg could be used
Segment combination abdefg could be used
Segment combination abcefg could be used
Segment combination abcdfg could be used
Segment combination abcdeg could be used
Segment combination abcdefg could be used

So the segment combination abefg seems to be enough to distinguish digits 0 to 9 regardless of the tails/no tails for 6 and 9.

  //abefg
  0b11110, //0
  0b01000, //1
  0b11101, //2
  0b11001, //3
  0b01011, //4
  0b10011, //5
  0b10111, //6 with a tail
  0b00111, //6 with no tail
  0b11000, //7
  0b11111, //8
  0b11011  //9 with a tail or no tail (tail is seg d)

Hopefully I got it right this time!

@CoJammer I hope this is useful for you!