A wide range of displays is available for use with the Arduino system. For the WeMos D1 mini system I found 3 display boards. Each of them is based a on different controller chip and has different resolution. Here they are are:
64x48 pixels with SSD1306 | 128x128 with ST7735 | 320x240 pixel touch screen with ILI9341 |
![]() |
![]() |
![]() |
The 1.4" display is already quite a bit better even though 128x128 bit resolution is still not enough for sophisticated graphics. It is enough however to write a few lines of text and produce simple graphics, e.g. creating a graph of sensor readout results.
The 2.4" display is clearly the most powerful device, adding touch functionality. It is however so big that it is difficult to plug it onto the WeMos D1 bus, even if the connector is available. The better solution is an adapter board and a connecting cable.This display board also features a touch screen and is one of the boards supported by the lvgl Graphical User Interface (GUI) library.
Since the 1.4" display is enough for most our applications, it can be nicely plugged onto the bus just like any other sensor or actuator shield and it is substantially cheaper than the 2.4" solution, this is the device we chose for the course.
Before using the display its solder jumpers on the back must be configured. There are 4 solder fields for configuration
Searching the Internet I found many display drivers, none of which really satisfied me.
The first goal for our own driver was to be able to run all the demo programs on it. Since the calling sequences of the drivers are different (different method names, different way to pass parameters) some modifications to the demo code was of course necessary. In addition the method names and parameters defined in the framebuffer should be available.
Comparing the original ST7735 driver to the SSD1351 one we see the following differences
ST7735 | SSD1351 |
---|---|
clips drawing elements when they exceed display boundaries | drops drawing elements if any pixel would exceed display boundaries |
Provides 3 fonts as Python files | Provides many different fonts as C files These fonts must be loaded before use, which takes a long time |
uses .bmp files for images | uses binary rgb565 files for images |
does not support sprites | allows use of sprites |
Comes with 2 demo programs for graphics primitives and image display |
Comes with man demo programs, some of which are rather sophisticated Even supplies simple Arcade games |
Fonts are normally loaded into RAM before use. However, this takes time and uses a big amount of RAM memory, a very scarce resource on the standard ESP32. (We are using an ESP32 with additional PSRAM where the problem is much less critical).
Since font loading in the SSD1351 driver takes ages (the demo-font program using 9 different fonts took ~ 30s before the first character could be written. After that text writing was fast) I searched for another method and ended up asking the MicroPython forum. Peter Hinch sent me a link to his micropython-font-to-py git repository explaining how the font data can be kept in flash and you can nevertheless get fast access to the them. The fonts are implemented as Python source files providing not only the font data but also access routines to the pixel data. These font files can be frozen into MicroPython and are thus stored in flash. When a character is written, only the pixel data for this character is loaded into RAM.
The problem was now how to convert the font files in C supplied with the SSD1351 driver to Python font files compatible with micropython-font-to-py. I wrote a Python script:
https://afnog.iotworkshop.africa/pub/IoT_Course_English/TFTDisplay/convertFont.py.txt
doing exactly this. The output is actually executable (on the PC) and will print the pixel data of the letter "A" for this font.
Finally I copied the fonts into the modules/fonts directory of the MicroPython sources and froze them into the binary.
You can use the fonts by importing the MicroPython module:
from ST7735 import Display, color565 import fonts/sysfont as sysfont sck = Pin(18)
miso= Pin(19)
mosi= Pin(23)
SPI_CS = 26
SPI_DC = 5
spi = SPI(2, baudrate=32000000, sck=sck, mosi=mosi, miso=miso) display=Display(spi,SPI_CS,SPI_DC)
display.draw_text(0, 0, 'Hello World!', sysfont, color565(255, 0, 0))
In addition to font handling I received a link to micropython-nano-gui a lightweight and minimal MicroPython GUI library for display drivers based on the framebuf class. This library contains a few widgets to display sensor data and includes a plot library.
There are two different approaches to the display driver:
I now had:
I ended up writing a class with methods implementing both design principles. There is a method
Here are the methods:
These first methods write to the hardware directly
From my tests with the SSD1306 driver I had
Here are a few photos of some of the screen images
![]() |
![]() |
![]() |
This program is quite similar in nature as demo-ssd1306.py but produces slightly different graphics and it integrates a text writing demo in addition, where a long text is displayed, wrapped to the next line once the end of the line is reached. The text is displayed in portrait mode in green font color and in white when showing off text drawing in landscape mode.
Again a have a few photos for you:
![]() |
![]() |
![]() |
![]() |
Bouncing Boxes | Color squares | Color palette |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
In the list of demos for the SSD1351 driver you even find 2 simple video games:
Both games need additional hardware: a joystick in case of Super Mario and a linear potentiometer in the case of Arkanoid. demo-mario orriginally used a Bluetooth based joystick, which we don't have. I therefore replaced it with the analogue joystick from our sensor kit. Of course the software needed to be adapted correspondingly.
demo-mario | arkanoid |
![]() |
![]() |
Peter Hinch's nanogui library contains a few widgets that can be used to graphically display sensor results. Their number is fairly limited (that is why Peter calls it nanogui) but extensions are possible if needed. nanogui contains:
Here again some pictures
Clock | SHT30 meters | Voltmeter |
![]() |
![]() |
![]() |
The voltmeter meter application uses a Scale widget, not part of nanogui. Peter has supplied a superclass DObject (displayable object) from which the Scale widget is derived. The demo connects to the ESP32 ADC to display measured signal levels.
Peter's nanogui repository also contains a plotting package called fplot. This package allows to produce cartesian and polar plots to be generated. Particularly interesting is a feature that allows to add real time measurements to plots as they come in.
Again a few examples:
Cartesian Plot | Polar Plot | Damped Oscillator |
![]() |
![]() |
![]() |
I | Attachment | History | Action | Size | Date | Who | Comment |
---|---|---|---|---|---|---|---|
![]() |
convertFont.py.txt | r1 | manage | 8.6 K | 2020-07-21 - 11:26 | UliRaich | |
![]() |
font.png | r1 | manage | 2.7 K | 2020-07-21 - 09:22 | UliRaich | |
![]() |
img_7952.png | r1 | manage | 205.7 K | 2020-07-27 - 13:30 | UliRaich | |
![]() |
img_7958.png | r1 | manage | 211.5 K | 2020-07-27 - 14:03 | UliRaich | |
![]() |
img_7959.png | r1 | manage | 220.4 K | 2020-07-27 - 14:03 | UliRaich | |
![]() |
img_7960.png | r1 | manage | 238.6 K | 2020-07-27 - 14:03 | UliRaich | |
![]() |
img_7961.png | r1 | manage | 244.8 K | 2020-07-27 - 14:03 | UliRaich | |
![]() |
img_7964.png | r1 | manage | 238.0 K | 2020-07-27 - 13:48 | UliRaich | |
![]() |
img_7965.png | r2 r1 | manage | 241.3 K | 2020-07-27 - 13:42 | UliRaich | |
![]() |
img_7968.png | r1 | manage | 263.5 K | 2020-07-27 - 12:36 | UliRaich | |
![]() |
img_7972.png | r1 | manage | 245.8 K | 2020-07-27 - 13:03 | UliRaich | |
![]() |
img_7973.png | r2 r1 | manage | 236.6 K | 2020-07-27 - 13:05 | UliRaich | |
![]() |
img_7982.png | r1 | manage | 196.5 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_7984.png | r1 | manage | 221.3 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_7990.png | r1 | manage | 204.3 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_7994.png | r1 | manage | 187.9 K | 2020-07-27 - 12:36 | UliRaich | |
![]() |
img_7996.png | r1 | manage | 237.4 K | 2020-07-27 - 12:36 | UliRaich | |
![]() |
img_8000.png | r1 | manage | 231.5 K | 2020-07-27 - 13:30 | UliRaich | |
![]() |
img_8003.png | r1 | manage | 165.4 K | 2020-07-27 - 13:53 | UliRaich | |
![]() |
img_8014.png | r1 | manage | 227.4 K | 2020-07-28 - 12:03 | UliRaich | |
![]() |
img_8016.png | r1 | manage | 191.6 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_8020.png | r1 | manage | 204.1 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_8025.png | r1 | manage | 181.8 K | 2020-07-30 - 09:49 | UliRaich | |
![]() |
img_8026.png | r1 | manage | 402.3 K | 2020-07-30 - 09:54 | UliRaich | |
![]() |
img_8030.png | r1 | manage | 187.2 K | 2020-07-30 - 11:24 | UliRaich | |
![]() |
lolon2.4inch.png | r1 | manage | 218.8 K | 2020-07-04 - 09:45 | UliRaich | |
![]() |
ssd1306.png | r1 | manage | 158.9 K | 2020-07-04 - 09:44 | UliRaich | |
![]() |
tftJumpers.png | r1 | manage | 626.4 K | 2020-07-17 - 16:16 | UliRaich | |
![]() |
tftScreen.png | r1 | manage | 144.4 K | 2020-07-04 - 09:45 | UliRaich |