lovyan03 / LovyanGFX

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

drawPng fail (return false) #323

Closed PM04290 closed 1 year ago

PM04290 commented 1 year ago

Carefully written Issues are more likely to be given priority. 丁寧に記述された報告は優先して対応される可能性が高くなります。

Environment ( 実行環境 )

Problem Description ( 問題の内容 )

I have PNG files on SPIFFS, when I display them with drawPng(), sometimes the function returns 0 and nothing is displayed. The file is read in an array of bytes and set as a parameter to the function, with the number of bytes read. I tried to analyze the source code to find the problem myself but it is very complex (but brilliantly written); after a whole day of research I resolve to post this message. what can cause drawPng() function to return false?

my same program always return true and work fine when using ESP32-kit with ILI9341 see below my setup for each target

Expected Behavior ( 期待される動作 )

explicit return code of drawing error

Actual Behavior ( 実際の動作 )

return false somtimes (of the same bytes array/pgn)

Steps to reproduce ( 再現のための前提条件 )

very long source code so, i just want to know the reason(s) of false returning

Code to reproduce this issue ( 再現させるためのコード )

/**** for SC01

class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ST7796  _panel_instance;
    lgfx::Bus_SPI       _bus_instance;
    lgfx::Light_PWM     _light_instance;
    lgfx::Touch_FT5x06  _touch_instance;
  public:
    LGFX(void)
    {
      {
        auto cfg = _bus_instance.config();
        cfg.spi_host = HSPI_HOST;
        cfg.pin_mosi = 13;
        cfg.pin_miso = -1;
        cfg.pin_sclk = 14;
        cfg.pin_dc   = 21;
        cfg.spi_3wire  = true;
        cfg.freq_write = 40000000;
        _bus_instance.config(cfg);
        _panel_instance.setBus(&_bus_instance);
      }
      {
        auto cfg = _panel_instance.config();
        cfg.pin_cs           =    15;
        cfg.pin_rst          =    22;
        cfg.readable         = false;
        _panel_instance.config(cfg);
      }
      {
        auto cfg = _light_instance.config();
        cfg.pin_bl = 23;
        cfg.invert = false;
        cfg.freq   = 44100;
        cfg.pwm_channel = 7;
        _light_instance.config(cfg);
        _panel_instance.setLight(&_light_instance);
      }
      {
        auto cfg = _touch_instance.config();
        cfg.pin_int    = 39;
        cfg.pin_sda    = 18;
        cfg.pin_scl    = 19;
        cfg.i2c_addr   = 0x38;
        cfg.i2c_port   = 1;
        cfg.freq       = 400000;
        cfg.x_min      = 0;
        cfg.x_max      = 319;
        cfg.y_min      = 0;
        cfg.y_max      = 479;
        cfg.bus_shared = false;
        cfg.offset_rotation = 0;
        _touch_instance.config(cfg);
        _panel_instance.setTouch(&_touch_instance);
      }
      setPanel(&_panel_instance);
    }
};
//***** FOR ESP32+ILI9341
class LGFX : public lgfx::LGFX_Device
{
    lgfx::Panel_ILI9341 _panel_instance;
    lgfx::Bus_Parallel8 _bus_instance;
    lgfx::Touch_XPT2046 _touch_instance;

  public:
    LGFX(void)
    {
      {
        auto cfg = _bus_instance.config();
        cfg.freq_write = 20000000;
        cfg.pin_wr = 4;
        cfg.pin_rd = 2;
        cfg.pin_rs = 15;  // Data / Command
        // LCD data interface, 8bit MCU (8080)
        cfg.pin_d0 = 12;
        cfg.pin_d1 = 13;
        cfg.pin_d2 = 26;
        cfg.pin_d3 = 25;
        cfg.pin_d4 = 17;
        cfg.pin_d5 = 16;
        cfg.pin_d6 = 27;
        cfg.pin_d7 = 14;
        _bus_instance.config(cfg);
        _panel_instance.setBus(&_bus_instance);
      }
      {
        auto cfg = _panel_instance.config();
        cfg.pin_cs           =    33;
        cfg.pin_rst          =    32;
        cfg.pin_busy         =    -1;
        cfg.panel_width      =   240;
        cfg.panel_height     =   320;
        cfg.offset_x         =     0;
        cfg.offset_y         =     0;
        cfg.offset_rotation  =     1;
        cfg.dummy_read_pixel =     8;
        cfg.dummy_read_bits  =     1;
        cfg.readable         =  true;
        cfg.invert           = false;
        cfg.rgb_order        = false;
        cfg.dlen_16bit       = false;
        cfg.bus_shared       =  true;
        _panel_instance.config(cfg);
      }
      {
        auto cfg = _touch_instance.config();
        cfg.x_min      = 0;
        cfg.x_max      = 239;
        cfg.y_min      = 0;
        cfg.y_max      = 319;
        cfg.pin_int    = -1;
        cfg.bus_shared = true;
        cfg.offset_rotation = 1;
        cfg.spi_host = VSPI_HOST;
        cfg.pin_cs   = 33;
        cfg.pin_mosi = GPIO_NUM_23;
        cfg.pin_miso = GPIO_NUM_19;
        cfg.pin_sclk = GPIO_NUM_18;
        cfg.freq = 2700000;
        _touch_instance.config(cfg);
        _panel_instance.setTouch(&_touch_instance);
      }
      setPanel(&_panel_instance);
    }
};
tobozo commented 1 year ago

hi, thanks for your feedback :+1:

please edit your post and add one the png files

png uses zlib to decompress palette and data, drawPng() may fail silently when not enough heap is available

PM04290 commented 1 year ago

d-temperature-48

DEBUGf("drawsprite %d Bytes %d %d\n", nb, xI, yI); DEBUGf("%d %d %d %d\n", ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(), ESP.getMaxAllocHeap()); DEBUGln(_sprite->drawPng(tmpIcon, nb, xI, yI));

for the png attached, this is the result of the code

drawsprite 621 Bytes 1 40 71976 69820 321532 47044 0

tobozo commented 1 year ago

ok looks like it's not a memory problem, but I'm confused as your mentioned SPIFFS earlier, and it looks like you're using the byte array version of drawPng. I'd try to debug nb, xl and yl values too.

have you tried this?

_sprite->drawPngFile( SPIFFS, "/path/to/file.png",  x, y );

[edit]

drawsprite 621 Bytes 1 40

does it mean width=1, height=40 ?

looks like it's working, the first column of your png is transparent, so explicitely printing a 1x40 surface of transparent pixels ends up in nothing being printed

so whatever tries to calculate the width/height of the png is occasionally wrong, or there's a bug somewhere in the code than can corrupt the value of xl

PM04290 commented 1 year ago

xI and yI are top/left corner of png

i have tried drawPngFile but i have a compiler error; it's why i use a memory buffer

D:\HomeAssistant\DIY\MesProjets\SmartMonitor\display.cpp: In member function 'virtual void XitemInfo::draw(bool)': display.cpp:619:66: error: no matching function for call to 'lgfx::v1::LGFX_Sprite::drawPngFile(fs::SPIFFSFS&, const char, int32_t&, int32_t&)' _sprite->drawPngFile(SPIFFS, (const char)filepath, xI, yI );

tobozo commented 1 year ago

oh this one should be easy to solve: include SPIFFS.h before including LovyanGFX.hpp

PM04290 commented 1 year ago

of course.... lol

but, same issue with SPIFFS

drawsprite 987 Bytes 96 41 82428 50984 291576 47044 0

i think it's a problem on heap memory but i don't know which one; I just discovered another problem on the web server that I don't have on the ESP32-WROOM (ESP Dev Module) i'm affraid by the difference on the heap memory usage between WROOM and WROVER; it is clear that I do not use a lot of memory with regard to the figures indicated in the log

PM04290 commented 1 year ago

i draw png on MQTT data received, see log for 4 data incomming at the same time.... only the first refused

MQTT -> 95 drawsprite 1893 Bytes 1 40 99156 70992 306636 48904 0 MQTT -> 6.5 drawsprite 621 Bytes 1 40 99032 70992 306652 50988 1 MQTT -> closed drawsprite 474 Bytes 1 40 101228 55456 306708 50988 1 MQTT -> disarmed drawsprite 987 Bytes 96 41 101228 55456 306708 50988 1

tobozo commented 1 year ago

is the problem still there when psram is disabled?

PM04290 commented 1 year ago

there is no way to enable/disable PSRAM on IDE for ESP Wrover Module and on sdkconfig file i have this:

#
# SPI RAM config
#
CONFIG_SPIRAM_BOOT_INIT=
CONFIG_SPIRAM_USE_MEMMAP=
CONFIG_SPIRAM_USE_CAPS_ALLOC=
CONFIG_SPIRAM_USE_MALLOC=
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_SPIRAM_TYPE_ESPPSRAM32=
CONFIG_SPIRAM_TYPE_ESPPSRAM64=
CONFIG_SPIRAM_SIZE=-1
CONFIG_SPIRAM_SPEED_40M=y
CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
CONFIG_SPIRAM_BANKSWITCH_RESERVE=8
CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST=
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=
tobozo commented 1 year ago

ESP32 Dev Module board entry has an option to enable/disable psram and can fit both wrover and wroom profiles

image

PM04290 commented 1 year ago

Strange numeric world.... this morning, drwPngFile not work but drwPng work (with 1197 bytes). drawPng use a static memory array instead of drawPngFile who make a malloc i presume. this morning i haven't problem with my webserver, without any change in code. You mean i can use ESP Dev Module to compile for ESP Wrover ? (WT32-SC01)

tobozo commented 1 year ago

ESP32 in a nutshell: ça peut marcher sur un malentendu :-)

image

PM04290 commented 1 year ago

@tobozo puisque tu es Frenchy, je vais directement te poser la question dans la langue de Molière : est-ce tu utilise les ESP32-S3 avec l'arduino IDE, et si oui, comment fais tu pour charger la SPIFFS (data) ? le plugin couramment utilisé ne fonctionne pas. Et sinon, connais tu des modules du genre ESP32, programmable facilement avec l'arduino IDE, mais qui fasse du Zigbee; l'ESP-H3 a été annoncé il y a plusieurs mois mais je pense qu'il va falloir un moment avant qu'il soit débuggé.

tobozo commented 1 year ago

J'utilise ESP32FS.

image

Une fois installé l'outil devient disponible dans le menu tools.

image

Ceci dit il est plutot recommandé d'utiliser LittleFS.h, SPIFFS.h n'est plus maintenu et obsolete.

Si ton plugin ne fonctionne pas c'est probablement a cause de la taille de la partition SPIFFS qui n'est pas réaliste, ou trop grande pour le plugin dont la derniere maj remonte a avant la release du S3 :-)

Avec ce plugin tu auras plus de chances que ça fonctionne en commençant "sobre", avec la taille de partition par défaut pour un ESP32-Wroom. Note qu'a chaque changement de type de partition il faut absolument 1) flasher le sketch 2) uploader

image

ESP32, programmable facilement avec l'arduino IDE, mais qui fasse du Zigbee

C'est pas exactement de l'ESP32 mais ça s'en rapproche : le Zigbee Unit de M5stack, Cortex-M3 embarqué, connectable via un port série et fourni avec un cable compatible M5.

PM04290 commented 1 year ago

Tu utilise donc les ESP32-S3, il n'est pas reconnu par l'ESP core 1.x, il faut passer au 2.0.x.... tu n'as pas trop eu de problème avec certaines libraires ? j'ai essayé et j'ai eu plusieurs erreurs de compilation avec des librairies majeures, je suis donc revenu au 1.x, en mettant de coté le S3 pour le moment. Pour littleFS, on parle bien de celui là ?

tobozo commented 1 year ago

LittleFS est built-in dans le noyau arduino-esp32, la version 2.0.5 est la plus stable avec le S3:

https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS

PM04290 commented 1 year ago

et comment on charge le dossier "data" ?

tobozo commented 1 year ago

avec le plugins ESP32FS

image

PM04290 commented 1 year ago

bin je dois pas avoir le bon plugin, le mien ne me demande rien quand je l'active.... tu n'aurais pas un lien stp ?

tobozo commented 1 year ago

Désolé je t'ai dit tout ce que je savais et je n'ai pas de lien supplémentaire a fournir, il va falloir faire tes propres recherches :wink:

Le probleme initial avec drawPng étant apparemment résolu je me permets de fermer ce ticket.

Note: les questions sur SPIFFS sont hors sujet avec ce repo et peuvent etre adressées sur les sites respectifs d'arduino-esp32 et arduino-esp32fs-plugin.