[SOLVED] Flickering problem 74HC164

Hi,

I found few old auxiliary displays (6 digits 7-segments LED) laying around in my warehouse.
Planning to replace the original microcontroller with Uno.

The board uses 6 pcs of 74HC164, so each 74hc164 responsible to a single digit.

I have successfully connected Uno to display any numbers that i want (without using the original microcontroller).

The connection is:
Arduino 74HC164
====== ======
Pin 2 Serial data (pin1 & 2)
Pin 3 Clock (pin 8)
+5V MR (pin 9) & Vcc (pin 14)

If I wanna display "123", the display will show [blank][blank][blank]123.

The problem is the display flickers/flashes/ghosting everytime i update the display with new number.

Please help me.

Bronson

Please post your program

A certain amount of flickering is inevitable with 74hc164, it is a very simple chip. 74hc595 would be better.

I suggest using the SPI pins and library on the Arduino to update the '164s to minimise flickering.

But first post your code, maybe that can be improved significantly. Auto Format the code first and use code tags when you post it!

You cannot avoid flickering with the HC164, but can minimize it by updating the display as fast as possible and as seldom as possible. The fastest way to update the display is with direct IO, but it is a bit tricky to program.

This is why the 74HC595 is better, it has a data enable latch, that means the data on the output is latched or remembered from the data in the shift register. This allows you do the shifting of data without the outputs changing and only revealing on all the pins at once.

With the 164, the output of the shift register appeared on each output as it shifts past. You will see this as flickering. If you use the SPI interface instead of shift out then the wrong bits appear but faster there will be less flickering but you will still see some.

Thx for the prompt reply everyone.

Here is my code:

// --F--
//|     |
//G     E
//|     |
// --H--
//|     |
//A     C
//|     |
// --B--    D

int data = 2;
int clock = 3;

void setup() {
  Serial.begin(9600);
  pinMode(data, OUTPUT);
  pinMode(clock, OUTPUT);
}

void showDisplay(String s) {

  int x = 0;
  for (int n = s.length() - 1; n >= 0; n--) {
    switch (s[n]) {
      case '0': shiftOut(data, clock, MSBFIRST, B11101110); break;
      case '1': shiftOut(data, clock, MSBFIRST, B00101000); break;
      case '2': shiftOut(data, clock, MSBFIRST, B11001101); break;
      case '3': shiftOut(data, clock, MSBFIRST, B01101101); break;
      case '4': shiftOut(data, clock, MSBFIRST, B00101011); break;
      case '5': shiftOut(data, clock, MSBFIRST, B01100111); break;
      case '6': shiftOut(data, clock, MSBFIRST, B11100111); break;
      case '7': shiftOut(data, clock, MSBFIRST, B00101100); break;
      case '8': shiftOut(data, clock, MSBFIRST, B11101111); break;
      case '9': shiftOut(data, clock, MSBFIRST, B01101111); break;
      case ' ': shiftOut(data, clock, MSBFIRST, B00000000); break;
      case '-': shiftOut(data, clock, MSBFIRST, B00000001); break;
    }
  }
}


void loop() {
  showDisplay("------");
  delay(600);
  showDisplay("     0");
  delay(600);
  showDisplay("     1");
  delay(600);
  showDisplay("     2");
  delay(600);
  showDisplay("     4");
  delay(600);
  showDisplay("     5");
  delay(600);
}

Thx
Bronson

I just tried using SPI method.
It works perfectly!!

Thx alot everyone.

Here is the updated code:

#include <SPI.h>

// --F--
//|     |
//G     E
//|     |
// --H--
//|     |
//A     C
//|     |
// --B--    D

int data = 11;
int clock = 13;

void setup() {
  Serial.begin(9600);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
}

void showDisplay(String s) {

  int x = 0;
  for (int n = s.length() - 1; n >= 0; n--) {
    switch (s[n]) {
      case '0': SPI.transfer(B11101110); break;
      case '1': SPI.transfer(B00101000); break;
      case '2': SPI.transfer(B11001101); break;
      case '3': SPI.transfer(B01101101); break;
      case '4': SPI.transfer(B00101011); break;
      case '5': SPI.transfer(B01100111); break;
      case '6': SPI.transfer(B11100111); break;
      case '7': SPI.transfer(B00101100); break;
      case '8': SPI.transfer(B11101111); break;
      case '9': SPI.transfer(B01101111); break;
      case ' ': SPI.transfer(B00000000); break;
      case '-': SPI.transfer(B00000001); break;
    }
  }
}


void loop() {
  showDisplay("------");
  delay(600);
  showDisplay("     0");
  delay(600);
  showDisplay("     1");
  delay(600);
  showDisplay("     2");
  delay(600);
  showDisplay("     4");
  delay(600);
  showDisplay("     5");
  delay(600);
}

Above code works nicely. Now i need to implement SPI method into my real code (reading RS232 data from weighing scale and displays them on LED display).

Will update the result soon.

Bronson

Succesfully implemented SPI method to my code.

Actually there are still some ghostings, but it has been reduced significantly.

Thx again :slight_smile:

Regards,
Bronson

Ghosting can probably be further reduced by placing the required segment pattern data for all digits into a buffer (a byte array) and sending that out with a single SPI.transfer(buffer, sizeof(buffer)).

And there might also be some improvement by playing with SPISettings.

From Arduino documentation:

SPISettings mySettting(speedMaximum, dataOrder, dataMode)
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

A faster speed means less flickering, but put restrictions on the connecting cable.

HKJ-lygte:
And there might also be some improvement by playing with SPISettings.

From Arduino documentation:

SPISettings mySettting(speedMaximum, dataOrder, dataMode)
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))

A faster speed means less flickering, but put restrictions on the connecting cable.

I have tried this. It didnt make any noticeable difference.

Bronson_alex:
I have tried this. It didnt make any noticeable difference.

Try it after you have implemented PoulRB suggestion.

HKJ-lygte:
Try it after you have implemented PoulRB suggestion.

Will do and post the result. Thx

I have tested PaulRB suggestion. No ghosting!! Yay!

But it has a really weird behaviour:
I cannot send same variable twice.
Display becomes blank everytime I send the same variable more than once.

#include <SPI.h>

int data = 11;
int clock = 13;
const byte text1[] = {B00101000, B00000000, B00000000, B00000000, B00000000, B00000000}; //1
const byte text2[] = {B11001101, B00000000, B00000000, B00000000, B00000000, B00000000}; //2
const byte text3[] = {B01101101, B00000000, B00000000, B00000000, B00000000, B00000000}; //3

void setup() {
  Serial.begin(9600);
  SPI.begin();
}

void loop() {
  SPI.transfer(text1, sizeof(text1));
  delay(200);
  SPI.transfer(text2, sizeof(text2));
  delay(200);
  SPI.transfer(text3, sizeof(text3));
  delay(200);
  Serial.println("loop");
}

Above code will make display shows: 1,2,3 then blank. No looping whatsoever. The arduino doesnt crash cos Serial Monitor keep displaying “loop” text.

Bronson

New hint.

If I declare the variable inside loop procedure, it loops now. Completely free of ghosting.

So why I cant use global variable? SPI library bug?

Successfully porting SPI.transfer(array, sizeof(array)) method to my final working code.

No ghosting/flickering whatsoever. Work perfectly!

Still have no idea about global variable problem, but it is an easy workaround to avoid global variable.

Thanks to everyone especially PaulRB and HKJ-lygte :slight_smile:

Bronson

Bronson_alex:
So why I cant use global variable? SPI library bug?

Not a bug and not really anything to do with the variable being global or local.

What's happening is that when you use SPI.transfer(buffer,sizeof(buffer)) it over-writes the buffer with data coming in on the MISO (Master-In-Slave-Out) pin simultaneously with sending out data with the MOSI (Master-Out-Slave-In) pin. In your circuit, there is no data coming back in, so the buffer gets filled with zeroes.

When you made the buffer local, this over-writing still happened but it didn't matter, because the buffer gets set up fresh each time loop is called.

The same thing happens when you use SPI.transfer(byte) except that instead of over-writing the byte, the data read back in is returned by the function. So you could write

byte dataIn = SPI.transfer(dataOut);

SPI is designed to swap bytes between master and slave chips simultaneously, which is why transfer
is coded to do this. For an output-only device like this shift register its redundant, but with other chips
its very handy!

Thx for the insight of SPI.transfer.
So that's why it is called TRANSFER instead of WRITE or PRINT.
I will remember this in future.

Thx again. Couldnt do it without u guys.

Bronson