Bonjour à tous,
Je viens ici solliciter votre aide pour la compréhension de la lenteur d'affichage de mes images sur mon esp32-s3 N16R8
Déjà pour commencer j'i du dwongrade quelque bibliotheque pour enfin avoir une image qui s'affiche mais bon....
Je suis avec un ili9488 spi 3.2" de 320x480.
voici mon code user_setup.h
#include <TJpg_Decoder.h>
#define FS_NO_GLOBALS
#include <FS.h>
#include "SPIFFS.h"
#include "SPI.h"
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap){
if ( y >= tft.height() ) return 0;
tft.pushImage(x, y, w, h, bitmap);
return 1;
}
void setup()
{
Serial.begin(115200);
Serial.println("\n\nTesting TJpg_Decoder library");
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield();
}
Serial.println("\r\nInitialisation done.");
tft.begin();
tft.setRotation(1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.fillScreen(TFT_BLACK);
TJpgDec.setSwapBytes(true);
TJpgDec.setJpgScale(1);
TJpgDec.setCallback(tft_output);
// Afficher une seule fois l'image
}
void loop()
{
TJpgDec.drawFsJpg(0, 0, "/horizon.jpg");
delay(2000);
TJpgDec.drawFsJpg(0, 0, "/aloy.jpg");
delay(2000);
}
Les images s'affiche bien mais l'affichage n'est pas rapide elles défile de haut en bas en 1.5s environ je trouve ça assez long et peut élégant.
J'ai essayé avec chat GPT, Gemini et écumé pas mal d'info sur le web, mais quand on débute on trouve tout et n'importe quoi et tout ce que lis je ne le comprends pas forcement.
Donc si une personne veut bien me mettre sur la bonne voie je serai bien content !
Merci
Bonjour,
Quelle est la résolution de tes images? Plus les images sont "grandes", plus ça va s'afficher lentement. L'idéal est de les rééchantilloner à la taille de ton écran, 320x480.
Il est conseillé aussi d'utiliser des images BMP, elles ne sont pas compréssé, donc plus rapide à afficher.
En supposant que le SPI fonctionne à une vitesse de 3MHZ (il me semble que c'est un maximum.
Pour un écran de 320x480, il y a donc 153600 pixels à envoyer. Si on est en mode couleurs sur 16 bits (il y a un mode sur 18 bits moins utilisé), il faut deux octets par pixels. Il faut donc envoyer 307200 octets. Pour chaque octet, on envoie un bit de start, 8 bits de donnée en un bit de stop. Il y a donc 3072000 à envoyer. Si l'ESP se débrouille pour que les octets à envoyer soient prêts tout le temps, à 3MHZ, il faut 3072000/3MHz = 1 seconde.
Si tout est au max, il faut au moins 1 seconde pour envoyer une image. Si pendant ce temps il doit faire autre chose, lire la carte SD par exemple (qui est aussi lue en série, donc lentement) il lui faudra un peu plus de temps.
On ne peut pas descendre en dessous de la seconde, seconde et demie.
C'est pour cela que j'ai utilisé un afficheur en mode parallèle 16 bits (envoi de 16 bit à la fois) au lieu du mode SPI (1 bit à la fois).
Mes images je les est faites avec photoshop en 320x480 pour 20ko max
J'ai essayé aussi un autre code avec LittlesFS et activé DMA dans user_setup.h de tft espi
mais j'ai exactement le meme resultat 1.5s pour afficher une image. au cas ou voici le code
Merci pour tes infos Vileroi ! nos message se sont croisés. Je suis dessus de cette réalité !
Cependant j'ai vue des vidéo ou une personne affiche une sorte de diapo de plusieurs images et au click sur sont écran les images change instantanément. Bref peut être y a t il un format une méthode différente pour avoir des images rapide.
Ce qui me fait un peur c'est la perf j'ai pour prjet de piloter plusieurs led environ 15, GPIO + dfminiplayers + ecran. Le but est de jouer un effet lumineux un son et une image gif. les 3 simultanément
Je te conseille, d'utiliser un esp32 s3 pour le tft et un autre pour tes leds, servo0, capteurs, etc... et je les fais communiquer avec ESP-NOW.
Moi c'est ce que je fais et mes images (non-compressées) s'affiche rapidement mais j'utilise un tft plus petit (240x320) en SPI et avec la librairie TFT_e SPI de bodmer (c'es la bibliothèque la plus rapide que j'ai trouvé après en avoir essayé plusieurs).
L'affichage d'images prend beaucoup de ressources, je branche rien d'autres que le tft, le tactile et la carte SD.
Pour les leds, je te conseille des ws2812b, tu pourras facilement en piloter 15 ou plus simplement avec 3 fils (un fil pour les datas et deux fils pour l'alimentation).
Salut Axelmaux, 2 esp32 c'est la piste que j'envisage mais ça me plait moyen !
il faut encore que j'essaie d'autre format d'image et que j'explore les fichier hex progem (je crois) mais aussi les gifs. En meme temps je découvre ce merveilleux petit jouer en codant tous et n'importe quoi dessus. Je vais fuiner un peut partout des infos mais si j'arrive à optimisé un truc je posterai l'info !
Sinon, si tu veux un tft performant, il faut prendre un avec connexions parallèle (comme dit vileroi), mais ça va te prendre beaucoup de broche de ton esp32...
Si tu prends un tft parallèle 16 bits:
21 à 22 utilisés pour le TFT
Il resterait donc 8 à 9 GPIOs libres
Tu peux descendre à 6–7 GPIOs utiles si tu laisses certains ports réservés à l’USB ou au boot
Si tu ajoutes le tactile et la carte SD, il te restera au mieux entre 3 et 7 broches de libres.
J'ai de bonnes nouvelles !! Finalement, j'ai réussi à afficher une image en 850 ms. Pfiou, c'est déjà mieux que 1.4 s. Cependant, il faut passer par la case des images en .raw.
J'ai développé un script Python qui convertit les images jpg, jpeg et png en .raw. Ce script doit être placé dans le dossier contenant vos images. Avec une ligne de commande, toutes les images sont converties en un rien de temps !!
Personnellement, j'utilise LittleFS pour stocker mes images. On verra par la suite si je mets une carte SD ou non et je ferai d'autres tests de performance.
Le bénéfice est cool car il y a moins de bibliothèques à inclure, le processeur ne travaille pas à la conversion, les données sont envoyées directement à l'écran. Mais le plus cool, c'est la qualité des images : elles sont au top sur l'écran, fidèles aux couleurs et nettes !
Avec les fichiers jpg, pour obtenir les mêmes résultats, je dois beaucoup dégrader l'image avec Photoshop et réduire la qualité à 20 %, ça passe mais ce n'est pas terrible non plus. Si l'on veut la même qualité, il faut enregistrer une image de 300 ko voire plus. Avec les bibliothèques TFT_eSPI et TJpg_Decoder en full qualité jpeg, on est à 1.4 s voire plus en qualité moyenne, tandis qu'en .raw, on arrive à 850 ms.
En conclusion, je dirais qu'avec le format .raw, nous avons le beurre et un peu plus
Je ferai un zip demain avec tous les fichiers source et les informations. Là tout de suite, j'ai la flemme.
Voici le dossier complet avec tous les explicatifs dedans !
Vous trouverez un dossier images pour afficher des images jpg, un autre dossier pour afficher des .raw et le dernier en bonus un script pour convertir votre jpg png en raw. image-rawetjpg-tft-espi.zip (2,2 Mo)
Il y a un goulot d'étranglement quelque part, mais je ne sais pas d'où il vient ! je suis sur que si ou le trouve on pourrai aller encore plus vite.
J'ai augmenté la fréquence à 70Mhz du spi mais le gain est de 50ms grand max. je sais si c tft_espi le buffer par ligne ou simplement mon écran ili9488 chinois qui à une limite de dingue.
Si vous avez des informations et ou des solution pour encore optimiser, n'hésitez pas à me le faire savoir !
Aussi au cas ou pour tft_espi voici mon user_setup.h
Je viens de faire un autre test avec un ili9341 là ça change tout !!
Affichage de fichiers RAW RGB565 depuis LittleFS
horizon.raw affiché en 98 ms
aloy.raw affiché en 99 ms
Pfff mon ili9488 est limité sur son spi ou la tft_espi quel dommage.
Allez bonne journée
Si la taille de la mémoire le permet, mettre en cache l'image RAW ou BMP avec la couleur de chaque pixel lors de l'écriture effective du pixel
Repérer dans le driver l'écriture vers le LCD et n'attaquer l'écriture effective que si la couleur du pixel est différente de celle du cache
Cette méthode est bien adaptée si les images évoluent sans trop de différences comme dans le cas d'une animation
NB: Méthode que j'utilise sur un ESP32-S3-GEEK pour optimiser le rafraichissement partiel ou total de l'écran de 240×135 pixels 65K couleurs. De plus, associé au maintien et à l'utilisation du cache, je calcule le min, la moyenne, le max et l'écart type du pourcentage du nombre de pixels trouvés dans le cache et n'ayant donc pas fait l'objet d'une écriture effective...
Je pense pareil que toi... Souvent (pas toujour) quand un demandeur a reglé son problème, on n'a plus de retour... Sans parler de personnes qui s'inscrivent pour résoudre un problème précis et une fois résolu, on ne les voit plus. Mais heureusement, pour l'instant, il y a un noyau de membres dans la partie francophone du forum qui reste actif.
La fréquence maximum théorique du SPI sur un ESP32-S3 est de 80 MHz.
Je n'ai jamais vu d'exemple d'utilisation du SPI à cette fréquence (sauf pour la phase de flashage, mais c'est une autre fonction).
Par contre j'ai vu très souvent des bibliothèques qui imposent une fréquence de 20 MHz.
Pour moi ce n'est pas à une bibliothèque d'imposer la fréquence, car on peut être amené à devoir utiliser simultanément des composants rapides et des composants lents, mais c'est comme ça.
Pour du graphisme, avec des images un peu lourdes il faut fonctionner à la fréquence la plus élevée possible.
Cette fréquence dépend du CI qui gère l'écran : est-il capable de fonctionner à 20 MHz, à 40 MHz ?
Et aussi de la qualité du câblage.
Première opération à faire : fouiller dans le code de la bibliothèque pour savoir si la fréquence SCK est déjà réglée ou pas.
Ma vision des choses.
Certain → c'est dans la datasheet :
avr à 16 MHz, SCK (SPI) max = 16 MHz / 2 = 8 MHz
Supposé et/ou déduit :
La base : En logique synchrone, la fréquence des datas est au max la moitié de celle de l'horloge, c'est aussi le théorème de Shannon sur l'échantillonnage.
Je n’ai pas donné de nouvelles car je n’ai pas vraiment eu le temps de me pencher sur LoyanGFX. Il est vrai que, lorsqu’on obtient des réponses, on ne revient pas toujours sur le forum concerné.
Personnellement, mon projet est assez complexe à mon niveau : j’ai dû faire de nombreux tests sur l’audio, les images, FreeRTOS… et je ne suis pas venu vous solliciter sans raison.
Cela dit, j’ai tout de même partagé mon expérience en fournissant directement mes fichiers. Je ne peux pas non plus travailler régulièrement sur mon petit projet, notamment à cause de mon travail.
Je comprends vos réactions, ainsi que la frustration de partager des informations précieuses sans toujours recevoir de retour ou même un simple merci.
Alors, un grand MERCI à vous tous pour m’avoir aidé à débloquer certaines choses.
Et pour enrichir l’échange et me rattraper, je publierai ici l’ensemble de mon projet afin de partager pleinement mon expérience.
J'ai installé la librairie LovyanGFX et effectivement, elle est beaucoup plus rapide pour l'affichage des images que TFT_eSPI. J'ai eu un peu de mal avec les couleurs à l'écran car j'utilise des fichiers RAW et l'encodage est lu différemment avec LovyanGFX. Voici mon fichier de configuration pour un écran ILI9341, si ça peut aider. Ah oui, mes fichiers RAW sont encodés avec le code Python que j'ai fourni dans le zip du post ci-dessus et affichés avec cette fonction :
void showRawImage(const char* path) {
File f = LittleFS.open(path, "r");
if (!f) {
Serial.println("Impossible d’ouvrir l’image !");
return;
}
tft.startWrite();
tft.setAddrWindow(0, 0, 240, 320);
uint16_t buffer[240]; // Une ligne de 240 pixels (480 octets)
for (int y = 0; y < 320; y++) {
f.read((uint8_t*)buffer, 240 * 2); // Lecture directe dans le buffer
tft.pushImage(0, y, 240, 1, buffer);
}
tft.endWrite();
f.close();
}
J'ai commandé un autre écran avec une dalle IPS, ça sera plus joli pour les couleurs et avec un meilleur angle de vue. Je ferai des photos quand je l'aurai reçu d'ici 10 jours au moins. La prochaine étape sera d'essayer de mettre un GIF pour voir si le rendu est potable ou pas