How to have fast text with ILI9340 LCD?

Status
Not open for further replies.

jimmie

Well-known member
Hello:

I am using a 2.2" LCD (ILI9340). I have a simple sketch which I use to display very fast text. However, all I see are white squares. Is this a limitation of this display? This works on a character LCD.

Here is my code:


void loop() {
count = count + 1;
tft.setCursor(0, 0);
tft.setTextColor(ILI9340_WHITE); tft.setTextSize(3);
tft.print(count);
delay (3);
}

I realize I can use a longer delay but that would be unacceptable in my full sketch.

Thanks.
 
The time consuming and always identical setTextColor and setTextSize can be done in setup(), no need to re-iterate these each loop().
But still then, you’ll get all numbers printed one above the other, you’ll have always to clear the affected screen area before printing the next value.
Even if there are understandable reasons for actualizing the display often and quickly, don’t forget that the human eye does not catch up with refresh rates > 25Hz, which means that it is sufficient to update the display every 40ms. To not waist CPU time by using the blocking delay(), I’d rather use an intervalTimer object to trigger the display update at these regular intervals, while the loop() might continue doing more important work in the meantime.
 
Thank you @ Theremingenieur. Certainly good advice.

I changed the code to the one below, but I am still getting numbers written on top of one another even with a long delay. I guess I do not know how does one clear the "...clear the affected screen area"?

Here is my current code:

void loop() {
tft.setCursor(0, 0);
tft.println(" ");
tft.setCursor(0, 0);
count = count + 1;
tft.print(count);
delay (2000);
}
 
Even if there are understandable reasons for actualizing the display often and quickly, don’t forget that the human eye does not catch up with refresh rates > 25Hz, which means that it is sufficient to update the display every 40ms. To not waist CPU time by using the blocking delay(), I’d rather use an intervalTimer object to trigger the display update at these regular intervals, while the loop() might continue doing more important work in the meantime.

Alternatively to interval timer one could use


Code:
void loop() {
  count = count + 1;

  // update TFT
  static uint32_t t0=0;
  uint32_t t1=milis();
  if(t1-t0>40) // maybe 20 (50 Hz update rate)?
  {
    tft.print(count);
    t0=t1;
  }
  // do other stuff
}
 
Thank you @ Theremingenieur. Certainly good advice.

I changed the code to the one below, but I am still getting numbers written on top of one another even with a long delay. I guess I do not know how does one clear the "...clear the affected screen area"?

Two possible variants:
a) "Gross": Draw a filled rectangle of appropriate size but not larger than needed to save time and CPU cycles in the background color (I guess black) just before printing the next numeric value.
b) "Delicate": Print the old numeric value again at the same coordinates, but in background color, just before printing the new value.

Understand that in opposite to a lcd matrix, the tft is pixel based and not character based. Thus you have basically to "kill" every drawn pixel before drawing something new in the same area.

symbolic example code for solution b)
Code:
void loop() {
tft.setTextColor(backgroundColor);
tft.setCursor(0,0);
tft.print(count);
tft.setTextColor(foregroundColor);
tft.setCursor(0,0);
count +=1;
tft.print(count);
delay(whatever);
}
 
Last edited:
Thank you @WMXZ. Certainly using millis will avoid using delay but the problem remains, namely the numbers are written on top of one another. In other words, the first line is not cleared prior to writing new data (and I do not know how to do it).

Here is my current code:

void loop() {
tft.setCursor(0, 0);
count = count + 1;

// update TFT
static uint32_t t0=0;
uint32_t t1=millis();
if(t1-t0>40) // maybe 20 (50 Hz update rate)?
{
tft.print(count);
t0=t1;
}
// do other stuff
}
 
Thank you again @Theremingenieur.

Indeed, you did remind me. A few years ago, I used successfully drawing a filled rectangle. I will try your "delicate" method now.
 
Thank you @WMXZ. Certainly using millis will avoid using delay but the problem remains, namely the numbers are written on top of one another. In other words, the first line is not cleared prior to writing new data (and I do not know how to do it).

I did not address the overwrite but suggested a 'timed' version that does not need a timer object.
If in setup you clear the whole screen, or at least the areas where you plan to write continuously, then you are fine.
Also you could the write field initialize with some values (e.g. 0) then you can use the 'delicate' method.
 
I won't mention about how often you update or the like as that was mentioned earlier...

@Theremingenieur solution should work as would a simple fillrect/fillscreen - But potentially the user will see flashes as first the text is erased (drawn in background color) and then redrawn in FG color with new number.

Another solution might be to use drawing the text in Opaque mode. That is something like:

Code:
void loop() {
    count = count + 1;
    tft.setCursor(0, 0);
    tft.setTextColor(ILI9340_WHITE, ILI0340_BLACK);   // set text color for FG and BG color
    tft.setTextSize(3);
    tft.print(count);
    delay (3);
}
Note: the above may be sufficient for you, but if your text output is shorter than previous ones than text to the right is not overwritten... I have solved this a couple of different ways.
a) If you know that there is nothing to the right of your field and lets say you know the number will take 1-3 digits to output, then simply output a couple of spaces after the
number to possibly overwrite any previous digits.

b) Use fill rect to clear out anything to the right of your new output. That is if you know your text will draw inside a rectangle likes say (0,0) - (100, 50), you can
after you do your tft.print, you can then do something like:

Code:
void loop() {
    count = count + 1;
    tft.setCursor(0, 0);
    tft.setTextColor(ILI9340_WHITE, ILI0340_BLACK);   // set text color for FG and BG color
    tft.setTextSize(3);
    tft.print(count);
    int16_t cursor_x = tft.getCursorX();
    tft.fillRect(cursor_x, 0, 100 - cursor_x, 50);  // note the 0, 100, 50 are your field y1, field width, field height... 
    delay (3);
}

This can be easily be modified to handle fields where you pass in either: x, y, w, h or x1, y1, x2, y2
 
I like the first, opaque variant. The width problem could be solved by using a formatted printf(), left-padding the number with zeros.
And, BTW, no need to put the line

tft.setTextColor(ILI9340_WHITE, ILI0340_BLACK); // set text color for FG and BG color

into the loop, since these values won't change and could be set once in setup().
 
I agree with Michael, that in your current code base you could put some of the settings like color and size into setup.

However it was unclear to me from the text in the original posting:
I realize I can use a longer delay but that would be unacceptable in my full sketch

If there will be additional text being output and if all of the text fields will use the same font/colors.... If so move to setup, else
may need it where the text is output...
 
Status
Not open for further replies.
Back
Top