Screen shows only one frame and then turns white

Description

Screen shows only one frame and then turns white.

What MCU/Processor/Board and compiler are you using?

ST7789 with esp32. Squareline studio, lvg v8.3.6

What have you tried so far?

Code to reproduce

Add the relevant code snippets here.

#include <TFT_eSPI.h>
#include <Arduino.h>
#include <SPI.h>

#define USE_UI          //if you want to use the ui export from Squareline ,pleease define USE_UI.
#define Display_28        //according to the board you using ,if you using the ESP32 Display 3.5inch board, please define 'Display_35'.if using 2.4inch board,please define 'Display_24'.

#ifdef USE_UI
#include <lvgl.h>
#include "ui.h"
#endif

#if defined Display_35      //ESP32 Display 3.5inch Board
/*screen resolution*/
static const uint16_t screenWidth  = 480;
static const uint16_t screenHeight = 320;
uint16_t calData[5] = { 353, 3568, 269, 3491, 7  };     /*touch caldata*/

#elif defined Display_24    //ESP32 Display 2.4inch Board
static const uint16_t screenWidth  = 320;
static const uint16_t screenHeight = 240;
uint16_t calData[5] = { 557, 3263, 369, 3493, 3  };

#elif defined Display_28    //ESP32 Display 2.8inch Board
static const uint16_t screenWidth  = 320;
static const uint16_t screenHeight = 240;
uint16_t calData[5] = { 189, 3416, 359, 3439, 1 };
#endif


TFT_eSPI lcd = TFT_eSPI(); /* TFT entity */

#if defined USE_UI
static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[ screenWidth * screenHeight / 13 ];

//_______________________
/* display flash */
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
  uint32_t w = ( area->x2 - area->x1 + 1 );
  uint32_t h = ( area->y2 - area->y1 + 1 );

  lcd.startWrite();
  lcd.setAddrWindow( area->x1, area->y1, w, h );
  lcd.pushColors( ( uint16_t * )&color_p->full, w * h, true );
  lcd.endWrite();

  lv_disp_flush_ready( disp );
}

uint16_t touchX, touchY;
/*touch read*/
void my_touchpad_read( lv_indev_drv_t * indev_driver, lv_indev_data_t * data )
{

  bool touched = lcd.getTouch( &touchX, &touchY, 600);
  if ( !touched )
  {
    data->state = LV_INDEV_STATE_REL;
  }
  else
  {
    data->state = LV_INDEV_STATE_PR;

    /*set location*/
    data->point.x = touchX;
    data->point.y = touchY;

    Serial.print( "Data x " );
    Serial.println( touchX );

    Serial.print( "Data y " );
    Serial.println( touchY );
  }
}
#endif


void setup()
{
  Serial.begin( 9600 ); /*serial init */

  //Port_D
  pinMode(25, OUTPUT);
  digitalWrite(25, LOW);

  //LCD init
  lcd.begin();          
  lcd.setRotation(1); 
  lcd.fillScreen(TFT_BLACK);
  lcd.setTouch(calData);
  delay(100);
  //background light pin
  pinMode(27, OUTPUT);
  digitalWrite(27, HIGH);
  lcd.invertDisplay(0);
#if defined USE_UI
  //lvgl init
  lv_init();
  
  lv_disp_draw_buf_init( &draw_buf, buf1, NULL, screenWidth * screenHeight / 13 );

  /*Display init*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init( &disp_drv );
  /*Display driver port of LVGL*/
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register( &disp_drv );

  /*touch driver port of LVGL*/
  static lv_indev_drv_t indev_drv;
  lv_indev_drv_init( &indev_drv );
  indev_drv.type = LV_INDEV_TYPE_POINTER;
  indev_drv.read_cb = my_touchpad_read;
  lv_indev_drv_register( &indev_drv );

  ui_init();        //LVGL UI init
  
#else               //if you haven't defined 'USE_UI', the program compiler will not compile the code above; it will just compile the code follows

  lcd.fillScreen(TFT_BLACK);    //The screen of the board will change the screen color per second.
  delay(1000);
  lcd.fillScreen(TFT_WHITE);
  delay(1000);
  lcd.fillScreen(TFT_RED);
  delay(1000);
  lcd.fillScreen(TFT_YELLOW);
  delay(1000);
  lcd.fillScreen(TFT_BLUE);
  delay(1000);
  lcd.fillScreen(TFT_GREEN);
  delay(1000);
#endif
  Serial.println( "Setup done" );
}

int n = 0;
void loop()
{
n++;
char b[20];
char c[20];
char d[20];
char e[20];
String(n).toCharArray(d,20);
String((n*-1)+129).toCharArray(c,20);
String(millis()).toCharArray(b,20);
String(millis()/67).toCharArray(e,20);
 lv_label_set_text(ui_AmbientTemp,b);
 lv_label_set_text(ui_AmbientTemp1,e);
 lv_label_set_text(ui_Water,d);
 lv_label_set_text(ui_OilTemp,c);
 lv_slider_set_value(ui_WaterTempSlider, n, LV_ANIM_ON);
 lv_slider_set_value(ui_WaterTempSlider1, (n*-1)+129, LV_ANIM_ON);
if(n>129){n=0;}
//#if defined USE_UI
lv_tick_inc(20);
Serial.println( b);
 lv_timer_handler();
 lv_task_handler();
 
  delay(20);
//#else
  //while(1);
//#endif
}

Screenshot and/or video

0:11 - screen shows one frame

Welcome here and whatis your question?

how to solve that? It should show data all the time. Not only for few miliseconds

Solve bug in your hw schematics. My tip display RST signal.
Too your loop code is ugly tick_inc cant be placed here … Remove this line and enable custom tick in conf

you mean that rst might not be connected propertly? When I tried with just TFT_eSPI everything worked fine

Use as start this

and in lv_conf.h set

#define LV_TICK_CUSTOM 1

It’s clearly not a problem with code. I’ve used same one with ILI9341 and it worked fine. Any other ideas?

When you dont plan accept recommendation from docu and forum , stop asking here and go play with LEGO.

I’ve litearlly changed that code dumb ass. Whats the diffrence beetween using build in function and doing it previus way. And docs? Thats a lot of shit, half of links doesnt even work.

And here is smth for you actually:

Hello,

Obviously Marian is a bit rude but he is actually correct.
In your main loop you call both lv_timer_handler() and lv_task_handler() AND lv_tick_inc().
lv_timer_handler and lv_task_handler are the same. So call only one: lv_task_handler() just calls
lv_timer_handler(). See the source code below:

static inline LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_task_handler(void)
{
    return lv_timer_handler();
}

Just use lv_timer_handler()!

Next, lv_tick_inc() should be called at a certain set interval (i.e. a timer interrupt). See the documenation:

https://docs.lvgl.io/master/porting/tick.html

Very recently discussed this in another thread: WT32-SC01 lv_label_set_text not changing on screen

Hope this clears things up, this might not fix that white screen issue but should still be in order.

As Tinus says, we had this discussion about refreshing the screen. My solution was;

In the code header, put this

hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

void ARDUINO_ISR_ATTR onTimer()
{
  portENTER_CRITICAL_ISR(&timerMux);
  portEXIT_CRITICAL_ISR(&timerMux);
  lv_tick_inc(1000);
}

and in your setup(), this

  timer = timerBegin(1000000);
  timerAttachInterrupt(timer, &onTimer);
  timerAlarm(timer, 1000000, true, 0);

The timer will fire every second - I tried to do it more often but the ESP32 kept booting. Every time it fires, it will call the onTimer() function which will refresh the screen.

Of course, mine won’t be the only solution, but it works for me and I’m sticking to it! Good luck and don’t stand on the LEGO, it hurts like buggery! Steve.