Flickering / Jitter during screen change

Description

Screen jitters / flickers while changing screens. Happens in both landscape and portrait orientations.

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

MaTouch ESP32-S3 Parallel TFT with Touch 7“
ESP32-S3-WROOM-1-N16R8, 16MB Flash, 8MB PSRAM
Screen Resolution: 1024*600

What LVGL version are you using?

v8.3.11 and also tried with v9.1.0

What do you want to achieve?

Smooth transition between screens, animated or non animated. No preference.

What have you tried so far?

  • Changing LVGL version to v9.1.0, same behavior
  • Changing orientations
  • Enabling / disabling screen change animations in SLS
  • Changing frequency to: 12000000, 14000000,16000000, 20000000

Code to reproduce

LCD Initialization:

Arduino_ESP32RGBPanel *bus = new Arduino_ESP32RGBPanel(
  GFX_NOT_DEFINED /* CS */, GFX_NOT_DEFINED /* SCK */, GFX_NOT_DEFINED /* SDA */,
  40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
  45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
  5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
  8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */
);

Arduino_RPi_DPI_RGBPanel *gfx = new Arduino_RPi_DPI_RGBPanel(
  bus,
  SCREEN_W /* width */, 1 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 128 /* hsync_back_porch */,
  SCREEN_H /* height */, 1 /* vsync_polarity */, 13 /* vsync_front_porch */, 3 /* vsync_pulse_width */, 45 /* vsync_back_porch */,
  1 /* pclk_active_neg */, 14000000 /* prefer_speed */, true /* auto_flush */);

/* Display flushing */
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);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

setup() and loop()

void setup() {
  Serial.begin(115200); /* prepare for possible serial debug */
  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, LOW);
  delay(100);

  String LVGL_Arduino = "Hello Arduino! ";
  LVGL_Arduino += String('V') + lv_version_major() + "." + lv_version_minor() + "." + lv_version_patch();

  Serial.println(LVGL_Arduino);
  Serial.println("I am LVGL_Arduino");

  lv_init();

  pin_init();
  touch_init(gfx->width(), gfx->height());

  // Init Display
  gfx->begin();

#if LV_USE_LOG != 0
  lv_log_register_print_cb(my_print); /* register print function for debugging */
#endif

#ifdef ESP32
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 10, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 10);
#endif
  if (!disp_draw_buf) {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  } else {
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 10);

    /*Initialize the display*/
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    disp_drv.sw_rotate = 1;
    disp_drv.rotated = LV_DISP_ROT_90;
    disp_drv.full_refresh = 1; 
    lv_disp_drv_register(&disp_drv);

    /*Initialize the touch input driver*/
    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();
  }
  Serial.println("Setup done");
}

void loop() {
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);
}

Screenshot and/or video

Video: https://youtube.com/shorts/QutcEuve9I0?feature=share

Hi I have the same probleem:

  • ESP32S3-WROOM-2-N32R8, 32MB Flash, 8MB PSRAM
  • LCD display, 480x480 px, 16bit RGB interface. I am using LVGL 8.3.4
  • Using ESP-IDF 5.2.1

What have you tried so far?

  • Changing the PCLK frequency from 16000000, to 8000000, to 10000000

Code to reproduce
in my main.c

lvgl_mux = xSemaphoreCreateRecursiveMutex();

xTaskCreatePinnedToCore(lvgl_port_task, "LVGL", LVGL_STACK_SIZE, NULL, 15, NULL, 1 );

// Tick interface for LVGL
const esp_timer_create_args_t lvgl_tick_timer_args =
{
    .callback = increase_lvgl_tick,
    .name = "lvgl_tick"
};
esp_timer_handle_t lvgl_tick_timer;
esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer);
esp_timer_start_periodic(lvgl_tick_timer, portTICK_PERIOD_MS * 1000);

if (lvgl_lock(-1))
{
    ui_init();
    lvgl_unlock();
}
backlight_init( LCD_PIN_BK_LIGHT );

This is my initialization code for the display:

void qmsd_rgb_spi_init()
{
spi_bus_config_t buscfg = {
.sclk_io_num = LCD_SPI_CLK,
.mosi_io_num = LCD_SPI_DATA0,
.miso_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 10 * 1024,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));

spi_device_interface_config_t devcfg = {
    .clock_speed_hz = 10 * 1000 * 1000,     //Clock out at 10 MHz
    .mode = 0,                              //SPI mode 0
    .spics_io_num = LCD_SPI_CS,             //CS pin
    .queue_size = 7,                        //We want to be able to queue 7 transactions at a time
};

ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &g_screen_spi));
rgb_driver_init();
gpio_set_drive_capability( (gpio_num_t)LCD_PCLK_GPIO, GPIO_DRIVE_CAP_0 );       // Strongest setting, or blurry edges

spi_bus_remove_device(g_screen_spi);
spi_bus_free(SPI2_HOST);

gpio_config_t io_conf =
{
    .intr_type = GPIO_INTR_DISABLE,
    .pin_bit_mask = BIT64(LCD_SPI_CS),
    .mode = GPIO_MODE_OUTPUT
};
gpio_config(&io_conf);
gpio_set_level( LCD_SPI_CS, 1 );

}

void screen_setup(void)
{
qmsd_rgb_spi_init();

esp_lcd_rgb_panel_config_t panel_config = {
    .data_width = 16,
    .psram_trans_align = 64,
    .pclk_gpio_num = LCD_PCLK_GPIO,
    .vsync_gpio_num = LCD_VSYNC_GPIO,
    .hsync_gpio_num = LCD_HSYNC_GPIO,
    .de_gpio_num = LCD_DE_GPIO,
    .disp_gpio_num = LCD_DISP_EN_GPIO,
    .data_gpio_nums = {
        LCD_DATA0_GPIO,
        LCD_DATA1_GPIO,
        LCD_DATA2_GPIO,
        LCD_DATA3_GPIO,
        LCD_DATA4_GPIO,
        LCD_DATA5_GPIO,
        LCD_DATA6_GPIO,
        LCD_DATA7_GPIO,
        LCD_DATA8_GPIO,
        LCD_DATA9_GPIO,
        LCD_DATA10_GPIO,
        LCD_DATA11_GPIO,
        LCD_DATA12_GPIO,
        LCD_DATA13_GPIO,
        LCD_DATA14_GPIO,
        LCD_DATA15_GPIO,
    },
    .timings = {
        .pclk_hz = 16 * 1000 * 1000,
        .h_res = 480,
        .v_res = 480,
        .hsync_pulse_width = 8,
        .hsync_back_porch = 13,
        .hsync_front_porch = 10,
        .vsync_pulse_width = 8,
        .vsync_back_porch = 13,
        .vsync_front_porch = 2,
    },
    .flags.fb_in_psram = 1,
    .flags.refresh_on_demand = 0,   // Mannually control refresh operation
    .flags.double_fb = 1,
    // .bounce_buffer_size_px = 4800,
    .clk_src = LCD_CLK_SRC_PLL160M,
};

qmsd_rgb_init(&panel_config);

}

This is the link to the video showing the issue:

Kind regards.