SPI screens are notably slow. These screens are 240x240 pixels at 16 bit, so each frame is 115200 bytes of RAW data. If you clock the SPI at 40Mhz you can transfer a maximum of 4.8Mbps, that's 43 frames per second without taking in account the commands for the transfer (those are not much, but they count) and the delay between transfers. Then you need to add that while you are transferring data you are blocking the cores, so at the end you get those ~24fps with one single screen. To achieve maximum performance you can use DMA, the second core and a double buffer: in the first core you decode one frame, signal the second core to transfer that buffer, the second core prepares the DMA and triggers the transfer, meanwhile the first core starts decoding the next frame in the second buffer and so on, with this you remove any delay between transfers and maximize the time the first core can work in decoding frames. In fact the first core will end decoding a lot faster than the DMA transfer to the screen so you will need to synchronize the cores and ensure that the DMA transfer has finished before signaling the start of a new transfer.
@@drgusman My apologies. I stand corrected. I just checked and it is indeed SPI. Usually SPI is labelled with MOSI, MISO, CS and CLK, however, the labelling on the pins give the appearance of I2C with SDA and SCL.
@@Psirust Yeah, I know, I don't know why but these chinese manufacturers this days tend to put SDA and SCL instead of MOSI and CLK in that type of screen even if it's SPI, the only good way to discern it is to check if there is a CS line, posibly they have no clue on what they're building... xD
The ESP has 2 x SPI: HSPI and VSPI. You can use the first SPI with the first core and the second SPI with the second core. This should cut down on latency. You can also try other animated-GIF-like formats, such as APNG, WebP, AVIF, MNG and FLIF, to see if they lower your processing overhead.
GIFs have always been an extremely compute intensive format. Those sites where back in the day you could download animated emojis from would have your desktop CPU running at 100%. The smoothest animations I've seen so far on the ESP32 are from 'Lottie'. No idea how easy or hard it is to get running though.
Well Gif's themselves not really. But animated GIF's run an uncompiled script that displays an image after decoding it for a specific amount of time and converting each frame to modern graphics is a lot of programming. It is an obsolete format for really old computers that is so taxing because of its obsolesence.
I’ve been doing a few screen based projects lately involving esp32’s and screens, and memory management has been a real struggle. But Incase it matters, on top of confirming what others have said, (I’ve yet to have any problems with spi at 40mhz, and atleast on the S3 chip 80mhz has been pretty happy too), if this still turns out to be insufficient remember that on top of having two cores and command queue capabilities, you also have 2 hardware spi buses, HSPI and VSPI, so you could split the screens 3+3 and cut the bandwidth toll in half.
You can go wider than that. It's not obvious from the name, but the I2S 0 peripheral has an LCD mode allowing you to DMA 8, 16 or 24 bits wide, and the SPI devices support 2 bit DIO and 4 bit QSPI transfers. It's not RP2040 level, but quite capable if you get a little hacky. It's likely this program would benefit from putting the decompression routine in RAM, so it won't get evicted from cache during data reads. After that, verify the program is double buffering correctly, and then run two processors. The LCD driver chip (GC9A01) also supports 2 bit SPI, which would be SPI_TRANS_MODE_DIO in the ESP32 SPI.
I'm not sure what the default is for TFT_eSPI, but you may be able to bump up the communication speed as well. 40MHz is usually pretty stable with an esp32, and I've had some luck with 80MHz as well, although it won't help much if the bottleneck is in managing the gifs themselves, and not the transfer rate
The default appears to be 27MHz SPI clock, which combined with partial updates and 16 bits per pixel gives a theoretical limit of about 1/(6*240*240*16 bit / 27Mbit/s) * 4/pi ≈ 6.21 fps. Combine this with how the decoder can't run more than one or two lines ahead, and it looks like this is a relevant bottleneck. The ESP32 documentation hints that 27MHz might be the limit when going through the GPIO matrix, but using tightly coupled IO_MUX pins can reach 80MHz. For extra fun, it appears the dual data serial mode has a different bit order in the ESP32 and display controller, so the palette format would need to be rearranged.
The power consumption part not correct. You just checked the absolute max io current of the ESP chip itself. 1: you should never reach absolute max. There is a recommended max value in the datasheet. 2: IO pin and power pin is not the same. You are not powering the screen from an IO pin but from the 3.3V regulator on the board. So you should check the datasheet of the LDO not the ESP32. 3: the current draw that you measured is on the 5V USB rail, but your screen is powered from 3.3V. If there is a linear regulator then the current is roughly the same. But if you have a switching mode PSU then the 3.3V current is like 5/3.3 = 1.5 times more then the measured on 5V.
interesting thing about GIF decoding is that decoding speed tightly depends on content you have in your GIF, so it means that if your GIF frame has lots of different pixels, wide palette (but it will still be limited to 256 color palette i think) - decoding rate will be slow because decompressor output might redraw large portion of screen, but if your GIF frame has, say, text characters appearing on black background (like that console animation) - frame rate will be high because decompressor will only give you "parts that have changed since last frame", if i understand the process correctly. there is also separate song and dance around transparency handling, to do proper which you need a large framebuffer, but you should be good if your gif does not use transparency pixels
Honestly I think that the mirroring is caused by all the displays reading the same data.. since they are in parallel and you wanted only to play the gif on the first display anyway, i think there was a error in the code that pulled all CS pins active, therefore every display read the data.. imho the real limit is the spi bus, because with every display you need to send more data through the same bus.. maybe try just blinking the LCD from black to white and see the limit.. you will bypass delay with reading the gif and measure the real bandwith to the display. btw i'm also working on a project with esp32, i'm making a led bus panel (using P10 monochrome displays) to show the line number etc. and i was blown away by the performance of the esp32
Yes good idea to test where the bottle neck is. Also If there isn't enough memory to store the decompressed gif, try decompressing only 1....or 2...or 3. You could double the frame rate if only 2 were pre-decompressed(?).
Great Video, i was watching your other TFT videos, and have question, Any posibilities to run 2 x TFT on esp32 c3 super micro Pcb board, also i am truing to find Pin Assignment in your code, no lack.
CS PIN15 is always active - i need to touch pin15 with other CS PIN after ESP is turned on to see animation on screen (bout only one at the time works)
It's even more amazing that we can connect wifi between the esp32 and the phone to change many different gif images through the esp32's web server, can you guide me? thank you
One question, is there a way to modify the code, so that the screens have a power delay between them? For example, that the first 2 turn on normal and the rest turn on 10 seconds later? I appreciate it, this video has teach me a lot. I have learned a lot from it!
Thank you, I do not think you can have power control, meaning control the voltage supply on the screens. But you can add a simple delay() function to delay the gif playing on the screens
Je vais t'checker tes vidéos de proche! Je suis en train de (re)faire mes fichiers 3D pour imprimer un blaster DL-21 (Star Wars) et je voulais lui rentrer un écran rond dans le scope un 2e carré dans le body! En plus des piou-piou et d'une DEL qui pourrait flasher fort dans le canon. Aaaaanyway... Lâche pas la patate!
You are my hero - I managed to get two displays to work, thank you so much! I have a question please: Can you tell me how to make the GIF animation slower? If I put in more frames, the gif gets too big... But I need it to be slower - can you tell me which parameter in the code to change? Thank you so much!
Hello, I am your fan. I used your code using esp32 dev module on 30pin. But why does the gif change very quickly on one LCD and the other LCD does not respond? What is the reason??
Yes, all other pins are the same, and only cs pins are applied differently. Use only 1 "gc9a01" >> 6 gif files to convert quickly Use only two "gc9a01" >>>>>"gc9a01" in number 2 fixed output one fixed gif image, but the first "gc9a01" quickly changes six gifs..@@thelastoutpostworkshop
Can you try splitting it across two SPI buses? I’m not super knowledgeable about this, but you are sending all the data down a single serial bus rather than paralleling the data transmission. I’m assuming there’s a time cost involved in the whole chip selection function.
I have a question for you! I run the 6 screens and everything runs good! I want to use a tft display gc9107 T-0.85 from lilygo, the first screen runs goog but to fast on 100 fps, when I add the second display the code upload good but the screen blocks and the serial monitor shows error! Do I need to modify the code for this displays?
It appears not supported directly by the TFT_espi library, here is the comment by the developer of the library : The module seems to have a new display controller type GC9107. This appears to have the same commands and register init values as the GC9A01 but has different offsets since not all the pixel capability is used. I think this ideally needs another driver file set to avoid confusion. e.g. #define GC9107_DRIVER. This is simple to implement and I may be able find time to update the library the near future. In the meantime I see you have a solution.
Sorry for the delay. I fix the problem on the serial monitor. Now for some reason I want to run different displays with a different driver, (st7735 128x128) But only run the 1st display and don't want to run the other ones. Do I need to configure something on the code maybe?
First make sure your display is supported by the TFT_eSPI library and a driver is provided for your display. Next you will have to make some adjustments to the code to adapt to a 230x320 pixels screen. You also need to make sure you have enough memory. Start with one screen at a time.
Waiting part2...!! Get help from all smart programmers in order to let second core participating in the decoding process and use all available hardware to its limit to transfer data.
SPI communication has no defined speeds the way I2C does and can easily handle 10mbps. So, it's definitely the EPS32's limitations causing the framerates.
depends, clock is limiting factor, esp32 can handle up to 80mhz clock, in his test clock is probbably in range from 20-40MHz. Using DMA it can be even faster
Assuming 16 bit pixels and full display updates, it's already running at least 30Mbps. The ESP32 should be capable of 80Mbps (but the breadboard won't be), and the displays could be optimized by using D/C as data, not writing the corner regions, not writing static regions, and perhaps using a different colour depth. Sadly this display board lacks the TE line to prevent tearing.
@@andraznovak6735 you dont convert gifs to header files, you use decompressor library (AnimatedGIF in this case) to process gif binary and library outputs pixels while it decodes gif blocks within that binary
You can convert arbitrary data to in memory data using objcopy. A similar process was done here to build header files, they're just hex dumps in C format. One tool to do this is xxd -include. This is the method (though not exact tool) of delivering the GIF data to the AnimatedGIF routines in this project, so halollisimo was mistaken. As long as the data is constant the ESP32 can store it in flash memory; that's why it uses const and PROGMEM.
Hello: thank you for this video tutorial. I have tried assembling according to the video here, using 2 TFT screens to display gif animations gif_1 and gif_2. The result displayed on the screens shows one screen perfectly, but on the second screen, the animations appear overlapped (gif_1 and gif_2 animations appear simultaneously). Please kindly provide information on what needs to be fixed. The program code is as follows: #include #include #include "AnimatedGIF.h" // Examples images #include "images/hyperspace.h" #include "images/hud_6.h" //#include "images/nostromo.h" //#include "images/hud_1.h" //#include "images/hud_2.h" //#include "images/hud_5.h" //#include "images/hud_7.h" //#include "images/darthvader.h" //#include "images/x_wing.h" //#include "images/bb8.h" // Adjust this value based on the number of displays const int NUM_DISPLAYS = 2; // Add more CS pins if you have more displays, each display must have a dedicated pin const int CS_PINS[NUM_DISPLAYS] = { 15, 22 }; int currentScreenIndex = 0; AnimatedGIF gif_1; AnimatedGIF gif_2; //AnimatedGIF gif_3; //AnimatedGIF gif_4; //AnimatedGIF gif_5; //AnimatedGIF gif_6; TFT_eSPI tft = TFT_eSPI(); unsigned long lastFrameSpeed = 0; void setup() { Serial.begin(115200); tft.init(); for (int i = 0; i < NUM_DISPLAYS; i++) { pinMode(CS_PINS[i], OUTPUT); digitalWrite(CS_PINS[i], LOW); // select the display tft.fillScreen(TFT_BLACK); tft.setRotation(2); // Adjust Rotation of your screen (0-3) digitalWrite(CS_PINS[i], HIGH); // Deselect the display } openGif(&gif_1, hyperspace, sizeof(hyperspace)); openGif(&gif_2, hud_6, sizeof(hud_6)); //openGif(&gif_3, nostromo, sizeof(nostromo)); //openGif(&gif_4, x_wing, sizeof(x_wing)); //openGif(&gif_5, hud_2, sizeof(hud_2)); //openGif(&gif_6, bb8, sizeof(bb8)); } void loop() { playGif(&gif_1, 0); playGif(&gif_2, 1); //playGif(&gif_3, 2); //playGif(&gif_4, 3); //playGif(&gif_5, 4); //playGif(&gif_6, 5); } void openGif(AnimatedGIF *gif, const uint8_t *gifImage, int gifSize) { gif->begin(BIG_ENDIAN_PIXELS); if (!gif->open((uint8_t *)gifImage, gifSize, GIFDraw)) { Serial.printf("Could not open gif "); } } void playGif(AnimatedGIF *gif, int screenIndex) { currentScreenIndex = screenIndex; int res = gif->playFrame(false, NULL); if (res == 0) { // If no more frames are available, reset the GIF to the beginning gif->reset(); gif->playFrame(false, NULL); } if (res == -1) { Serial.printf("Gif Error = %d on screen %d ", gif->getLastError(), screenIndex); } if (screenIndex == 0) { if (lastFrameSpeed == 0) { lastFrameSpeed = millis(); } else { Serial.printf("Screen 0 FPS=%f ", 1000.0f / (millis() - lastFrameSpeed)); lastFrameSpeed = millis(); } } } Thank you. PS : when I disconnect the CS wires from pin 15 and 22, and restarted the esp32, then screen still can display the gif animation. but the 1st and 2nd screen appear overlapping animations ( gif_1 and gif_2 appear on the same time ). Pin connection : MOSI : 23 CLK : 18 CS : 15 and 22 DC : 2 RST : 4
If you see overlapping animation, it's a problem with CS pins. First thing make sure the GIFDdraw function has these lines at the beginning : digitalWrite(CS_PINS[currentScreenIndex], LOW); // Select the display tft.startWrite(); and these lines at the end of the function : tft.endWrite(); digitalWrite(CS_PINS[currentScreenIndex], HIGH); // Deselect the display Also make sure you can safely use pins 15 and 22 on your ESP32 development board. Try using other pins for CS.
@@thelastoutpostworkshop Hello Sir : Thank you for your reply. Highly apapreciated. Problem solved. I changed the cs pins. The Gifdraw function already has the command function as you wrote before. Thank you so much. Best regards, Samuel
Can you make the eye size? ruclips.net/video/Ke1SJ8-6zJw/видео.html Because you have a video tutorial about the eye but it is not as big as above thank you
SPI screens are notably slow. These screens are 240x240 pixels at 16 bit, so each frame is 115200 bytes of RAW data. If you clock the SPI at 40Mhz you can transfer a maximum of 4.8Mbps, that's 43 frames per second without taking in account the commands for the transfer (those are not much, but they count) and the delay between transfers. Then you need to add that while you are transferring data you are blocking the cores, so at the end you get those ~24fps with one single screen. To achieve maximum performance you can use DMA, the second core and a double buffer: in the first core you decode one frame, signal the second core to transfer that buffer, the second core prepares the DMA and triggers the transfer, meanwhile the first core starts decoding the next frame in the second buffer and so on, with this you remove any delay between transfers and maximize the time the first core can work in decoding frames. In fact the first core will end decoding a lot faster than the DMA transfer to the screen so you will need to synchronize the cores and ensure that the DMA transfer has finished before signaling the start of a new transfer.
Thanks a lot for the explanation!
Good explanation... except these screens are not SPI.
They are I2C... which is even slower than SPI by orders of magnitude.
@@Psirust They are SPI, you can check the datasheet, the controller is a GC9A01
@@drgusman My apologies. I stand corrected.
I just checked and it is indeed SPI. Usually SPI is labelled with MOSI, MISO, CS and CLK, however, the labelling on the pins give the appearance of I2C with SDA and SCL.
@@Psirust Yeah, I know, I don't know why but these chinese manufacturers this days tend to put SDA and SCL instead of MOSI and CLK in that type of screen even if it's SPI, the only good way to discern it is to check if there is a CS line, posibly they have no clue on what they're building... xD
Would be great to see how to use lvgl or similar to create a fluid ui with for example smooth scroll and page transition animations.
The ESP has 2 x SPI: HSPI and VSPI. You can use the first SPI with the first core and the second SPI with the second core. This should cut down on latency. You can also try other animated-GIF-like formats, such as APNG, WebP, AVIF, MNG and FLIF, to see if they lower your processing overhead.
GIFs have always been an extremely compute intensive format. Those sites where back in the day you could download animated emojis from would have your desktop CPU running at 100%.
The smoothest animations I've seen so far on the ESP32 are from 'Lottie'. No idea how easy or hard it is to get running though.
It's possible to run those animations on esp32 with espidf only. That project RUclips channel has a video on it. I haven't seen it on Arduino ide yet.
Well Gif's themselves not really. But animated GIF's run an uncompiled script that displays an image after decoding it for a specific amount of time and converting each frame to modern graphics is a lot of programming. It is an obsolete format for really old computers that is so taxing because of its obsolesence.
I’ve been doing a few screen based projects lately involving esp32’s and screens, and memory management has been a real struggle. But Incase it matters, on top of confirming what others have said, (I’ve yet to have any problems with spi at 40mhz, and atleast on the S3 chip 80mhz has been pretty happy too), if this still turns out to be insufficient remember that on top of having two cores and command queue capabilities, you also have 2 hardware spi buses, HSPI and VSPI, so you could split the screens 3+3 and cut the bandwidth toll in half.
You can go wider than that. It's not obvious from the name, but the I2S 0 peripheral has an LCD mode allowing you to DMA 8, 16 or 24 bits wide, and the SPI devices support 2 bit DIO and 4 bit QSPI transfers. It's not RP2040 level, but quite capable if you get a little hacky.
It's likely this program would benefit from putting the decompression routine in RAM, so it won't get evicted from cache during data reads. After that, verify the program is double buffering correctly, and then run two processors.
The LCD driver chip (GC9A01) also supports 2 bit SPI, which would be SPI_TRANS_MODE_DIO in the ESP32 SPI.
Awesome Experiment. Thank you
. Please more of that!
I'm not sure what the default is for TFT_eSPI, but you may be able to bump up the communication speed as well. 40MHz is usually pretty stable with an esp32, and I've had some luck with 80MHz as well, although it won't help much if the bottleneck is in managing the gifs themselves, and not the transfer rate
I would give it a try!
The default appears to be 27MHz SPI clock, which combined with partial updates and 16 bits per pixel gives a theoretical limit of about 1/(6*240*240*16 bit / 27Mbit/s) * 4/pi ≈ 6.21 fps. Combine this with how the decoder can't run more than one or two lines ahead, and it looks like this is a relevant bottleneck.
The ESP32 documentation hints that 27MHz might be the limit when going through the GPIO matrix, but using tightly coupled IO_MUX pins can reach 80MHz.
For extra fun, it appears the dual data serial mode has a different bit order in the ESP32 and display controller, so the palette format would need to be rearranged.
It would be great to see the sequence of the plans that Leia gives to R2 on how to destroy the Death Star
The power consumption part not correct. You just checked the absolute max io current of the ESP chip itself. 1: you should never reach absolute max. There is a recommended max value in the datasheet. 2: IO pin and power pin is not the same. You are not powering the screen from an IO pin but from the 3.3V regulator on the board. So you should check the datasheet of the LDO not the ESP32. 3: the current draw that you measured is on the 5V USB rail, but your screen is powered from 3.3V. If there is a linear regulator then the current is roughly the same. But if you have a switching mode PSU then the 3.3V current is like 5/3.3 = 1.5 times more then the measured on 5V.
Yes you’re right! Thanks for letting me know
Yeah if I remember correctly the 3.3v regulator is rated to 500ma. Tho I might be confusing the 8266 and 32
interesting thing about GIF decoding is that decoding speed tightly depends on content you have in your GIF, so it means that if your GIF frame has lots of different pixels, wide palette (but it will still be limited to 256 color palette i think) - decoding rate will be slow because decompressor output might redraw large portion of screen, but if your GIF frame has, say, text characters appearing on black background (like that console animation) - frame rate will be high because decompressor will only give you "parts that have changed since last frame", if i understand the process correctly. there is also separate song and dance around transparency handling, to do proper which you need a large framebuffer, but you should be good if your gif does not use transparency pixels
Yes you are right, all this come into play and a large frame buffer is indeed needed which is a major limitation on microcontroller
Decompress once and store the decompressed data. Then just send data[frame++]. No more bottle neck in esp32.
Honestly I think that the mirroring is caused by all the displays reading the same data.. since they are in parallel and you wanted only to play the gif on the first display anyway, i think there was a error in the code that pulled all CS pins active, therefore every display read the data.. imho the real limit is the spi bus, because with every display you need to send more data through the same bus.. maybe try just blinking the LCD from black to white and see the limit.. you will bypass delay with reading the gif and measure the real bandwith to the display.
btw i'm also working on a project with esp32, i'm making a led bus panel (using P10 monochrome displays) to show the line number etc. and i was blown away by the performance of the esp32
Thanks for your suggestion you gave me ideas to look into it
Yes good idea to test where the bottle neck is.
Also
If there isn't enough memory to store the decompressed gif, try decompressing only 1....or 2...or 3. You could double the frame rate if only 2 were pre-decompressed(?).
Excellent video and great information thanks for sharing
Awesome ! I want to make one into an oscilloscope with dual display (data and clock )
Great Video, i was watching your other TFT videos, and have question, Any posibilities to run 2 x TFT on esp32 c3 super micro Pcb board, also i am truing to find Pin Assignment in your code, no lack.
Seek this video where I run two TFT with ESP32 including how to connect the pins and configure the driver : ruclips.net/video/pmCc7z_Mi8I/видео.html
I think it would be great if you could make a digital version of the nixie clock on these displays or a simple digital clock using images
thanks man, very inspiring
CS PIN15 is always active - i need to touch pin15 with other CS PIN after ESP is turned on to see animation on screen (bout only one at the time works)
Isn't the last example just broadcasting the same image to all screens, therefore only using 1/6 of the bandwidth?
Maybe I but I am not sure
It's even more amazing that we can connect wifi between the esp32 and the phone to change many different gif images through the esp32's web server, can you guide me? thank you
One question, is there a way to modify the code, so that the screens have a power delay between them? For example, that the first 2 turn on normal and the rest turn on 10 seconds later? I appreciate it, this video has teach me a lot. I have learned a lot from it!
Thank you, I do not think you can have power control, meaning control the voltage supply on the screens. But you can add a simple delay() function to delay the gif playing on the screens
@thelastoutpostworkshop that's awesome 👌 but how to add the delay on the ino code?
Je vais t'checker tes vidéos de proche!
Je suis en train de (re)faire mes fichiers 3D pour imprimer un blaster DL-21 (Star Wars) et je voulais lui rentrer un écran rond dans le scope un 2e carré dans le body!
En plus des piou-piou et d'une DEL qui pourrait flasher fort dans le canon.
Aaaaanyway... Lâche pas la patate!
Hi, thanks for the video!
Just one queation, is it possible to use bigger screens, such as a 3" circular display?
I did not see round screen larger available on the market, if I happen to see one, I will try it
Hey I Need Help Im Stuck Anyone Know The SPI Pins On The ESP32-C6 Perchance?. I Cant Get Mine To Display Jack Squat On A GC9A01 Display!!!?.😭😭
You are my hero - I managed to get two displays to work, thank you so much! I have a question please: Can you tell me how to make the GIF animation slower? If I put in more frames, the gif gets too big... But I need it to be slower - can you tell me which parameter in the code to change? Thank you so much!
You can change the first parameter of this function to true : gif->playFrame(true, NULL);
or you can a a delay() between each frame.
@@thelastoutpostworkshop THANK YOU, IT WORKS!!! OMG!! :D
can you please explain how to assign CS pins through the code?
There is an explanation in this video : ruclips.net/video/zBzIBRsckTw/видео.html
@@thelastoutpostworkshop thank you so much! i have been trying to figure this out for so long. i actually followed your sd card one.
I have modified it by reading the gif on a micro SD and using 2 tft displays, it has succeeded but I have a problem with the fps dropping
Micro SD card is too slow, consider transferring the GIFs into memory before playing them
Hello, I am your fan.
I used your code using esp32 dev module on 30pin.
But why does the gif change very quickly on one LCD and the other LCD does not respond? What is the reason??
Thank you! Is the other LCD on the same SPI bus and with a different CS pin than the first ?
Yes, all other pins are the same, and only cs pins are applied differently.
Use only 1 "gc9a01" >> 6 gif files to convert quickly
Use only two "gc9a01" >>>>>"gc9a01" in number 2 fixed output one fixed gif image, but the first "gc9a01" quickly changes six gifs..@@thelastoutpostworkshop
Can you try splitting it across two SPI buses? I’m not super knowledgeable about this, but you are sending all the data down a single serial bus rather than paralleling the data transmission. I’m assuming there’s a time cost involved in the whole chip selection function.
In my experimentation, the cost involved in chip selection is negligible vs the cost of reading and decompressing the GIFs for each frame
I have a question for you! I run the 6 screens and everything runs good!
I want to use a tft display gc9107 T-0.85 from lilygo, the first screen runs goog but to fast on 100 fps, when I add the second display the code upload good but the screen blocks and the serial monitor shows error!
Do I need to modify the code for this displays?
It appears not supported directly by the TFT_espi library, here is the comment by the developer of the library : The module seems to have a new display controller type GC9107. This appears to have the same commands and register init values as the GC9A01 but has different offsets since not all the pixel capability is used. I think this ideally needs another driver file set to avoid confusion. e.g. #define GC9107_DRIVER. This is simple to implement and I may be able find time to update the library the near future. In the meantime I see you have a solution.
What are the errors you get on the serial monitor ?
Sorry for the delay. I fix the problem on the serial monitor.
Now for some reason I want to run different displays with a different driver, (st7735 128x128)
But only run the 1st display and don't want to run the other ones. Do I need to configure something on the code maybe?
how do i get my 240x320 tft display esp32 to display gifs? im a complete novice
First make sure your display is supported by the TFT_eSPI library and a driver is provided for your display. Next you will have to make some adjustments to the code to adapt to a 230x320 pixels screen. You also need to make sure you have enough memory. Start with one screen at a time.
Waiting part2...!! Get help from all smart programmers in order to let second core participating in the decoding process and use all available hardware to its limit to transfer data.
SPI communication has no defined speeds the way I2C does and can easily handle 10mbps. So, it's definitely the EPS32's limitations causing the framerates.
Thanks for the explanation
depends, clock is limiting factor, esp32 can handle up to 80mhz clock, in his test clock is probbably in range from 20-40MHz. Using DMA it can be even faster
Assuming 16 bit pixels and full display updates, it's already running at least 30Mbps. The ESP32 should be capable of 80Mbps (but the breadboard won't be), and the displays could be optimized by using D/C as data, not writing the corner regions, not writing static regions, and perhaps using a different colour depth. Sadly this display board lacks the TE line to prevent tearing.
Could the program itself be doing suboptimal processing for such a task? (Sorry, im a software guy 😂)
Yes the program is not optimal, there are constraints introduced to minimize memory allocation
But these are just reading the bitmaps from memory and don't have to do any decoding, right?
They have to be decoded because the bitmaps would be much too large for the memory of the ESP32
@@thelastoutpostworkshop How do you convert gifs to header files?
@@andraznovak6735 you dont convert gifs to header files, you use decompressor library (AnimatedGIF in this case) to process gif binary and library outputs pixels while it decodes gif blocks within that binary
You can convert arbitrary data to in memory data using objcopy. A similar process was done here to build header files, they're just hex dumps in C format. One tool to do this is xxd -include. This is the method (though not exact tool) of delivering the GIF data to the AnimatedGIF routines in this project, so halollisimo was mistaken. As long as the data is constant the ESP32 can store it in flash memory; that's why it uses const and PROGMEM.
Gives us an insight into the graphical capability of the ESP32.
Looks nice.
It does!
Hello: thank you for this video tutorial.
I have tried assembling according to the video here, using 2 TFT screens to display gif animations gif_1 and gif_2. The result displayed on the screens shows one screen perfectly, but on the second screen, the animations appear overlapped (gif_1 and gif_2 animations appear simultaneously).
Please kindly provide information on what needs to be fixed.
The program code is as follows:
#include
#include
#include "AnimatedGIF.h"
// Examples images
#include "images/hyperspace.h"
#include "images/hud_6.h"
//#include "images/nostromo.h"
//#include "images/hud_1.h"
//#include "images/hud_2.h"
//#include "images/hud_5.h"
//#include "images/hud_7.h"
//#include "images/darthvader.h"
//#include "images/x_wing.h"
//#include "images/bb8.h"
// Adjust this value based on the number of displays
const int NUM_DISPLAYS = 2;
// Add more CS pins if you have more displays, each display must have a dedicated pin
const int CS_PINS[NUM_DISPLAYS] = { 15, 22 };
int currentScreenIndex = 0;
AnimatedGIF gif_1;
AnimatedGIF gif_2;
//AnimatedGIF gif_3;
//AnimatedGIF gif_4;
//AnimatedGIF gif_5;
//AnimatedGIF gif_6;
TFT_eSPI tft = TFT_eSPI();
unsigned long lastFrameSpeed = 0;
void setup() {
Serial.begin(115200);
tft.init();
for (int i = 0; i < NUM_DISPLAYS; i++) {
pinMode(CS_PINS[i], OUTPUT);
digitalWrite(CS_PINS[i], LOW); // select the display
tft.fillScreen(TFT_BLACK);
tft.setRotation(2); // Adjust Rotation of your screen (0-3)
digitalWrite(CS_PINS[i], HIGH); // Deselect the display
}
openGif(&gif_1, hyperspace, sizeof(hyperspace));
openGif(&gif_2, hud_6, sizeof(hud_6));
//openGif(&gif_3, nostromo, sizeof(nostromo));
//openGif(&gif_4, x_wing, sizeof(x_wing));
//openGif(&gif_5, hud_2, sizeof(hud_2));
//openGif(&gif_6, bb8, sizeof(bb8));
}
void loop() {
playGif(&gif_1, 0);
playGif(&gif_2, 1);
//playGif(&gif_3, 2);
//playGif(&gif_4, 3);
//playGif(&gif_5, 4);
//playGif(&gif_6, 5);
}
void openGif(AnimatedGIF *gif, const uint8_t *gifImage, int gifSize) {
gif->begin(BIG_ENDIAN_PIXELS);
if (!gif->open((uint8_t *)gifImage, gifSize, GIFDraw)) {
Serial.printf("Could not open gif
");
}
}
void playGif(AnimatedGIF *gif, int screenIndex) {
currentScreenIndex = screenIndex;
int res = gif->playFrame(false, NULL);
if (res == 0) {
// If no more frames are available, reset the GIF to the beginning
gif->reset();
gif->playFrame(false, NULL);
}
if (res == -1) {
Serial.printf("Gif Error = %d on screen %d
", gif->getLastError(), screenIndex);
}
if (screenIndex == 0) {
if (lastFrameSpeed == 0) {
lastFrameSpeed = millis();
} else {
Serial.printf("Screen 0 FPS=%f
", 1000.0f / (millis() - lastFrameSpeed));
lastFrameSpeed = millis();
}
}
}
Thank you.
PS :
when I disconnect the CS wires from pin 15 and 22, and restarted the esp32, then screen still can display the gif animation. but the 1st and 2nd screen appear overlapping animations ( gif_1 and gif_2 appear on the same time ).
Pin connection :
MOSI : 23
CLK : 18
CS : 15 and 22
DC : 2
RST : 4
If you see overlapping animation, it's a problem with CS pins. First thing make sure the GIFDdraw function has these lines at the beginning : digitalWrite(CS_PINS[currentScreenIndex], LOW); // Select the display
tft.startWrite();
and these lines at the end of the function : tft.endWrite();
digitalWrite(CS_PINS[currentScreenIndex], HIGH); // Deselect the display
Also make sure you can safely use pins 15 and 22 on your ESP32 development board.
Try using other pins for CS.
@@thelastoutpostworkshop Hello Sir : Thank you for your reply. Highly apapreciated.
Problem solved. I changed the cs pins. The Gifdraw function already has the command function as you wrote before. Thank you so much.
Best regards,
Samuel
nice
very nice!!
Try this on a Teensy 4.1 - 600mhz speed, ability to increase ram to 8 and even 16mb using PSRAM chips and 3 SPI bus lines!
Thanks for the suggestion, I will try it
4mb Ram? it does have 512kb ram i think? and 4mb flash ....
Thats awesome this is exactly what i need but only with 5 screen 👏
with 6 screens, you can build an electronic dice
Nice idea!
your english is cookie.
nice
Can you make the eye size? ruclips.net/video/Ke1SJ8-6zJw/видео.html Because you have a video tutorial about the eye but it is not as big as above thank you
Esp32-s3 should perform better
of course it do not work :(