Flickering text on tft lcd

Hello everyone!

I am working on a gauge set for my car, i am using an arduino mega and a 3.5" TFT LCD

(https://www.amazon.com/dp/B0B5ML6R5L?ref=ppx_yo2ov_dt_b_product_details&th=1).

the text for the sensor readings is flickering way worse than i expected. i found a couple potential solutions one is the "flickerfree" library:

(Teensy/Arduino/ESP FlickerFree text printing - YouTube)

the other is in the adafruit gfx library called a "canvas":

I've tried to get both of these approaches to work but I haven't been able to. i am using the mcufriend library and it seems like the flickerfree library maybe doesnt play nice with it, the adafruit version i just don't understand how to implement it. anything I've tired that will compile just displays nothing.

has anyone had success? or maybe another option? it seems like the "flickerfree" option is the simplest.

currently filckering code:

#include <Adafruit_GFX.h>    // Core graphics library
#include <MCUFRIEND_kbv.h>   // Hardware-specific library
MCUFRIEND_kbv tft;

//include fonts
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>
#include <Fonts/FreeSans24pt7b.h>

#include <FreeDefaultFonts.h>

//include image files
#include "gaugebmp.h" //includes image tab
#include "splash.h" //includes image tab

//define colors
#define BLACK   0x0000
#define RED     0xF800
#define GREEN   0x07E0
#define WHITE   0xFFFF
#define GREY    0x8410
#define BLUE    0x001F

//setup voltage related variables
float voltage_temp = 0.0;
float voltage_disp = 0.0;
float r1=90900.0;
float r2=10000.0;
float voltage_disp_overwrite = 0.0;

//setup for oil related variables
const int oilZero = 102.4; //analog reading of pressure transducer at 0psi
const int oilMax = 921.6; //analog reading of pressure transducer at 100psi
const int oilmaxPSI = 100; //psi value of transducer being used

float oilValue = 0; //variable to store the value coming from the pressure transducer
float oilValue_overwrite = 0;

//setup for boost related variables
const int boostZero = 102.4; //analog reading of pressure transducer at 0psi
const int boostMax = 921.6; //analog reading of pressure transducer at 100psi
const int boostmaxPSI = 100; //psi value of transducer being used

float boostValue = 0; //variable to store the value coming from the pressure transducer
float boostValue_overwrite = 0;



void setup(void)
{
    Serial.begin(9600);
    uint16_t ID = tft.readID();
    Serial.println("Example: Font_simple");
    Serial.print("found ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
    tft.begin(ID);
    tft.setRotation (1); //sets screen rotation to landscape (can be set 0 to 3)
    tft.fillScreen(BLACK);

    tft.drawBitmap(0, 0, splash, 480, 320, BLUE); //draws bitmap from tab (for color images use tft.drawRGBBitmap)

    delay(3000);
    tft.fillScreen(BLACK);
   
    tft.drawBitmap(0, 0, gaugebmp, 480, 320, WHITE); //draws bitmap from tab
   
}



//void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg)
//{
   // int16_t x1, y1;
   // uint16_t wid, ht;
    //tft.drawFastHLine(0, y, tft.width(), WHITE);
   // tft.setFont(f);
   // tft.setCursor(x, y);
   // tft.setTextColor(GREEN);
   // tft.setTextSize(sz);
   // tft.print(msg);
   
   // delay(1000);
//}

void loop(void)
{

 //reading and calculating sensors
  
  //voltage sensing
  int voltage_read = analogRead(A15);
  voltage_temp = (voltage_read * 5) / 1024.0; //convert read value to voltage value
  voltage_disp = voltage_read / (r2/(r1+r2)); //comping for voltage divider r2/(r1+r2)
  if (voltage_disp < 0.1)
  {
    voltage_disp=0.0;
  }
  if (voltage_disp > 99)
  {
    voltage_disp=99;
  }

  //oil pressure sensing
  oilValue = analogRead(A14); //reads value from input pin and assigns to variable
  oilValue = ((oilValue-oilZero)*oilmaxPSI)/(oilMax-oilZero); //conversion equation to convert analog reading to psi
  if (oilValue < 1)
  {
    oilValue=0;
  }
  if (oilValue > 99)
  {
    oilValue=99;
  }

    //boost pressure sensing
  boostValue = analogRead(A13); //reads value from input pin and assigns to variable
  boostValue = ((boostValue-boostZero)*boostmaxPSI)/(boostMax-boostZero); //conversion equation to convert analog reading to psi
   if (boostValue < 1)
  {
    boostValue=0.0;
  }
  if (boostValue > 99)
  {
    boostValue=99.0;
  }
  
  //displaying data

    tft.setFont(&FreeSans12pt7b);

  //voltage
  if (voltage_disp < 12.6 or voltage_disp > 15)
  {
   
    tft.setCursor(80, 200);
    tft.setTextColor(BLACK);
    tft.setTextSize(1);
    tft.print (voltage_disp_overwrite, 1);
    tft.setCursor(80, 200);
    tft.setTextColor(RED);
    tft.print (voltage_disp, 1);
  }
  else
  {
    
    tft.setCursor(80, 200);
    tft.setTextColor(BLACK);
    tft.setTextSize(1);
    tft.print (voltage_disp_overwrite, 1);
    tft.setCursor(80, 200);
    tft.setTextColor(GREEN);
    tft.print (voltage_disp, 1);
  }

  //boost
  
    tft.setCursor(225, 200);
    tft.setTextColor(BLACK);
    tft.setTextSize(1);
    tft.print (boostValue_overwrite, 0);
    tft.setCursor(225, 200);
    tft.setTextColor(GREEN);
    tft.print (boostValue, 0);
  
  //oil
 if (oilValue < 10)
 {
  
    tft.setCursor(355, 200);
    tft.setTextColor(BLACK);
    tft.setTextSize(1);
    tft.print (oilValue_overwrite, 0);
    tft.setCursor(355, 200);
    tft.setTextColor(RED);
    tft.print (oilValue, 0);
 }
 else
 {
    
    tft.setCursor(355, 200);
    tft.setTextColor(BLACK);
    tft.setTextSize(1);
    tft.print (oilValue_overwrite, 0);
    tft.setCursor(355, 200);
    tft.setTextColor(GREEN);
    tft.print (oilValue, 0);
 }

    //set text overwrites
    voltage_disp_overwrite=voltage_disp;
    oilValue_overwrite=oilValue;
    boostValue_overwrite=boostValue;
 
  delay (100);

}

"flickerfree" code:

#include <Adafruit_GFX.h>    // Core graphics library
#include <MCUFRIEND_kbv.h>   // Hardware-specific library
MCUFRIEND_kbv tft;
#include <FlickerFreePrint.h>

//include fonts
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>
#include <Fonts/FreeSans24pt7b.h>

#include <FreeDefaultFonts.h>

//include image files
#include "gaugebmp.h" //includes image tab
#include "splash.h" //includes image tab

//define colors
#define BLACK   0x0000
#define RED     0xF800
#define GREEN   0x07E0
#define WHITE   0xFFFF
#define GREY    0x8410
#define BLUE    0x001F

//setup voltage related variables
float voltage_temp = 0.0;
float voltage_disp = 0.0;
float r1=90900.0;
float r2=10000.0;

//setup for oil related variables
const int oilZero = 102.4; //analog reading of pressure transducer at 0psi
const int oilMax = 921.6; //analog reading of pressure transducer at 100psi
const int oilmaxPSI = 100; //psi value of transducer being used

float oilValue = 0; //variable to store the value coming from the pressure transducer


//setup for boost related variables
const int boostZero = 102.4; //analog reading of pressure transducer at 0psi
const int boostMax = 921.6; //analog reading of pressure transducer at 100psi
const int boostmaxPSI = 100; //psi value of transducer being used

float boostValue = 0; //variable to store the value coming from the pressure transducer

//flickerfree
FlickerFreePrint<MCUFRIEND_kbv.h> fftft(&Display, C_WHITE, C_BLACK);




void setup(void)
{
    Serial.begin(9600);
    uint16_t ID = tft.readID();
    Serial.println("Example: Font_simple");
    Serial.print("found ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
    tft.begin(ID);
    tft.setRotation (1); //sets screen rotation to landscape (can be set 0 to 3)
    tft.fillScreen(BLACK);

    tft.drawBitmap(0, 0, splash, 480, 320, BLUE); //draws bitmap from tab (for color images use tft.drawRGBBitmap)

    delay(3000);
    tft.fillScreen(BLACK);
   
    tft.drawBitmap(0, 0, gaugebmp, 480, 320, WHITE); //draws bitmap from tab
   
}



void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg)
{
    int16_t x1, y1;
    uint16_t wid, ht;
    //tft.drawFastHLine(0, y, tft.width(), WHITE);
    tft.setFont(f);
    tft.setCursor(x, y);
    tft.setTextColor(GREEN);
    tft.setTextSize(sz);
    tft.print(msg);
   
    delay(1000);
}

void loop(void)
{

 //reading and calculating sensors
  
  //voltage sensing
  int voltage_read = analogRead(A15);
  voltage_temp = (voltage_read * 5) / 1024.0; //convert read value to voltage value
  voltage_disp = voltage_read / (r2/(r1+r2)); //comping for voltage divider r2/(r1+r2)
  if (voltage_disp < 0.1)
  {
    voltage_disp=0.0;
  }
  if (voltage_disp > 99)
  {
    voltage_disp=99;
  }

  //oil pressure sensing
  oilValue = analogRead(A14); //reads value from input pin and assigns to variable
  oilValue = ((oilValue-oilZero)*oilmaxPSI)/(oilMax-oilZero); //conversion equation to convert analog reading to psi
  if (oilValue < 1)
  {
    oilValue=0;
  }
  if (oilValue > 99)
  {
    oilValue=99;
  }

    //boost pressure sensing
  boostValue = analogRead(A13); //reads value from input pin and assigns to variable
  boostValue = ((boostValue-boostZero)*boostmaxPSI)/(boostMax-boostZero); //conversion equation to convert analog reading to psi
   if (boostValue < 1)
  {
    boostValue=0;
  }
  if (boostValue > 99)
  {
    boostValue=99;
  }
  
  //displaying data

  //voltage
  if (voltage_disp < 12.6 or voltage_disp > 15)
  {
  tft.setFont(&FreeSans24pt7b);
    tft.setCursor(50, 200);
    tft.setTextColor(RED);
    tft.setTextSize(1);
    fftft.print (voltage_disp, 1);
  }
  else
  {
      tft.setFont(&FreeSans24pt7b);
    tft.setCursor(50, 200);
    tft.setTextColor(GREEN);
    tft.setTextSize(1);
    fftft.print (voltage_disp, 1);
  }

  //boost
  tft.setFont(&FreeSans24pt7b);
    tft.setCursor(175, 200);
    tft.setTextColor(GREEN);
    tft.setTextSize(1);
    fftft.print (boostValue, 0);
  
  //oil
 if (oilValue < 10)
 {
  tft.setFont(&FreeSans24pt7b);
    tft.setCursor(300, 200);
    tft.setTextColor(RED);
    tft.setTextSize(1);
    fftft.print (oilValue, 0);
 }
 else
 {
    tft.setFont(&FreeSans24pt7b);
    tft.setCursor(300, 200);
    tft.setTextColor(GREEN);
    tft.setTextSize(1);
    fftft.print (oilValue, 0);
 }

 
  delay (250);

}

adafruit antiflicker code:

#include <Adafruit_GFX.h>    // Core graphics library
#include <MCUFRIEND_kbv.h>   // Hardware-specific library
MCUFRIEND_kbv tft;

//include fonts
#include <Fonts/FreeSans9pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
#include <Fonts/FreeSerif12pt7b.h>
#include <Fonts/FreeSans24pt7b.h>

#include <FreeDefaultFonts.h>

//include image files
#include "gaugebmp.h" //includes image tab
#include "splash.h" //includes image tab

//define colors
#define BLACK   0x0000
#define RED     0xF800
#define GREEN   0x07E0
#define WHITE   0xFFFF
#define GREY    0x8410
#define BLUE    0x001F

//setup voltage related variables
float voltage_temp = 0.0;
float voltage_disp = 0.0;
float r1=90900.0;
float r2=10000.0;

//setup for oil related variables
const int oilZero = 102.4; //analog reading of pressure transducer at 0psi
const int oilMax = 921.6; //analog reading of pressure transducer at 100psi
const int oilmaxPSI = 100; //psi value of transducer being used

float oilValue = 0; //variable to store the value coming from the pressure transducer


//setup for boost related variables
const int boostZero = 102.4; //analog reading of pressure transducer at 0psi
const int boostMax = 921.6; //analog reading of pressure transducer at 100psi
const int boostmaxPSI = 100; //psi value of transducer being used

float boostValue = 0; //variable to store the value coming from the pressure transducer

//GFX canvas
GFXcanvas1 canvas(480, 320);


void setup(void)
{
    Serial.begin(9600);
    uint16_t ID = tft.readID();
    Serial.println("Example: Font_simple");
    Serial.print("found ID = 0x");
    Serial.println(ID, HEX);
    if (ID == 0xD3D3) ID = 0x9481; //force ID if write-only display
    tft.begin(ID);
    tft.setRotation (1); //sets screen rotation to landscape (can be set 0 to 3)
    tft.fillScreen(BLACK);

    tft.drawBitmap(0, 0, splash, 480, 320, BLUE); //draws bitmap from tab (for color images use tft.drawRGBBitmap)

    delay(3000);
    tft.fillScreen(BLACK);
   
    tft.drawBitmap(0, 0, gaugebmp, 480, 320, WHITE); //draws bitmap from tab

    canvas.setTextWrap(false);
   
}



void showmsgXY(int x, int y, int sz, const GFXfont *f, const char *msg)
{
    int16_t x1, y1;
    uint16_t wid, ht;
    //tft.drawFastHLine(0, y, tft.width(), WHITE);
    tft.setFont(f);
    tft.setCursor(x, y);
    tft.setTextColor(GREEN);
    tft.setTextSize(sz);
    tft.print(msg);
   
    delay(1000);
}

void loop(void)
{

 //reading and calculating sensors
  
  //voltage sensing
  int voltage_read = analogRead(A15);
  voltage_temp = (voltage_read * 5) / 1024.0; //convert read value to voltage value
  voltage_disp = voltage_read / (r2/(r1+r2)); //comping for voltage divider r2/(r1+r2)
  if (voltage_disp < 0.1)
  {
    voltage_disp=0.0;
  }
  if (voltage_disp > 99)
  {
    voltage_disp=99;
  }

  //oil pressure sensing
  oilValue = analogRead(A14); //reads value from input pin and assigns to variable
  oilValue = ((oilValue-oilZero)*oilmaxPSI)/(oilMax-oilZero); //conversion equation to convert analog reading to psi
  if (oilValue < 1)
  {
    oilValue=0;
  }
  if (oilValue > 99)
  {
    oilValue=99;
  }

    //boost pressure sensing
  boostValue = analogRead(A13); //reads value from input pin and assigns to variable
  boostValue = ((boostValue-boostZero)*boostmaxPSI)/(boostMax-boostZero); //conversion equation to convert analog reading to psi
   if (boostValue < 1)
  {
    boostValue=0;
  }
  if (boostValue > 99)
  {
    boostValue=99;
  }
  
  //displaying data

  canvas.fillScreen(0);

  //voltage
  if (voltage_disp < 12.6 or voltage_disp > 15)
  {
  tft.setFont(&FreeSans24pt7b);
    canvas.setCursor(50, 200);
    //canvas.setTextColor(RED);
    canvas.setTextSize(1);
    canvas.print (voltage_disp, 1);
    canvas.drawBitmap(0,0, canvas.getBuffer(),
      canvas.width(), canvas.height(), RED, GREEN);
  }
  else
  {
      tft.setFont(&FreeSans24pt7b);
    canvas.setCursor(50, 200);
    //canvas.setTextColor(GREEN);
    canvas.setTextSize(1);
    canvas.print (voltage_disp, 1);
        canvas.drawBitmap(0,0, canvas.getBuffer(),
      canvas.width(), canvas.height(), RED, GREEN);
  }

  //boost
  tft.setFont(&FreeSans24pt7b);
    tft.setCursor(175, 200);
    tft.setTextColor(GREEN);
    tft.setTextSize(1);
    tft.print (boostValue, 0);
  
  //oil
 if (oilValue < 10)
 {
  tft.setFont(&FreeSans24pt7b);
    tft.setCursor(300, 200);
    tft.setTextColor(RED);
    tft.setTextSize(1);
    tft.print (oilValue, 0);
 }
 else
 {
    tft.setFont(&FreeSans24pt7b);
    tft.setCursor(300, 200);
    tft.setTextColor(GREEN);
    tft.setTextSize(1);
    tft.print (oilValue, 0);
 }

 
  delay (250);

}

Have you tried a longer delay here (let the old data settle before the new data arrives), or no delay (put old data atop new data)?

How did you leap from a 0V-5V scale to a 0-99 scale? Where is the math?

Points awarded for using 1024 and not 1023 as a scale factor though...

looks like you draw that canvas onto itself.. probably should be onto tft instead..

good luck, have fun.. ~q

voltage_disp = voltage_read / (r2/(r1+r2))

r1 and r2 are defined at the top of the code

because i am reading the 12 volt system on the car i am using a resistive divider. theoretically it should never hit 99 volts but that is the max my resistive divider can handle without overloading the pin on the arduino. the "(r2/(r1+r2)) accounts for the divider.

i cant take credit, here is where i read about it:

i have tried and it just changes the rate of the flicker

i will experiment a little more with this but i was trying to follow the example in the adafruit documentation. a few hours in and my head was spinning. Haha

Well you got close..
use a separate canvas..
do all the drawing to it, then draw it all at once to the display..

should do it..

~q

@carldozer
To minimize flickering do not print the values every time you measure it, do it when the values were changed only.

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