Dim flickery displays

Hello,

I am attempting to multiplex 6, 12 volt, Common Anode 7 segment displays

I am using a shift register and a uln2803 to control the segments and a shift register and transistors to control the anodes.

I am getting a tremendous amount of flicker and the displays are dim.

Here is the code.

int segData = 8;
int segClock = 7;
int segLatch = 6;

int anData = 9;
int anClock = 10;
int anLatch = 11;


byte anodePins[6] = {0,0,0,0,0,0};

byte segmentPins[8] = {0,0,0,0,0,0,0,0};

byte counter[6] = {0,0,0,0,0,0};

int rolloverAssign[6] = {0,1,0,0,0,0};

int count = 0;

int rollover = 0;

int hold = 3;

int anodePosition = 0;
int segmentPosition = 5;

byte numbers[10][8] = {
                          {0,1,1,1,1,1,1,0},//  0 
                          {0,0,0,0,1,1,0,0},//  1
                          {1,0,1,1,0,1,1,0},//  2
                          {1,0,0,1,1,1,1,0},//  3
                          {1,1,0,0,1,1,0,0},//  4
                          {1,1,0,1,1,0,1,0},//  5
                          {1,1,1,1,1,0,0,0},//  6
                          {0,0,0,0,1,1,1,0},//  7
                          {1,1,1,1,1,1,1,0},//  8
                          {1,1,0,0,1,1,1,0}//  9
};

void updateDisplay();
void segmentsOff();
void anodesOff();

void setup() 
{
 
  
  pinMode(segData, OUTPUT); // Shift Register for Segments
  pinMode(segClock, OUTPUT);
  pinMode(segLatch, OUTPUT);

  pinMode(anData, OUTPUT); // Shift Register for Anodes
  pinMode(anClock, OUTPUT);
  pinMode(anLatch, OUTPUT);
  
 
  
  if(counter[0] == 1)
  rollover = 1;
}

void loop() 
{
 updateDisplay();
 incCount();
 
}

void incCount()
{
  
 count += 1;
  
if(count == 250)
 {
   counter[5]  += 1;
   count = 0;
 }
 
 if(counter[5] == 10)
 {
 counter[5] = 0;
 counter[4] += 1;
 }
 
 if(counter[4] == 6)
 {
   counter[4] = 0;
   counter[3] += 1;
 }
 
if(counter[3] == 10)
{
  counter[3] = 0;
  counter[2] += 1;
}

if(counter[2] == 6)
{
  counter[2] = 0;
  counter[1] += 1;
}

if(counter[1] == 10 && rollover == 0)
{
  counter[1] = 0;
  counter[0] += 1;
  rollover += 1;
}
else 
if(rollover == 1 && counter[1] == 3)
{
  for(int i = 0; i < 6; i++)
 counter[i] = rolloverAssign[i]; 
  
  rollover = 0;
}
}

void updateDisplay()
{
  if(anodePosition == -1)
  {
    anodePosition = 5;
    segmentPosition = 5;
  }
  else
  {
    anodesOff();
   segmentsOff();
    anodePins[anodePosition] = 1;
    
   
    
    for (int n = 0; n < 8; n++)
      {
      digitalWrite(segLatch, LOW);           
      shiftOut(segData, segClock, MSBFIRST, numbers[counter[segmentPosition]][n]);          
       digitalWrite(segLatch, HIGH);          
      }
    
    for (int a = 0; a < 7; a++)
    {
      digitalWrite(anLatch, LOW);           
      shiftOut(anData, anClock, MSBFIRST, anodePins[a]);         
       digitalWrite(anLatch, HIGH);           
    
  }
      
     
    
 
     delay(hold);
      
       
     anodePosition -= 1;
     segmentPosition -= 1;
  }
}

void anodesOff()
{
  for(int i = 0; i < 7; i++)
  { 
    digitalWrite(anLatch, LOW);           
    shiftOut(anData, anClock, MSBFIRST, 0);         
    digitalWrite(anLatch, HIGH);            

  }
}

void segmentsOff()
{
  for(int s = 0; s < 7; s++)
  {
    digitalWrite(segLatch, LOW);          
 shiftOut(segData, segClock, MSBFIRST, 0);          
 digitalWrite(segLatch, HIGH);
anodePins[s] = 0;  
}
}

at a delay of 5ms the brightness is acceptable but the flicker is tremendous.

at a delay of 1ms the flicker is acceptable but the display is incredibly dim
and segments that should be off appear noticeable.

Any help or insight will be greatly appreciated.

You seem to be repeating your shiftOut() calls eight times when only one is needed.

How can I put the entire array into the shift register without the loop?

when I increase the delay to slow down the multiplexing, I can't tell if its before or after the next display becomes active but all of the displays turn on ever so slightly.

So when the 5th display comes on displays 1,2,3,4 and six will turn on ever so slightly.

I can imagine this is some of my flicker issue.

Each display is not going on and off cleanly.

Kreplach: How can I put the entire array into the shift register without the loop?

Hi Kreplach, you are filling the register 8 times over instead of once. Sending 64 bits instead of 8. Multiplexing one segment at a time instead of one digit at a time. Each call to shiftOut sends 8 bits, not 1.

Your 2 dimensional array holding the segment patterns does not need the second dimension. Instead, pack the segment data for each digit into a single byte using "B00110001" instead of "{0, 0, 1, 1, 0, 0, 0, 1}".

Same principle goes for your digit control register. You should be able to remove several "for" loops.

Paul

Hello,

I have changed the code to the following.

byte anodePins[7] = {B00000000,
                      B00000001,
                      B00000010,
                      B00000100,
                      B00001000,
                      B00010000,
                      B00100000};
                      
byte numbers[11] = { B01111110,
                            B00001100,
                          B10110110,
                          B10011110,
                          B11001100,
                          B11011010,
                          B11111000,
                          B00001110,
                          B11111110,
                          B11001110,
                          B00000000
};  

digitalWrite(segLatch, LOW);  
shiftOut(segData, segClock, MSBFIRST, numbers[5]);
 digitalWrite(segLatch, HIGH); 


digitalWrite(anLatch, LOW);           
shiftOut(anData, anClock, MSBFIRST, anodePins[7]);         
digitalWrite(anLatch, HIGH);

I get nothing on the displays.

Am I using the shift register correctly to read in the entire byte without the loop?

That’s looking much better. It SHOULD display the digit 5 on the 6th display.

Try this version. It SHOULD display 012345 in the 6 displays.

const int segData = 8;
const int segClock = 7;
const int segLatch = 6;

const int anData = 9;
const int anClock = 10;
const int anLatch = 11;

// You don't really need this since anodePins[i] == 1<<i and you can calculate it on the fly
byte anodePins[6] = {
  B00000001,
  B00000010,
  B00000100,
  B00001000,
  B00010000,
  B00100000};

byte numbers[10] = { 
  B01111110,
  B00001100,
  B10110110,
  B10011110,
  B11001100,
  B11011010,
  B11111000,
  B00001110,
  B11111110,
  B11001110
};  

void setup() 
{
  pinMode(segData, OUTPUT); // Shift Register for Segments
  pinMode(segClock, OUTPUT);
  pinMode(segLatch, OUTPUT);

  pinMode(anData, OUTPUT); // Shift Register for Anodes
  pinMode(anClock, OUTPUT);
  pinMode(anLatch, OUTPUT);
}

void loop() {
  for (int i =0; i<6; i++) {
    // Turn off all the anodes
    digitalWrite(anLatch, LOW);           
    shiftOut(anData, anClock, MSBFIRST, 0);         
    digitalWrite(anLatch, HIGH);

    //  Set the segments to the digit 'i'
    digitalWrite(segLatch, LOW);  
    shiftOut(segData, segClock, MSBFIRST, numbers[i]);
    digitalWrite(segLatch, HIGH); 

    // Turn on the anode for the 'i' digit
    digitalWrite(anLatch, LOW);           
    shiftOut(anData, anClock, MSBFIRST, anodePins[i]);
    digitalWrite(anLatch, HIGH);

    delay(3);  // Give the digit some time to display, otherwise the display is off more then on.
  }
}

Hello,

That works much better.

No flicker, display is plenty bright.

brilliant.

You have helped tremendously.

Thank You.

Hello,

Everything is working as expected.

All 6 12volt displays have numbers.

I set up a counter to simulate a clock and that is working.

My only problem now is that there seems to be ghosting and bleed in the displays.

For instance when the display has something like 01:36:25 displayed you will see a little of the 5 digit bleed into the 2 digit and so on.

The segments that make up the 2 for instance will be on and distinct but other segments will be on ever so slightly.

Any insight on how to solve this problem will be greatly appreciated.

Did you remember to turn off all the anodes before changing the segments? If you leave out that step the selected segments will light on the previously selected anode until the new anode is selected.

Alternatively, fix the bleeding problem AND save 3 Arduino outputs!

Daisy-chain the two shift registers: connect the data-out from the first to the data-in of the second. Connect the 2 Clock pins together and to an Arduino output and the 2 and Latch pins together and to an Arduino output. Send all 8 cathode and all 8 anode bits before sending the Latch signal. That way, both the cathodes and anodes will be changed at the same instant when they both receive the latch signal from the Arduino.

Paul

John,

You were entirely correct.

I forgot to turn off the displays.

Everything is working correctly at this point.

Thank You for your help.

Kreplach: John, Thank You for your help.

You were lucky in that I learned by making those same mistakes about a year or two ago when I did my first 7-segment display. :)

You can fine-tune the delay by increasing it until you get flicker and then reducing it until the flicker goes away.