How to use the Heltec OLED display on the ESP32

Heltec is a Chinese company that makes all kinds of SoC (system on a chip) devices. Their ESP32-based SoCs appear to be solid quality, and they offer a few variants, including a LoRa WLAN chip for long range connectivity on a narrow band.

I bought a handful of the Heltec OLED WiFi kit chips so as to have a little display without the hassle of attaching a two-line LCD on the device, to see what’s happening in the system. I have a previous piece on how to use the LCD displays, in case you are interested (it features the Arduino but it works just as well on ESP32).

The installation of the Heltec brand chips is straightforward, because after installing the general support for ESP32, you can add Heltec as a library to the Arduino IDE. This generates the file Heltec.h into the Libraries folder, and that brings you all the functionality you need.

The code you see in this blog post is available on GitHub.

OLED features

OLED stands for Organic LED, and it is some sort of biomechanical sorcery or magick that brings up imaged on the 0.96″ screen. It is bluish in color. The resolution is 128 x 96 pixels, so this isn’t exactly HD, but for the use I have for this it is absolutely adequate. You can display strings or draw lines, boxes, circles, or images, if you work the images into the right size, and then export them into a file format called XBM, which is a text file actually. This is a nice tutorial on using XBM. Essentially your image pixels are turned into zeros and ones, put into an array, and displayed by the Heltec functionality as images. The images in XBM are contained in a header file called images.h.

Here’s a short video on how the OLED works.

OLED with custom images, booting

The Haaga-Helia logo on this boot sequence is created by taking the actual logo, scaling it down to 128 x 96 pixels, and then exporting it to a format like this:

In XBM code, it looks like this:

define hhlogo_width 128
define hhlogo_height 64
const unsigned char hhlogo_bits[] PROGMEM = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,

[I am cutting a bunch of these lines here, because as you can see, it merely defines 0xFF of the pixel is off and something else like 0x3C for pixels that are on.]

0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, };

When these bits are rendered in the device, you see the picture as in the image above.

The device is actually rather handy in drawing not only pixel images, but lines, boxes, and curves too. When you install the library, you get some sample files, and one of them shows all these features, namely SSD1306DrawingDemo.

The draw demo program

Let’s look at how the device draws things. In the Setup function, the device must be enabled:

Heltec.begin(true /DisplayEnable Enable/, false /LoRa Disable/, true /Serial Enable/);

After that, it can be asked to do all kinds of operations, all of which must be followed by


In effect, every operation is written into a buffer an when this line is issued, it actually displays the values. It was unclear to me at first that this display operation must be repeated often, but when you figure out that this is the actual show command, it’s easy enough. Its counterpart is the clear operation:


This does not for some reason erase every pixel every time, so sometimes you need to draw a black box in the entire screen to make sure everything goes away. This code draws an alternating black / white set of rectangles:

void fillRect(void) {
uint8_t color = 1;
for (int16_t i=0; isetColor((color % 2 == 0) ? BLACK : WHITE); // alternate colors
Heltec.display->fillRect(i, i, DISPLAY_WIDTH - i2, DISPLAY_HEIGHT - i2);
// Reset back to WHITE

So, in essence, it is very easy to work with this display. The main commands you will use are

Heltec.display->drawLine(start-x, start-y, end-x, end-y);
Heltec.display->drawRect(topcorner-x, topcorner-y, 
bottomcorner-x, bottomcorner-y); //open rectangle
Heltec.display->fillRect(topcorner-x, topcorner-y,
bottomcorner-x, bottomcorner-y); //filled rectangle
Heltec.display->drawCircle(center-x, center-y, radius) //circle

Heltec.display->drawString(0, 0, "Hello world"); //this is of course one of the main methods, writing text on the screen

Heltec.display->setColor(WHITE); //color to use

This set of commands will take you far. The video below shows an analog clock in operation. It draws a circle, and then inside it, three likes with the same origin and differing lengths:

float xsec = arc_second * sin(analogSec * 6 * PI / 180); // Second needle TIP position, arc=needle length
float ysec = arc_second * cos(analogSec * 6 * PI / 180);
float xmin = arc_minute * sin(analogMin * 6 * PI / 180); // Minute needle TIP position, arc=needle length
float ymin = arc_minute * cos(analogMin * 6 * PI / 180);
float xhour = arc_hour * sin(hourDegrees * PI / 180); // Hour needle TIP position, arc=needle length
float yhour = arc_hour * cos(hourDegrees * PI / 180);
Heltec.display->drawCircle(x_origo, y_origo, 31);
Heltec.display->drawLine(x_origo, y_origo, x_origo + xsec, y_origo - ysec); //Second hand
Heltec.display->drawLine(x_origo, y_origo, x_origo + xmin, y_origo - ymin); //Minute hand
Heltec.display->drawLine(x_origo, y_origo, x_origo + xhour, y_origo - yhour); //Hour hand

You can learn more of the use of Heltec in the ESP32 UDP – Android application posts, of which a three part blog entry is being written and will be published as soon as I get them done.

Analog clock on Heltec

This analog/digital clock file, in case you want to try it out, is indeed on Github. To get the analog clock to change into a digital one, ground Pin 18. I hope this post helps you get started with the clever little OLED ESP32.

0 thoughts on “How to use the Heltec OLED display on the ESP32”

  1. Hi
    When i complie you clock code i get the error
    Arduino: 1.8.9 (Windows 10), Board: “WiFi Kit 32, Disabled, 240MHz (WiFi/BT), 921600, None”

    Build options changed, rebuilding all
    wificlock:4:20: error: images.h: No such file or directory

    compilation terminated.

    Multiple libraries were found for “WiFi.h”
    Used: C:\Users\david\AppData\Local\Arduino15\packages\Heltec-esp32\hardware\esp32\0.0.5\libraries\WiFi
    Not used: C:\Program Files (x86)\Arduino\libraries\WiFi
    exit status 1
    images.h: No such file or directory

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    Can you tell me what library is missing as i have tried a lot of oled one with no success


Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.