4-Digit LCD. How to stop flicker?

Hi guys, I’m making a remote thermoprobe using an LM35 and a 4-Digit LCD module.

I’ve got it working… ‘sort of’, except that the display’s first digit, which is always zero, is bright and steady, but the last three are weak and flickering. I’ve attached a video.

Here is my code…

unsigned int ST_CP = 5;     // RCLK
unsigned int SH_CP = 6;     // SCLK
unsigned int DS    = 4;     // DIO

 
 
void setup() 
{
  // Set Arduino pins as outputs
  pinMode(ST_CP, OUTPUT);
  pinMode(SH_CP, OUTPUT);  
  pinMode(DS,    OUTPUT);
  Serial.begin(9600);
}

// Table to convert a hex digit into the matching 7-seg display segments
//
//
int hexDigitValue[] = {
    0xFC,    /* Segments to light for 0  */
    0x60,    /* Segments to light for 1  */
    0xDA,    /* Segments to light for 2  */
    0xF2,    /* Segments to light for 3  */
    0x66,    /* Segments to light for 4  */
    0xB6,    /* Segments to light for 5  */
    0xBE,    /* Segments to light for 6  */
    0xE0,    /* Segments to light for 7  */
    0xFE,    /* Segments to light for 8  */
    0xF6     /* Segments to light for 9  */
};


/* Set display digit to a hexadecimal value '0'..'9','A'..'F'
 *  
 *    row = row number of digit to light up 0..3 where 3 is most significant (leftmost) display digit
 *    dgit = value 0 to 15 
 *    decimalPoint = true/false : whether to light thde decimal point or not
 */
void setDigit(unsigned int row, unsigned int digit, boolean decimalPoint)
{
      unsigned int rowSelector;
      unsigned int data;

      rowSelector = bit(3-row)<<4;
      data =  ~  hexDigitValue[ digit & 0xF ] ;
      if(decimalPoint)
        data &= 0xFE;
        
      // First 8 data bits all the way into the second 74HC595 
      shiftOut(DS, SH_CP, LSBFIRST, data );

      // Now shift 4 row bits into the first 74HC595 and latch
      digitalWrite(ST_CP, LOW);
      shiftOut(DS, SH_CP, LSBFIRST, rowSelector );
      digitalWrite(ST_CP, HIGH);
      
}


/* Displays a number as a 4-digit decimal number on the display
 *   Note this is multiplexed, so you need to keep calling it
 *   or you'll end up with just one digit lit.
 */
void displayNumber(unsigned int number){
    for(unsigned int i=0; i<4; i++){
      setDigit(i, number % 10, false); // display righmost 4 bits (1 digit)
      if (i==1) setDigit(1, number % 10, true);
      number = number / 10;  // roll on to the next digit
    } 
}


void loop() 
{
    static int count=0;
    float tempReading = analogRead(A0);
    float tempCelsius = ((tempReading/1024.0)*3350)/10;
    float dispTemp = (tempCelsius * 10);
    
    Serial.print("Temp = ");
    Serial.print(tempCelsius);
    Serial.println();
    delay(100);
    count = (count+1) % 10000;    // Decimal
    displayNumber(dispTemp);
}

I can change the speed of the flicker with the ‘delay’ line, but not make it brighter.

Any help, please?

EDIT… If I add 1000 to the displayed value, so that the first digit is always 1, not 0, its bright and steady, but the others stay weak and flickery, even the second digit which, as I have it sitting, stays at 2.

Display Flicker.mpg (365 KB)

That is a bit of a mystery. Looks like some sort of electrical issue. That first digit is pretty brights - how are you powering this thing? What happens if the first digit is all blank - no segments on at all? What happens if you don't send that first digit?

Is that really LCD or LED ? Link to the module and Can you describe how things are wired and powered?

Dimmer means not ON for as long as the others. Double Check your display code (seems you send digit 1 twice), check latching.

For example, Why are you asking to display digit 1 twice, once without the decimal point and one with the decimal point?

 setDigit(i, number % 10, false); // display righmost 4 bits (1 digit)
if (i==1) setDigit(1, number % 10, true);
void displayNumber(unsigned int number){
    for(unsigned int i=0; i<4; i++){
      setDigit(i, number % 10, false); // display righmost 4 bits (1 digit)
      if (i==1) setDigit(1, number % 10, true);
      number = number / 10;  // roll on to the next digit
    }
}

how should this work?
You are always setting “row” (like you call it in your other function) to 1.
What will happen if your number is <= 999 if you still print 4 digts?

p.s.: this is not a LCD.
Link the product you are using.
In your case: Use a LED display library for the 74HC595.
Which one of the 100 tutorials are you following?

Thank you, yes, I mis-typed, it's an LED display, not LCD.

These are the units I have... 4 Bits 4bit Digital Tube LED Display Module Red Four Serial for Arduino 595 Driver|Replacement Parts & Accessories| - AliExpress

I'm using an example I found online as the basis. It seems that it does latch the 4th, or left hand, digit, but not the others.

It looks like the author sends the first digit with the decimal point and without just not to have to separate it out in the "for" loop.

If I reduce the delay to minimal, 1ms, the right three digits are acceptably bright, but the last digit fluctuates too fast. I'm going to try to put in a rolling average so that what is displayed is the average of the last thirty readings so that it doesn't change much.

Is there a better example of an LED driver I could start with?

OK, I added smoothing, and now it works as it should, except that the left hand digit is still far brighter than the others. Any advice as to how to address this? The left digit will always be zero, so I’d rather have it not glare out like that. Not having it at all would even be fine.

Here’s the revised code…

(Oh, as an aside, is there a more accurate alternative to the LM35? Looks like about 0.3’C is the maximum accuracy)

/*
  Smoothing

  Reads repeatedly from an analog input, calculating a running average and
  printing it to the computer. Keeps ten readings in an array and continually
  averages them.

  The circuit:
  - analog sensor (potentiometer will do) attached to analog input 0

  created 22 Apr 2007
  by David A. Mellis  <dam@mellis.org>
  modified 9 Apr 2012
  by Tom Igoe

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Smoothing
*/

// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// value to determine the size of the readings array.

//Pins on the 74HC595 shift reg chip - correspondence with Arduino digital pins
unsigned int ST_CP = 5;     // RCLK
unsigned int SH_CP = 6;     // SCLK
unsigned int DS    = 4;     // DIO
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;

void setup() {
// Set Arduino pins as outputs
  pinMode(ST_CP, OUTPUT);
  pinMode(SH_CP, OUTPUT);  
  pinMode(DS,    OUTPUT);
// initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}
// Table to convert a hex digit into the matching 7-seg display segments
//
//
int hexDigitValue[] = {
    0xFC,    /* Segments to light for 0  */
    0x60,    /* Segments to light for 1  */
    0xDA,    /* Segments to light for 2  */
    0xF2,    /* Segments to light for 3  */
    0x66,    /* Segments to light for 4  */
    0xB6,    /* Segments to light for 5  */
    0xBE,    /* Segments to light for 6  */
    0xE0,    /* Segments to light for 7  */
    0xFE,    /* Segments to light for 8  */
    0xF6     /* Segments to light for 9  */
};

/* Set display digit to a hexadecimal value '0'..'9','A'..'F'
 *  
 *    row = row number of digit to light up 0..3 where 3 is most significant (leftmost) display digit
 *    dgit = value 0 to 15 
 *    decimalPoint = true/false : whether to light thde decimal point or not
 */
void setDigit(unsigned int row, unsigned int digit, boolean decimalPoint)
{
      unsigned int rowSelector;
      unsigned int data;

      rowSelector = bit(3-row)<<4;
      data =  ~  hexDigitValue[ digit & 0xF ] ;
      if(decimalPoint)
        data &= 0xFE;
        
      // First 8 data bits all the way into the second 74HC595 
      shiftOut(DS, SH_CP, LSBFIRST, data );

      // Now shift 4 row bits into the first 74HC595 and latch
      digitalWrite(ST_CP, LOW);
      shiftOut(DS, SH_CP, LSBFIRST, rowSelector );
      digitalWrite(ST_CP, HIGH);
      
}

/* Displays a number as a 4-digit decimal number on the display
 *   Note this is multiplexed, so you need to keep calling it
 *   or you'll end up with just one digit lit.
 */
void displayNumber(unsigned int number){
    for(unsigned int i=0; i<4; i++){
      setDigit(i, number % 10, false); // display righmost 4 bits (1 digit)
      if (i==1) setDigit(1, number % 10, true);
      number = number / 10;  // roll on to the next digit
    } 
}

void loop() {
  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = analogRead(inputPin);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  average = total / numReadings;
  // Convert it to an actual temperature
  float tempCelsius = ((average/1024.0)*3250);
  // Send it to the Serial monitor
  Serial.print("Temp = ");
  Serial.print(tempCelsius);
  Serial.println();
  delay(1);
  // and send it to the LED
      displayNumber(tempCelsius);
}

Instead of:
setDigit(i, number % 10, false) ; // display righmost 4 bits (1 digit)
if (i==1) setDigit(1, number % 10, true) ;

Try just:
setDigit(i, number % 10, i == 1) ; // display righmost 4 bits (1 digit) DP 1

Take a TM1637 library

There are multiple available - here is one to try

Thanks, J-M-L, I've downloaded that library to give it a try.

I've posted a question in a new thread because it's not directly related to my earlier question - the first line in the example of that library is :

@@ -1,83 +1,83 @@

and that errors out with "Stray '@' in program"

I can't find a reference to what '@' or '@@' means in c++

Thanks again.

Rickinnocal:
the first line in the example of that library is :

@@ -1,83 +1,83 @@

that's not what I see in the example

probably a wrong copy paste ?

Very strange. It's definitely in the version I unzipped, but when I did a fresh download and unzip, it's not there. 40 years ago I'd have blamed it on line noise :slight_smile:

That said, while it compiles and uploads, it still doesn't seem to actually do anything. I'm not sure my modules have a TM1637 in them. On the back there are two 74HC595 shift register chips.

The link you provided clearly mentions TM1637... the picture of the back indeed shows two 74HC595 shift register... seems to be a scam... You should ask for reimbursement

Rickinnocal:
Thanks, J-M-L, I've downloaded that library to give it a try.

I've posted a question in a new thread because it's not directly related to my earlier question - the first line in the example of that library is :

@@ -1,83 +1,83 @@

and that errors out with "Stray '@' in program"

I can't find a reference to what '@' or '@@' means in c++

Thanks again.

That is not C++, it's patch syntax:

At 70c a pop I'm not too worried about a refund :slight_smile:

I would, however, like to get rid of this annoying bright first digit.

Thanks for your help.

I don't have any of these device at hand, so can't reproduce.

real ones with TM1637 are even cheaper and no hassle to deal with

At 70c a pop I'm not too worried about a refund :slight_smile:

Don't do it for you, do it for the next guy... => That's more to prevent them from doing it again. That's false advertising and a plague. (and you'll likely get a free module to keep as they won't bother asking for the module back)

Thanks, pert. No idea where that came from, I've never worked with patches.

I'll go ahead and request one. Ali is usually pretty good about those... although you're never that sure what you'll get when you buy from them.

yeah sometimes it's feels like a lottery...

if you are open for a different display, look for a MAX7219 (with 0.3" segments) or a HT16K33 Display (0.5" segments). I find them more convenient and there are nice libraries available also.