ESP32-S3 devkit with display

in terms of performance os the ESP32-S3. It is exactly the same with respect to speed as the original ESP32. It has more pins and it has larger flash and psram availability to it over the esp32. The ESP32-S3 does have support for the RGB bus only if you use the driver that is included in the ESP-IDF. The ESP-IDF version that is used in the Arduino IDE is old and it doesn’t included the needed pieces to access the RGB bus driver in the ESP-IDF. So bitbang or hacking SPI are the only things that are going to allow it to work and there are performance losses for doing so.

1 Like

Thank you kdschlosser.
It’s why I didn’t get a better experience when tested ESP32S3 by Arduino IDE.
and worse when hooked ESP32S3 with a ST7789V the latter even can’t light up.

BTW. what “The Sonton ESP displays are RGB” means? is the “Sonton ESP " special?
what I used is just buy online ESP32 S3 and 1.69” TFT which used ST7789V.

And RGB display is kind of a misnomer. That term is not about the display itself it’s about the connection between the display and the driver IC that runs the display. It’s how the data gets transmitted to that driver IC. With an RGB bus the display IC doesn’t have any internal memory so in order for the display to work properly the buffer data has to be constantly streamed to the display. over and over again.

This is how it works out. say you are transmitting the data at 12Mhz that is 12,000,000 bits per second. Now that sounds like a lot right? It’s really not. with an RGB display that is using 16 lanes (16 pins connected to transfer the data) it is able to send 8 bits at a time in parallel. so lets do some quick math.

we assume an 800 x 400 display using 16 lanes so the color depth is RGB565 which is 2 bytes of data per pixel.

800 x 400 x 2 = 640,000 bytes of data.

There are 8 bits to a byte

640,000 x 8 = 5,120,000 bits.

Per the esp32 data sheet there is an interrupt time of 0.003094 seconds when doing a DMA transfer and if you are not using DMA there is no interrupt time because you have to wait until it is done sending, Polling is what that method is called. Polling incurs a 7us processing time for each transaction where as DMA transfers have a 21us processing time per transaction. The last piece is a polling transaction has a maximum size of 64 bytes per transaction where as on the esp32-s3 the maximum size per transaction is about 64,000 bytes when using DMA.

so this is what the math looks like

(transaction_time * (buf_size_bytes / max_trans_size)) + ((bits_to_byte * buf_size_bytes) / (frequency_in_hz * lane_count))

Lets plug in some numbers.

(2.1e-5 * (640,000 / 64,000)) + ((8 * 640,000) / (12,000,000 * 16)) = ~0.02688 seconds (~26.88 milliseconds)

That is what it would take in time to transmit a single frame over 16 lanes at 12MHz. How many of those can be sent in a single second…

1000 / 26.88 = 37.20 frames per second.

That’s not too bad, But that is only the time it takes to send the data, not to render it. It can easily take 7 to 12 milliseconds if doing a render where 1/2 the frame needs to be redrawn. lets call it 7 milliseconds…

26.88 + 7 = 33.88
1000 / 33.88 = 29.51

so now we are at 29.51 frames per second. If you then include needing to carry out other tasks at the same time like checking pin states and if you have to run any complex calculations that number is going to keep on falling. If you need to scroll and the entire screen needs to redraw then it starts getting expensive to do and the frame rate is going to be around 19 and then you take a hit for doing other things and now you are down to 10.

The ESP32 does have 2 cores to be able to do 2 things at the same time, problem is LVGL is not written to be thread safe so it’s not able to split the workload between 2 processes either.

A display that is 800 x 400 using an RGB bus at 16 bit color depth is not going to provide a nice user experience. The absolute maximum I would go on the ESP32 using an RGB bus with a very light workload for additional tasks would be a 480 x 320 display.

If you dive in really deep and you get everything using the 2 cores to their best it would give you 20 to 25 frames per second using DMA memory and 2 frame buffers.

There is another spot that could put you in a jam and that is the need to use the PSRAM for the frame buffer due to their size. If there is any code that has to access the PSRAM at the same time the buffer is being sent the data rates are going to drop. If there is one other thing accessing the memory the data rates are cut in half. The second core accesses the ram then you are down to 1/3rd of the transmission speed.

This is where you would use an I8080 interface. You get the 16 lanes. You can use DMA memory and double buffering. and the buffer sizes only need to be 1/10th the size thanks to the display IC having GRAM. The buffers also don’t have to be synced with each which means you can render to the second buffer while the first is being sent. The buffer sizes are also small enough so they can fit into sram which is a large amount faster. and the last thing is you can get a higher clock using I8080. 20MHz is pretty common.

High resolution displays using an RGB bus is not ideal if you want smooth UI transitions when using the ESP32.If you UI is being used for displaying sensor readings and there isn’t much in the way of user input it then you will do OK. You will achieve a better result using an I8080 bus if wanting smooth UI transitions and there is a lot of user input.

If at all possible I would steer clear of using the Arduino IDE. That because it doesn’t provide you with the display bus drivers that are going to run the best. I would not use any libraries to handle the transfers to the display. The code is not that hard to write so you are not using a framework other than the drivers in the ESP-IDF.

Here is an example of what the code would look like.