ESP32 (25) – Oled display with U8G2

by luca

If you read my post ESP32, Wemos or not to Wemos you know that I brought a development board, that happened to be a D-duino-32 clone, with an ESP-WROOM-32 module and a 0.96″ oled display.

This display, available also as a standalone module on several websites (for example on Banggood), has the following features:


  • size: 0.96 inches
  • resolution: 128×64 pixels
  • controller: SSD1306 with I2C interface
  • power supply: 3.3V – 6V


u8g2-00a u8g2-00b

It’s very easy to interface it with the esp32 chip thanks to the work of olikraus and Neil Kolban. The first wrote the u8g2 library, while the second implemented the specific functions of the u8g2’s hardware abstraction layer (HAL) for the esp32.

u8g2, installation

u8g2 is a fantastic library for monochrome displays: it supports several types of displays and controllers, it’s easy to port to new platforms and offers many methods to draw geometric figures, display images and write strings using different fonts.

Let’s learn how to use it in your project. First download the archive with the content of the library’s Github repository:


If it doesn’t exist, create the components folder in the main folder of your project. Unzip the archive into that folder and rename the subfolder u8g2-master in u8g2:


In the u8g2 folder create a file named with the following content:


Now download the files u8g2_esp32_hal.c and u8g2_esp32_hal.h from nkolban’s repository:


You can copy the two files in the main folder of your project:


u8g2, configuration

To use the u8g2 library in your program, first include the header file:

#include "u8g2_esp32_hal.h"

The HAL configuration is stored in the u8g2_esp32_hal_t struct:

typedef struct {
  gpio_num_t clk;
  gpio_num_t mosi;
  gpio_num_t sda;
  gpio_num_t scl;
  gpio_num_t cs;
  gpio_num_t reset;
  gpio_num_t dc;
} u8g2_esp32_hal_t;

The library supports both I2C and SPI displays: this is the reason why you see in the struct fields related to the two buses.

You can define and initialize the struct with default values with:

u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;

The oled display of the D-duino-32 board has an I2C interface connected to esp32’s pin 4 (SCL) and 5 (SDA):

u8g2_esp32_hal.sda = 5;
u8g2_esp32_hal.scl = 4;

When the configuration of the struct is complete, you can use the u8g2_esp32_hal_init() method:


Now move to the configuration of the u8g2 library. Define an u8g2_t variable:

u8g2_t u8g2;

Based on the display you’re using, you have to choose the correct setup function. The parameters for the function are:


  • the pointer to the u8g2_t variable you defined before
  • a constant value that specifies the display rotation
  • two HAL functions to send data on the bus and to delay


The constants for the display roation are:


and the two HAL functions developed by Kolban are:

  • u8g2_esp32_i2c_byte_cb
  • u8g2_esp32_gpio_and_delay_cb

Here I’m using the setup function for the ssd1306 “noname” controller with the _f prefix that means full framebuffer:

  &u8g2, U8G2_R0,
full framebuffer means that all the data to send to the display are stored in the RAM memory of the microcontroller. This makes easier and faster to work with the display but consumes more RAM. The u8g2 library also supports a page buffer mode to save some memory. A comparison between the different modes, with pros and cons, is available on the library’s wiki.

Finally – if you’re using an I2C display – you have to specify its address (here 0x78):


u8g2, use

After the setup, initialize the display with:


The display is now in power save mode, to “turn it on” you have to disable this mode with:

u8g2_SetPowerSave(&u8g2, 0);

Now you can call the different methods available to display text, images, shapes. If you’re using the full framebuffer mode, first prepare the buffer in memory and then send it to the display.

Prepare an empty buffer with ClearBuffer():


Now for example use the SetFont() and DrawStr() methods to write a string into the buffer with a specific font:

u8g2_SetFont(&u8g2, u8g2_font_timR14_tf);
u8g2_DrawStr(&u8g2, 2,17,"Hello World!");

and finally display the buffer’s content on the display with:




In the following video I quickly explain how to install the library, how to prepare an image to be displayed and in the end you can see the execution, on my D-duino-32, of the example program available on Github.

[youtube id=”sbCcsiIsQKc” width=”600″ height=”350″]

Related Posts


Jabes Cândido da Silva Wednesday March 28th, 2018 - 04:53 PM

Hi, congratulations on the explanations. I’m testing this example with a heltec module, and am having the following error at compile time:

C:/msys32/home/jabes/esp-idf/examples/lucca_exemplos/esp32-tutorial-master/18_u8g2/main/u8g2_esp32_hal.c:79:14: error: ‘spi_transaction_t {aka struct spi_transaction_t}’ has no member named ‘command’
trans_desc.command = 0;
make[1]: *** [/home/jabes/esp-idf/make/ u8g2_esp32_hal.o] Error 1
make: *** [C:/msys32/home/jabes/esp-idf/make/ component-main-build] Error 2

What do you think it can be?

luca Thursday May 3rd, 2018 - 01:35 PM

Hi, ESP changed something in the framework… you should use the updated version of the u8g2 hal

Claudio Ferronetti Monday May 21st, 2018 - 07:25 PM

Ciao, più o meno stesso errore. Non ho trovato aggiornamenti di u8g2_hal. Ho un ESP32-DEVKITC ESP32 Core Board V2 e l’unica modifica al progetto è stato cambiare i PIN SDA e SCL (21-22)

luca Sunday June 17th, 2018 - 02:13 PM

ciao, ho aggiornato l’articolo con la nuova versione del HAL, compatibile con il framework v3

Mauro Thursday July 26th, 2018 - 04:47 PM

Ciao Luca blog stupendo, ho provato questo esempio su una scheda wemos con Oled integrato come quello che compare nel video. Ho cambiato l’indirizzo a 0x3c come indicato dal venditore ma quando va in esecuzione continua a fare dei reboot continui.
L’ultima riga prima di riavviarsi scrive: u8g2_esp32_hal.c”, line 158, function: u8g2_esp32_i2c_byte_cb
abort() was called at PC 0x400d247b on core 0

Ho aggiornato tutto all’ultima versione.


Aniket R Udare Sunday December 2nd, 2018 - 05:07 AM

Did you get any solution to this?

Brent Brown Thursday September 20th, 2018 - 12:26 PM


Works after I make one change in your setup example from above…


Changed to:


Many thanks for the tutorial, from a first time OLED user~!

davide Friday November 16th, 2018 - 05:39 PM

Ciao Luca,
sto seguendo questo tuo tutorial, molto ben fatto, per riuscire a utilizzare la mia wemos lolin32 con isplay integrato.
Purtoppo sia dall’ide di arduino che da visual studio 2017 mi viene restituito lo stesso errore.
u8g2.h no such file or directory.

Questo probabilmente perchè la libreria non è installata nella cartella di default delle librerie arduino. Tuttavia se la sposto lì mi restituisce il medesimo errore ma su u8g2_esp32_hal.h

Come posso ovviare al problema?
Grazie mille

luca Saturday November 17th, 2018 - 05:01 PM

Ciao Davide, non usare Arduino ma il framework esp-idf “liscio”, vedrai che così funziona. Se invece vuoi usare Arduino, devi installare la libreria u8g2 dal Library Manager.

Aniket R Udare Sunday December 2nd, 2018 - 05:06 AM

I am facing the same problem as Mauro. I am using ESP32 by WEMOS which has build in OLED Screen.
I am getting the following error:
assertion “0 && “i2c_master_cmd_begin(I2C_MASTER_NUM, handle_i2c, I2C_TIMEOUT_MS / portTICK_RATE_MS)”” failed: file “D:/msys32/home/udare/18_u8g2/main/u8g2_esp32_hal.c”, line 158, function: u8g2_esp32_i2c_byte_cb
abort() was called at PC 0x400d295b

luca Friday December 7th, 2018 - 03:49 PM

Hi! Did you update the hal library?


Leave a Comment

1 × five =