espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
12.71k stars 7.22k forks source link

Problems with LCD on ESP32-S3-N4R8 with framework > v2.0.3 #8468

Closed benlye closed 9 months ago

benlye commented 9 months ago

Board

ESP32-S3-WROOM-1-N4R8

Device Description

Elecrow 7" ESP32 Display with ESP32-S3 https://www.elecrow.com/esp32-display-7-inch-hmi-display-rgb-tft-lcd-touch-screen-support-lvgl.html

Hardware Configuration

Version

latest master (checkout manually)

IDE Name

Arduino IDE and PlatformIO

Operating System

Windows 11

Flash frequency

80MHz

PSRAM enabled

yes

Upload speed

921600

Description

I'm using the Arduino_GFX graphics library to drive the LCD screen. The display works fine if I use Arduino ESP32 v2.0.3, but v2.0.4 or newer causes the screen to display very strangely - it fades to light grey and occasionally shows a faded-out version of what should be on it.

I've tracked the change where the screen stops working properly to https://github.com/espressif/arduino-esp32/commit/666c66d3d1c7437aaebaaadf2084927b7fc476c4, where the Espressif IDF was updated to v4.4. Obviously this is a very large update with a lot of changes.

I appreciate that this is most likely something that will need fixing in the Arduino_GFX graphics library, but I'm looking for any pointers towards anything I can do to try to figure this out so I can get this device / library to work with newer framework versions. The library itself works fine with other ESP32S3 display devices, including other RGB displays.

Sketch

#include <Arduino_GFX_Library.h>

#define TFT_BL 2

Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
  41 /* DE */, 40 /* VSYNC */, 39 /* HSYNC */, 0 /* PCLK */,
  14 /* R0 */, 21 /* R1 */, 47 /* R2 */, 48 /* R3 */, 45 /* R4 */,
   9 /* G0 */, 46 /* G1 */,  3 /* G2 */,  8 /* G3 */, 16 /* G4 */, 1 /* G5 */,
  15 /* B0 */,  7 /* B1 */,  6 /* B2 */,  5 /* B3 */,  4 /* B4 */,
   0 /* hsync_polarity */, 210 /* hsync_front_porch */, 30 /* hsync_pulse_width */, 16 /* hsync_back_porch */,
   0 /* vsync_polarity */,  22 /* vsync_front_porch */, 13 /* vsync_pulse_width */, 10 /* vsync_back_porch */,
   1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
    800 /* width */, 480 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */
);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); // Init Display

  pinMode(TFT_BL, OUTPUT);
  digitalWrite(TFT_BL, HIGH);

  lcd->begin();
  lcd->fillScreen(BLACK);
}

void loop() {
  // put your main code here, to run repeatedly:
  lcd->fillScreen(RED);
  delay(2000);
  lcd->fillScreen(GREEN);
  delay(2000);
  lcd->fillScreen(BLUE);
  delay(2000);
  lcd->fillScreen(BLACK);
  delay(2000);
}

Debug Message

N/A

Other Steps to Reproduce

I've tried PlatformIO and the Arduino IDE and both behave the same - v2.0.3 works, anything newer and the display stops working.

I have checked existing issues, online documentation and the Troubleshooting Guide

lbernstone commented 9 months ago

Does the lvgl demo work on your device? Does it have the same issue? https://github.com/lvgl/lv_port_esp32

benlye commented 9 months ago

Does the lvgl demo work on your device? Does it have the same issue? https://github.com/lvgl/lv_port_esp32

I can't run the LVGL demo because I can't even get that far - the display device doesn't even initialize properly on the newer toolchain. The LVGL demo works fine when compiled using the older toolchain.

I'm currently using the Arduino_GFX library, but LovyanGFX also supports RGB displays on ESP32 devices so I will give that a go as soon as I can (this weekend, hopefully).

I don't think I have a HW problem because it works OK on v2.0.3 of the arduino-esp32 framework. I'm thinking that some default option or setting was changed and I just need to adapt to it...

benlye commented 9 months ago

This seems to have been down to the RGB sync timing settings. The values which worked with the v2.0.3 framework did not work with the new versions, but I've now got values which do.

SuGlider commented 9 months ago

Could you please share the right values? Thanks!

benlye commented 9 months ago

I'm still working on getting it 100% right - I can make it work OK with LovyanGFX but I have a problem with Arduino_GFX where the screen stays black for around a minute before suddenly displaying correctly (and then working perfectly) - it seems I don't have the timing / sync quite right. If anyone has any advice to solve that, I'd be grateful.

This code works with LovyanGFX:

#include<Arduino.h>
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <driver/i2c.h>

#define GFX_BL  2

class LGFX : public lgfx::LGFX_Device
{
public:

  lgfx::Bus_RGB     _bus_instance;
  lgfx::Panel_RGB   _panel_instance;
  lgfx::Light_PWM   _light_instance;
  lgfx::Touch_GT911 _touch_instance;

  LGFX(void)
  {
    {
      auto cfg = _panel_instance.config();

      cfg.memory_width  = 800;
      cfg.memory_height = 480;
      cfg.panel_width  = 800;
      cfg.panel_height = 480;

      cfg.offset_x = 0;
      cfg.offset_y = 0;

      _panel_instance.config(cfg);
    }

    {
      auto cfg = _panel_instance.config_detail();

      cfg.use_psram = 1;

      _panel_instance.config_detail(cfg);
    }

    {
      auto cfg = _bus_instance.config();
      cfg.panel = &_panel_instance;

      cfg.pin_d0  = GPIO_NUM_15; // B0
      cfg.pin_d1  = GPIO_NUM_7;  // B1
      cfg.pin_d2  = GPIO_NUM_6;  // B2
      cfg.pin_d3  = GPIO_NUM_5;  // B3
      cfg.pin_d4  = GPIO_NUM_4;  // B4

      cfg.pin_d5  = GPIO_NUM_9;  // G0
      cfg.pin_d6  = GPIO_NUM_46; // G1
      cfg.pin_d7  = GPIO_NUM_3;  // G2
      cfg.pin_d8  = GPIO_NUM_8;  // G3
      cfg.pin_d9  = GPIO_NUM_16; // G4
      cfg.pin_d10 = GPIO_NUM_1;  // G5

      cfg.pin_d11 = GPIO_NUM_14; // R0
      cfg.pin_d12 = GPIO_NUM_21; // R1
      cfg.pin_d13 = GPIO_NUM_47; // R2
      cfg.pin_d14 = GPIO_NUM_48; // R3
      cfg.pin_d15 = GPIO_NUM_45; // R4

      cfg.pin_henable = GPIO_NUM_41;
      cfg.pin_vsync   = GPIO_NUM_40;
      cfg.pin_hsync   = GPIO_NUM_39;
      cfg.pin_pclk    = GPIO_NUM_0;
      cfg.freq_write  = 16000000;

      cfg.hsync_polarity    = 0;
      cfg.hsync_front_porch = 40;
      cfg.hsync_pulse_width = 48;
      cfg.hsync_back_porch  = 40;

      cfg.vsync_polarity    = 0;
      cfg.vsync_front_porch = 1;
      cfg.vsync_pulse_width = 31;
      cfg.vsync_back_porch  = 13;

      cfg.pclk_idle_high    = 1;
      _bus_instance.config(cfg);
    }
    _panel_instance.setBus(&_bus_instance);

    {
      auto cfg = _light_instance.config();
      cfg.pin_bl = GPIO_NUM_2;
      _light_instance.config(cfg);
    }
    _panel_instance.light(&_light_instance);

    {
      auto cfg = _touch_instance.config();
      cfg.x_min      = 0;
      cfg.x_max      = 800;
      cfg.y_min      = 0;
      cfg.y_max      = 480;
      cfg.pin_int    = -1;
      cfg.bus_shared = false;
      cfg.offset_rotation = 0;
      // I2C
      cfg.i2c_port   = I2C_NUM_1;
      cfg.pin_sda    = GPIO_NUM_19;
      cfg.pin_scl    = GPIO_NUM_20;
      cfg.freq       = 400000;
      cfg.i2c_addr   = 0x38;        // 0x5D , 0x14
      _touch_instance.config(cfg);
      _panel_instance.setTouch(&_touch_instance);
    }

    setPanel(&_panel_instance);
  }
};

LGFX gfx;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); // Init Display

  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);

  gfx.begin();
  gfx.fillScreen(TFT_RED);
  delay(2000);
  gfx.fillScreen(TFT_GREEN);
  delay(2000);
  gfx.fillScreen(TFT_BLUE);
  delay(2000);
  gfx.fillScreen(TFT_WHITE);
  delay(2000);
  gfx.fillScreen(TFT_BLACK);
  delay(2000);
}

void loop() {
  // put your main code here, to run repeatedly:
  gfx.fillScreen(TFT_RED);
  delay(2000);
  gfx.fillScreen(TFT_GREEN);
  delay(2000);
  gfx.fillScreen(TFT_BLUE);
  delay(2000);
  gfx.fillScreen(TFT_WHITE);
  delay(2000);
  gfx.fillScreen(TFT_BLACK);
  delay(2000);
}

This is what I currently have for Arduino_GFX:

#include <Arduino_GFX_Library.h>

#define GFX_BL 2

Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
  41 /* DE */, 40 /* VSYNC */, 39 /* HSYNC */, 0 /* PCLK */,
  14 /* R0 */, 21 /* R1 */, 47 /* R2 */, 48 /* R3 */, 45 /* R4 */,
   9 /* G0 */, 46 /* G1 */,  3 /* G2 */,  8 /* G3 */, 16 /* G4 */, 1 /* G5 */,
  15 /* B0 */,  7 /* B1 */,  6 /* B2 */,  5 /* B3 */,  4 /* B4 */,
   0 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 40 /* hsync_back_porch */,
   0 /* vsync_polarity */,  1 /* vsync_front_porch */, 31 /* vsync_pulse_width */, 13 /* vsync_back_porch */,
   1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
    800 /* width */, 480 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */
);
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200); // Init Display

  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);

  gfx->begin();
  gfx->fillScreen(RED);
  delay(2000);
  gfx->fillScreen(GREEN);
  delay(2000);
  gfx->fillScreen(BLUE);
  delay(2000);
  gfx->fillScreen(WHITE);
  delay(2000);
  gfx->fillScreen(BLACK);
  delay(2000);
}

void loop() {
  // put your main code here, to run repeatedly:
  gfx->fillScreen(RED);
  delay(2000);
  gfx->fillScreen(GREEN);
  delay(2000);
  gfx->fillScreen(BLUE);
  delay(2000);
  gfx->fillScreen(WHITE);
  delay(2000);
  gfx->fillScreen(BLACK);
  delay(2000);
}
SuGlider commented 9 months ago

@benlye - try this setting:

  0 /* hsync_polarity */, 210 /* hsync_front_porch */, 30 /* hsync_pulse_width */, 16 /* hsync_back_porch */,
  0 /* vsync_polarity */, 22 /* vsync_front_porch */, 13 /* vsync_pulse_width */, 10 /* vsync_back_porch */,
  1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);
benlye commented 9 months ago

@benlye - try this setting:

 0 /* hsync_polarity */, 210 /* hsync_front_porch */, 30 /* hsync_pulse_width */, 16 /* hsync_back_porch */,
 0 /* vsync_polarity */, 22 /* vsync_front_porch */, 13 /* vsync_pulse_width */, 10 /* vsync_back_porch */,
 1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);

Those settings are the ones the vendor provides in their examples, which only seem to work with arduino-esp32 v2.0.3. With the latest version the screen does not sync.

I have given up on Arduino_GFX and switched to LovyanGFX, which just works. This is the configuration I'm using with Lovyan:

class LGFX : public lgfx::LGFX_Device
{
public:
    lgfx::Bus_RGB _bus_instance;
    lgfx::Panel_RGB _panel_instance;
    lgfx::Light_PWM _light_instance;
    lgfx::Touch_GT911 _touch_instance;
    LGFX(void)
    {
        {
            auto cfg = _panel_instance.config();
            cfg.memory_width = 800;
            cfg.memory_height = 480;
            cfg.panel_width = 800;
            cfg.panel_height = 480;
            cfg.offset_x = 0;
            cfg.offset_y = 0;
            _panel_instance.config(cfg);
        }

        {
            auto cfg = _bus_instance.config();
            cfg.panel = &_panel_instance;

            cfg.pin_d0 = GPIO_NUM_15; // B0
            cfg.pin_d1 = GPIO_NUM_7;  // B1
            cfg.pin_d2 = GPIO_NUM_6;  // B2
            cfg.pin_d3 = GPIO_NUM_5;  // B3
            cfg.pin_d4 = GPIO_NUM_4;  // B4

            cfg.pin_d5 = GPIO_NUM_9;  // G0
            cfg.pin_d6 = GPIO_NUM_46; // G1
            cfg.pin_d7 = GPIO_NUM_3;  // G2
            cfg.pin_d8 = GPIO_NUM_8;  // G3
            cfg.pin_d9 = GPIO_NUM_16; // G4
            cfg.pin_d10 = GPIO_NUM_1; // G5

            cfg.pin_d11 = GPIO_NUM_14; // R0
            cfg.pin_d12 = GPIO_NUM_21; // R1
            cfg.pin_d13 = GPIO_NUM_47; // R2
            cfg.pin_d14 = GPIO_NUM_48; // R3
            cfg.pin_d15 = GPIO_NUM_45; // R4

            cfg.pin_henable = GPIO_NUM_41;
            cfg.pin_vsync = GPIO_NUM_40;
            cfg.pin_hsync = GPIO_NUM_39;
            cfg.pin_pclk = GPIO_NUM_0;
            cfg.freq_write = 12000000;

            cfg.hsync_polarity = 0;
            cfg.hsync_front_porch = 40;
            cfg.hsync_pulse_width = 48;
            cfg.hsync_back_porch = 40;

            cfg.vsync_polarity = 0;
            cfg.vsync_front_porch = 1;
            cfg.vsync_pulse_width = 31;
            cfg.vsync_back_porch = 13;

            cfg.pclk_active_neg = 1;
            cfg.de_idle_high = 0;
            cfg.pclk_idle_high = 0;

            _bus_instance.config(cfg);
        }
        _panel_instance.setBus(&_bus_instance);

        {
            auto cfg = _light_instance.config();
            cfg.pin_bl = GPIO_NUM_2;
            _light_instance.config(cfg);
        }
        _panel_instance.light(&_light_instance);

        {
            auto cfg = _touch_instance.config();
            cfg.x_min      = 0;
            cfg.x_max      = 800;
            cfg.y_min      = 0;
            cfg.y_max      = 480;
            cfg.pin_int    = -1;
            cfg.pin_rst    = -1;
            cfg.bus_shared = false;
            cfg.offset_rotation = 0;
            cfg.i2c_port   = I2C_NUM_1;
            cfg.pin_sda    = GPIO_NUM_19;
            cfg.pin_scl    = GPIO_NUM_20;
            cfg.freq       = 400000;
            cfg.i2c_addr   = 0x14;
            _touch_instance.config(cfg);
            _panel_instance.setTouch(&_touch_instance);
        }
        setPanel(&_panel_instance);
    }
};
TheOsram commented 5 months ago

Good evening,

sorry for reopening this threat and maybe for my english. I just got the 5 inch version from China. First i used the Arduino_GFX_Library and it was running perfect. But after adding any serial connection on any available port (Software-/Hardware) i have the same issues with display fading out and comming back.

#include <Arduino_GFX_Library.h> Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel( 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 */, 0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 8 /* hsync_back_porch */, 0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 8 /* vsync_back_porch */, 1 /* pclk_active_neg */, 16000000 /* prefer_speed */); Arduino_RGB_Display *gfx = new Arduino_RGB_Display(800 /* width */, 480 /* height */, rgbpanel, 2 /* rotation */, true /* auto_flush */);

After using LovyanGFX with the 5 Inch values it works like a champ.

@benlye that was really helpfull. thanks

jrodanapolis commented 4 months ago

@benlye Hi Ben, thank you so much for posting your work here. I'm so close to getting this Elecrow 7" screen working, but I can't seem to get touches to register with my UI. I can get the home screen of it to display, and can get the touch working with examples and simple code, but can't get it working with my UI for some reason. When I try to configure the way you did from your post on Aug 4, I get the error "'I2C_NUM_1' was not declared in this scope". If I change that to GPIO_NUM_1 I can compile and see my display, but the touch functionality is gone. Any suggestions? Thanks again!

benlye commented 4 months ago

I think you might have something wrong in your IDE setup or board/platform selection. I2C_NUM_1 is defined in the core, so should be defined automatically when everything is correctly configured. What IDE are you using? What platform? Which board?

It works for me in VS Code using the current espressif32 platform.

EDIT: Also, make sure you have #include <driver/i2c.h> in your sketch.

jrodanapolis commented 4 months ago

I think you might have something wrong in your IDE setup or board/platform selection. I2C_NUM_1 is defined in the core, so should be defined automatically when everything is correctly configured. What IDE are you using? What platform? Which board?

It works for me in VS Code using the current espressif32 platform.

EDIT: Also, make sure you have #include <driver/i2c.h> in your sketch.

I definitely didn't have "#include <driver/i2c.h>" so I appreciate that suggestion! I'll give that a try tonight to see if is the missing link.

I'm using the Arduino IDE with Elecrow 7" ESP32 screen (same one from your link above). Hoping to get it speaking to my Arduino Uno R4 WiFi next, but haven't gotten there yet. I also haven't branched out into PlatformIO yet... I was hoping that I could get away with just Arduino IDE, but am willing to give PlatformIO a try if needed.

I'm also using the latest versions of the ESP package and libraries. I started with the ESP32 v2.0.3, but saw Elecrow's recent announcement that by switching to the LovyanGFX library we should be able to use the latest ESP32 package here, so I thought I would update everything to the most recent releases: https://forum.elecrow.com/discussion/585/esp32-hmi-demo-code-updated-compatible-with-new-version-of-esp32-package/

I'll mess around with things tonight and see if I can get it working, and if you have any suggestions, I'd love to hear!

Westcott1 commented 2 months ago

I have touch working correctly using the bb_captouch library.

#include <bb_captouch.h>

BBCapTouch bbct;

#define TOUCH_SDA 19
#define TOUCH_SCL 20
#define TOUCH_INT -1
#define TOUCH_RST -1

const char* szNames[] = { "Unknown", "FT6x36", "GT911", "CST820" };

void TouchInit() {
  Serial.println("Touch init...");
  // Init touch device
  bbct.init(TOUCH_SDA, TOUCH_SCL, TOUCH_RST, TOUCH_INT);
  int iType = bbct.sensorType();
  Serial.printf("Touch sensor type = %s\n", szNames[iType]);
}

void TouchRead() {
  TOUCHINFO ti;

  if (bbct.getSamples(&ti)) {  // if touch event happened
    Serial.printf("Touch x: %d y: %d size: %d\n", ti.x[0], ti.y[0], ti.area[0]);
  }
}