ESP32-C3 OLED/The screen/07. First words on the OLED
The screen · 07 of 9

First words on the OLED

The glass is 72 pixels by 40. The controller behind it has 132 columns of memory, and the panel is wired to a window inside that — so the constructor you pick is not a detail, it is the whole difference between text and a blank screen.

Install U8g2, not the other one

Use U8g2 by oliver, from the Library Manager. It is the library that has a constructor for this exact panel, which the popular Adafruit SSD1306 library does not — that one is written for 128 × 64 modules and has no notion of the offset this glass needs.

Why the constructor is the whole sketch

The panel is 72 pixels wide and 40 tall. The controller driving it is not: it has 132 columns and 64 rows of display RAM, and the glass is wired to a window somewhere inside that. Nothing in the I²C protocol says where the window starts — the driver has to already know, and that knowledge is baked into the constructor's name.

72 × 40 of glass, 132 × 64 of memory
on the glass
Constructor
Buffer
72 × 40
Lands on the glass
yes
The buffer lands exactly on the glass. The constructor carries both the size and the offset into the controller’s 132 columns, so drawStr(0, 10, …) puts a character in the top-left corner of what you can actually see.

Three failures come out of that, and all three look like a broken screen:

  • A 128 × 64 constructor writes a picture bigger than the glass, starting in the wrong corner. You get a fragment, or nothing.
  • An SSD1306 72 × 40 constructor is the right size and the wrong controller. The two chips have different memory widths — 132 columns against 128 — so a driver written for one applies an offset the other does not want, and the picture lands a few pixels across with a sliver wrapped round the edge.
  • The SH1106 72 × 40 constructor is the one this board wants.

The pin order that is not the order you say it

U8G2_SH1106_72X40_WISE_F_SW_I2C u8g2(U8G2_R0, 6, 5);

After the rotation, U8g2's software-I²C constructors take clock first, then data — so SCL 6 and then SDA 5. People say "SDA and SCL" out loud and type them in that order, which puts the bus on the wrong two pins and produces exactly the same silence as every other mistake on this page.

The F means a full frame buffer. For a 72 × 40 monochrome panel that is 360 bytes, so there is no reason to use the paged variants on this chip. Draw into the buffer, then sendBuffer() once.

Forty pixels is not many

drawStr(0, 10, …) places text by its baseline, not its top, so a y of 10 puts a 10-pixel font just inside the top edge and a y of 0 puts it entirely off the screen. With u8g2_font_6x10_tf you get two comfortable lines of about twelve characters, or three tight ones.

If a string runs off the right-hand edge, U8g2 clips it silently rather than wrapping. u8g2.getStrWidth() will tell you how wide it would be before you draw it, which is the honest way to fit a variable-length reading into 72 pixels.

The code

oled_hello.ino

The smallest sketch that puts words on this screen. The constructor line carries the controller, the panel size and the two pins, and it is the only line most people get wrong.

/*  Lonely Binary ESP32-C3 OLED — first words
    Tools > Board:            ESP32C3 Dev Module
    Tools > USB CDC On Boot:  Enabled
    Library: U8g2 by oliver (Library Manager)          */

#include <U8g2lib.h>

// SH1106 controller, 72x40 panel, software I2C.
// Arguments: rotation, clock (SCL), data (SDA).
U8G2_SH1106_72X40_WISE_F_SW_I2C u8g2(U8G2_R0, 6, 5);

void setup() {
  u8g2.begin();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(0, 10, "LONELY");
  u8g2.drawStr(0, 22, "BINARY");
  u8g2.sendBuffer();
}

void loop() {}

The two arguments after the rotation are, in order, the clock pin and the data pin — SCL 6 then SDA 5, which is the opposite order to the way people say "SDA and SCL" out loud. Swap them and the bus goes quiet with no error message.

When it does not work

The screen stays completely dark

Run the I²C scanner first. If it reports a device at 0x3C the panel is alive and the problem is the constructor or the pin order; if it reports nothing, the problem is the bus and no display library will help. Those are two different afternoons and the scanner tells you which one you are in.

Text appears but shifted sideways, with a sliver wrapped round the edge

The wrong controller. An SSD1306 has 128 columns of memory and an SH1106 has 132, so a driver written for the first offsets the window by a different amount than this panel needs. Everything renders, a few pixels across, which reads as a hardware fault and is one word in the constructor.

Only the top-left corner of the drawing shows

A 128x64 constructor. That is what almost every OLED tutorial uses, because almost every other module is a 0.96 inch 128x64 — here it writes a picture four times the size of the glass, starting in the wrong corner, and you see whatever fragment happens to land in the window.

The sketch compiles but the board runs out of memory or resets in a loop

The F in the constructor name means a full frame buffer, which for this panel is only 360 bytes and is not the problem. A reset loop with a display attached is usually the supply — check it on USB before blaming the sketch, since a nearly-flat cell browns out under the screen's current draw.

Where this goes next

Bridge one pad and the board can read its own cell. Then three conversions in a row, each of them a chance to be wrong by a factor of two.

Battery level, on the screen

Edit this page — content/boards/c3-oled/first-words-on-the-oled.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

ESP32-C3 OLED Development Board with Expansion Base

Loading discussions…

Discuss this article

Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.

Browse ESP32-C3 OLED on the forum