lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.03k stars 189 forks source link

Testing an ILI9341 in esp32S3 #251

Closed martinberlin closed 1 year ago

martinberlin commented 1 year ago

52C1D42B-4F04-4211-B258-6CB694F6C526 Hi @lovyan03 Building this here with ESP-IDF v.4.4 and ESP32S3 (The Espressif dev board with 2 MB PSRAM) I'm testing one of this TFT following the examples here and other examples. Still could not get it to work correctly but the wiring seems alright since I see something! Also I had to comment this part of the CMakeFiles otherwise esp_lcd won't be added as a component and the build fails:

set(COMPONENT_SRCS ${SRCS})
find_package(LCD COMPONENTS esp_lcd QUIET)
#if (NOT LCD_FOUND)
# NOTE: It seems is landing in this one, since esp_lcd is not being added resulting in a fail build
#   set(COMPONENT_REQUIRES nvs_flash efuse)
#else()
  set(COMPONENT_REQUIRES nvs_flash efuse esp_lcd)
#endif()

I can help you with the CMake, I'm not expert but I like to research in this field, as it serves me for future projects. Still I could not see much except an R G (mirrored) in the TFT and a very dimm backlight. As another question: How is supposed to be regulated the backlight? There is any example that reflects on this? Advice: If you have the time it would be great to build a Wiki for this repository. Where you can explain and paste code examples for many different displays. I did this for my epaper component cale-idf : https://github.com/martinberlin/cale-idf/wiki and it works great since you can make a page per display and then explain in detail, so you avoid also getting issues (Or you can redirect developers to first read this Wiki page) And of course this let's you drop specific examples and config options for different MCU's.

Here is the sketch where I'm trying to drive a ILI9341 with S3:

#define LGFX_USE_V1
#include <LovyanGFX.hpp>
extern "C" {
    void app_main();
}

class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ILI9341 _panel_instance;
    lgfx::Bus_Parallel8 _bus_instance;
    lgfx::Light_PWM     _light_instance;
   public:
    LGFX(void)
    {
      {
        auto cfg = _bus_instance.config();
        // Bus_Parallel8 config
        //cfg.i2s_port = I2S_NUM_0;    // Not for S3
        cfg.freq_write = 20000000;    // 送信クロック (最大20MHz, 80MHzを整数で割った値に丸められます)
        cfg.pin_wr = 11;              // WR を接続しているピン番号
        cfg.pin_rd = 14;              // RD を接続しているピン番号
        cfg.pin_rs = 13;              // RS(D/C)を接続しているピン番号

        cfg.pin_d0 = 36;
        cfg.pin_d1 = 37;
        cfg.pin_d2 = 38;
        cfg.pin_d3 = 39;
        cfg.pin_d4 = 40;
        cfg.pin_d5 = 41;
        cfg.pin_d6 = 42;
        cfg.pin_d7 = 2;
        _bus_instance.config(cfg);    // 設定値をバスに反映します。
        _panel_instance.setBus(&_bus_instance);      // バスをパネルにセットします。
      }
      // Backlight BL pin in TFT
      { 
      auto cfg = _light_instance.config();    // バックライト設定用の構造体を取得します。

      cfg.pin_bl = 5;              // バックライトが接続されているピン番号
      cfg.invert = false;           // バックライトの輝度を反転させる場合 true
      cfg.freq   = 8000;           // バックライトのPWM周波数
      cfg.pwm_channel = 1;          // 使用するPWMのチャンネル番号

      _light_instance.config(cfg);
      _panel_instance.setLight(&_light_instance);
      }

      // TFT config CS, RST & dimensions
      {
      auto cfg = _panel_instance.config();
      cfg.pin_cs           =    10;  // Chip Select
      cfg.pin_rst          =    12;  // RST  (-1 = disable)
      cfg.pin_busy         =    -1;  // BUSY (-1 = disable)

      cfg.panel_width      =   240;  // 実際に表示可能な幅
      cfg.panel_height     =   320;  // 実際に表示可能な高さ
      cfg.offset_x         =     0;  // パネルのX方向オフセット量
      cfg.offset_y         =     0;  // パネルのY方向オフセット量
      cfg.offset_rotation  =     0;  // 回転方向の値のオフセット 0~7 (4~7は上下反転)
      cfg.dummy_read_pixel =     8;  // ピクセル読出し前のダミーリードのビット数
      cfg.dummy_read_bits  =     1;  // ピクセル以外のデータ読出し前のダミーリードのビット数
      cfg.readable         =  true;  // データ読出しが可能な場合 trueに設定
      cfg.invert           = false;  // パネルの明暗が反転してしまう場合 trueに設定
      cfg.rgb_order        = false;  // パネルの赤と青が入れ替わってしまう場合 trueに設定
      cfg.dlen_16bit       = false;  // 16bitパラレルやSPIでデータ長を16bit単位で送信するパネルの場合 trueに設定
      cfg.bus_shared       = false;  // SDカードとバスを共有している場合 trueに設定(drawJpgFile等でバス制御を行います)
      _panel_instance.config(cfg);
      }

      setPanel(&_panel_instance);
    }
  };

LGFX display;

void app_main() {
    printf("Testing an ILI8341 using Lovyan!\n");
    display.init();
    display.fillScreen(TFT_BLACK);
    display.setTextSize((std::max(display.width(), display.height()) + 255) >> 8);

    display.startWrite();
    display.setTextColor(0xFF0000U);
    display.drawString("R", 30, 16);
    display.setTextColor(0x00FF00U);
    display.drawString("G", 40, 16);
    display.setTextColor(0x0000FFU);
    display.drawString("B", 50, 16);
    display.endWrite();
}

Please tell me if I'm missing something and what would be the best way to collaborate with an S3 Demo.

lovyan03 commented 1 year ago

@martinberlin I am not good at advancing two topics at the same time, so I would like to limit the conversation here to Issues. Please proceed with the discussion about the creation of WiKi in the Discussion section, not in the Issue section.

Use the setBrightness function to adjust the backlight.

for (int i = 0; i < 256; ++i)
{
  display.setBrightness(i);
  delay(16);
}

With this code, the backlight should gradually brighten from off to on. Depending on the panel, the polarity of the lights on and off may be reversed. If it is reversed, change the invert parameter of the light instance.

/// light config
cfg.invert = true;

If the PWM control does not work, try connecting the BL pin to either Vcc or GND for now to brighten the screen.

Next, the orientation and color of the panel is different than expected. Perhaps the clock is too fast and the initialization commands are not being processed correctly. To be sure, lower freq_write in the bus configuration to about 10 MHz and see what happens.

If there is no change after lowering the clock, adjust the setting parameters.

/// panel config
cfg.invert    = true;  // polarity invert : white<->black  blue<->yellow
cfg.rgb_order = true;  // swap red<->blue
lovyan03 commented 1 year ago

I have adjusted the CMakeLists. Perhaps this will work with the ESP32S3. However, assuming that new MCUs will be introduced in the future, this branch may be a little less maintainable.

set(COMPONENT_SRCS ${SRCS})
if(IDF_TARGET MATCHES "esp32s3")
# message(STATUS "LGFX TARGET is esp32s3")
  set(COMPONENT_REQUIRES nvs_flash efuse esp_lcd)
else()
  find_package(LCD COMPONENTS esp_lcd QUIET)
  if (NOT LCD_FOUND)
# message(STATUS "LGFX TARGET is NOT esp32s3")
    set(COMPONENT_REQUIRES nvs_flash efuse)
  else()
# message(STATUS "LGFX TARGET is NOT esp32s3 but has esp_lcd")
    set(COMPONENT_REQUIRES nvs_flash efuse esp_lcd)
  endif()
endif()
martinberlin commented 1 year ago

Hi Lovyan,

I am not good at advancing two topics at the same time, so I would like to limit the conversation here to Issues.

Sure, sorry let's just focus on making this work. About light config, it seems I have just a bad display. Either connecting the BLK pin to 3.3V (very dimmed light) or to GND (completely off) does not solve the problem. But the curious thing is that the backlight starts strong just for some milliseconds and then goes down. In fact leaving the light pin open (no connection) seems to be stronger than connecting it to PWM. It's like the backlight is fed also from another source than this BLK wire. Very strange. In any case it was a 10 u$ display, so won't worry much.

About Panel config:

   cfg.rgb_order = true;  // swap red<->blue. Perfect now colors work as expected.

Also had to swap width x height:

      cfg.panel_width      =   320;  // 240 
      cfg.panel_height     =   240;  // 320 trimmed screen

And last problem is that the display is mirrored. Tried adjusting the frequency down to 10 Mhz but that does not seem to be the issue here. Thanks a lot for your help!

lovyan03 commented 1 year ago

Hello @martinberlin

In fact leaving the light pin open (no connection) seems to be stronger than connecting it to PWM.

Come to think of it, I have seen products before with backlights that would not turn on unless the PWM frequency was low or high ( 1000 ~ 40000 ). I don't know if this will solve the problem, but try changing the PWM frequency and adjusting setBrightness just to be sure.

Also had to swap width x height:

No, if the driver IC is ILI9341, then width = 240; height = 320; is correct. The orientation should be adjusted using the setRotation function.

However, it is odd that the orientation is landscape in the sample code you presented. Perhaps the initialization parameters were not handled correctly or some other glitch may be involved.

lovyan03 commented 1 year ago

@martinberlin Ah... It is possible that the panel may require 5V for the backlight.

martinberlin commented 1 year ago

Thanks I will try that also. 5V does not seem to solve the problem either. Here a small video: https://twitter.com/martinfasani/status/1540228525801758720

No, if the driver IC is ILI9341, then width = 240; height = 320; is correct.

Ok but with 240*320 this is what I see: From 0 to 240 (Correct) from 240 -> 320 Noise. Would post a picture but it does not look good at all without backlight. Will try to fix it adjusting PWM. Thanks a lot.

Any hints in the mirroring issue?

lovyan03 commented 1 year ago

Try the setRotation function. This function will rotate by 90 degrees for 0 ~ 3. 4 ~ 7 rotate by 90 degrees with the top and bottom flipped.

lovyan03 commented 1 year ago

Try this code. https://github.com/lovyan03/LovyanGFX/blob/master/examples/HowToUse/2_user_setting/2_user_setting.ino#L236-L253

If it works correctly, it will look like this.

image

martinberlin commented 1 year ago

Thanks I will try at night since with such a low backlit, I see nothing! By the way changed the BL pin to 5 and soldered a LED with a RES. Your PWM works perfectly in the component. So it's just that I have bad hardware or there is a specific FREQ that on this display without Datasheet won't work. Brand is: ZHONGJINGYUAN In another datasheets such as this: https://datasheetspdf.com/pdf-file/769801/ILITEK/ILI9341/1 I see that sometimes this displays need to receive a command to switch the backlight on? Or maybe is some different SPI model. ILI9341_datasheet

lovyan03 commented 1 year ago

Oh... I hadn't thought of that because I have never seen a panel where the backlight is controlled by the LCD driver IC. Perhaps there is a possibility that it could be operated by sending commands to the ILI9341.

Since 0x54 is a read register, try writing to the 0x53 register.

display.startWrite();
display.writeCommand(0x53);  // Write CTRL Display 
display.writeData(0x04);    // BL On
display.endWrite();
martinberlin commented 1 year ago

I tried many writeCommand's and none seem to fix the issue. At the end I realized that leaving the BLK pin open is the most bright of all. It's amazing how many hours we can spend fighting against a ten dollar display ;)

Anyways I learned a lot in the process and finally got to print R, G, B in the right colors and orientation. But using:

 cfg.panel_width`      =   320;  // 240 
 cfg.panel_height     =   240;  // 320 -> gives trimmed screen will add some photos

// AND : uint8_t rotation = 5;

But there was no way at all to make the backlight better. No datasheet for this brand and type of display. And also it was removed from Aliexpress making it impossible to adquire a new one.

martinberlin commented 1 year ago

Thanks for all the tips! will reopen if I need more help. Proud to support you!

IMG_1649

martinberlin commented 1 year ago

BFED4744-E009-4E59-B49D-66C7F52CB138