SSD1306 OLED display connected to an ESP32-S2 over hardware I2C. I noticed that the text will sometimes get scrambled or lag during a screen update. When left running long enough, the screen will get stuck and stop updating, despite serial monitor continuing to function. Does anyone know how to fix this? Here is a video of the laggy behavior: https://youtu.be/9OYW00cE24U 128x32 SSD1306 OLED scrambled text

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
unsigned long drawState = 1;
unsigned long previousTime = 0;
unsigned long eventInterval = 4000;

#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)

int screenSwitchLast = millis();

void loop() {

  if (millis() - screenSwitchLast >= eventInterval) {
    screenSwitchLast = millis();

    switch (drawState) {
      case 1:
        drawTemp(); //draw Temperature
      case 2:
        drawHum(); //draw Humidity

    if (drawState > 2) {
      drawState = 1;

void drawTemp() {
  Serial.print("Temp ");
  display.setCursor(0, 12);
  display.print("Temp: ");

void drawHum() {
  Serial.print("Hum ");
  display.setCursor(0, 12);
  display.print("Hum: ");

I saw this post which recommends running screen update code on the second core but the ESP32-S2 only has 1 core. I'm at odds with how I'd get this to work reliably on a single core ESP32.

Board: Adafruit ESP32-S2 Feather- 4M Flash and 2M PSRAM 
Display: 128x32 12C OLED - Ox3C

Arduino Settings:
   - USB CDC on Boot: Enabled
   - CPU Frequency: 240mHz (WiFi)
   - Core Debug Level: None
   - USB DFU on Boot: Disabled
   - Erase All Flash Before Sketch Upload: Disabled
   - Flash Frequency: 80mHz
   - Flash Mode: QIO
   - Flash Size: 4MB (32Mb)
   - USB Firmware MSC on Boot: Disabled
   - Partition Scheme: Minimal SPIFFS 1.9MB APP with OTA/190KB SPIFFS
   - PSRAM: Enabled
   - Upload Mode: Internal USB
   - Upload Speed: 921600
  • You are constantly clear the screen as clear screen is a relatively "time-consuming" process, plus the i2c buffer for display is quite small (32-bytes if I remember correctly). Move display.clearDisplay();, display.setTextSize(2); and display.setTextColor(SSD1306_WHITE); to the setup() function as all those only need to be setup once in your application, and also move the delay(1) to the main loop, this will help to address the lagging issue. You may need to print an extra space after "%" as "% " to overwrite the "F" previously print by the temperature string though.
    – hcheung
    Commented Jun 5, 2023 at 13:49
  • I tried the changes you suggested, but the lack of 'display.clearDisplay();' leaves the "Temp: 10F" text in place and when the "Hum: 20%" gets printed, it simply overlaps it. See photo here: jmp.sh/23oUnVHW
    – subcanny
    Commented Jun 5, 2023 at 22:20
  • You're using Adafruit's library; have you tried running their example code to see if it works for you?
    – romkey
    Commented Jun 5, 2023 at 23:27
  • Sorry, I mixed up with another library SSD1306Ascii which does not need to call display.clearDisplay() every time. BTW, I tested your original code with a 128x32 oled, and don't see the lagging your experienced, on both Adafruit library and SSD1306Ascii, but I use a classic ESP32 Dev kit.
    – hcheung
    Commented Jun 6, 2023 at 11:42
  • @hcheung I switched over to a regular ESP32 as well and it's working fine. I'm really curious to find out what is causing the issue with the S2 variant, so I'm going to try the example code like romkey mentioned. I'm also going to try disabling the radios to see if that helps.
    – subcanny
    Commented Jun 6, 2023 at 22:48


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.