{{ t.products }}

{{ live_data.products.length }}

{{ t.categories }}

{{ live_data.categories.length }}

{{ t.brands }}

{{ live_data.brands.length }}
Menu
If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!
If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!If you cannot find a specific electronic or automation spare part on our website or in the market, please contact us — quantity does not matter!

How to Build a Mini OLED Character with the XIAO ESP32-C6?

•
Author: Senanur Yılmaz
•
Publish Time: 10.11.2026
•
Reading Time: 10 Minute
How to Build a Mini OLED Character with the XIAO ESP32-C6?
How to Build a Mini OLED Character with the XIAO ESP32-C6

How to Build a Mini OLED Character with the XIAO ESP32-C6

In this guide, we will build a cute mini OLED character that changes its facial expressions. Even if you have never assembled an electronic circuit before, you will learn where every wire goes, which software to install, and how to upload the code to the board.

What will the finished project do? The character will blink, look left and right, and display happy, sad, surprised, sleepy, and angry expressions. The project does not use a motor; all movement is created by drawings on the OLED screen.

1. Materials

Safety: A soldering iron becomes extremely hot, so children must work with an adult. Never puncture, crush, short-circuit, or reverse the positive and negative terminals of a LiPo battery. Connect the battery last.

2. How does the system work?

The XIAO ESP32-C6 calculates the face that should be drawn and sends it to the OLED through a two-wire communication method called I2C. SDA is the data wire and carries the drawing information. SCL is the clock wire and controls the timing of the data. VCC and GND provide electrical power to the display.

3. Wiring diagram

Görsel önizleme

Red indicates power, black indicates ground/negative, green indicates data, and blue indicates the clock connection.

FromToPurpose
OLED VCCXIAO 3V3Supplies a safe 3.3 V to the display.
OLED GNDXIAO GNDProvides the common ground connection.
OLED SDAXIAO D4 / SDASends display data.
OLED SCLXIAO D5 / SCLProvides the I2C clock signal.
Battery positive (+)Middle switch pinCarries battery power to the switch.
One outer switch pinXIAO BAT+Connects the battery when the switch is on.
Battery negative (−)XIAO BAT−Provides the battery’s negative connection.

Connecting the three-pin slide switch

mini-oled-switch-wiring-en.png

The switch has three pins, but we only use two: the middle pin and one of the outer pins. Leave the other outer pin unconnected. If the on/off direction feels reversed, move the wire from the selected outer pin to the other outer pin.

Charging note: The switch completely disconnects the battery’s positive wire. Therefore, the switch must be in the ON position when charging the battery through the XIAO’s USB-C port.

Recommended soldering order

  1. Disconnect the USB cable and battery.
  2. Prepare the OLED’s VCC, GND, SDA, and SCL wires.
  3. Solder these four wires to the XIAO according to the table.
  4. Solder the battery’s positive wire to the middle pin of the switch.
  5. Connect one outer switch pin to the BAT+ pad on the XIAO.
  6. Connect the battery’s negative wire to the XIAO BAT− pad.
  7. Cover exposed metal with heat-shrink tubing or suitable insulation.
  8. Check for short circuits before connecting the battery.

4. Software: Arduino IDE

Arduino IDE is the free program we will use to send the code to the XIAO board. Download and install the correct version for your operating system from the Arduino IDE download page.

Installing ESP32 board support

  1. Open Arduino IDE.
  2. Go to File > Preferences.
  3. Add this address to Additional Boards Manager URLs:
    https://espressif.github.io/arduino-esp32/package_esp32_index.json
  4. Open Boards Manager from the left sidebar.
  5. Search for esp32 and install version 3.0.0 or newer of the package by Espressif Systems.
  6. Select Tools > Board > ESP32 Arduino > XIAO_ESP32C6.
  7. Connect the board with a USB-C data cable and select its port from Tools > Port.

Installing the U8g2 display library

  1. Click the Library Manager icon on the left side of Arduino IDE.
  2. Type U8g2 in the search box.
  3. Install the U8g2 library by Oliver Kraus.

5. Run a simple display test first

Testing the display and wires before uploading the full animation makes troubleshooting much easier. In Arduino IDE, select File > New Sketch, delete the example code, and paste the following:

#include <Wire.h>
#include <U8g2lib.h>

// Try the SH1106 driver first for this display.
U8G2_SH1106_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE);

void setup() {
  Wire.begin(D4, D5);       // D4 = SDA, D5 = SCL
  display.begin();
  display.clearBuffer();
  display.setFont(u8g2_font_ncenB14_tr);
  display.drawStr(25, 38, "Hello!");
  display.sendBuffer();
}

void loop() {
  // Nothing is required here because the text remains on the display.
}

Click the check-mark button to verify the code, then click the arrow-shaped Upload button. If “Hello!” appears, the wiring is correct.

If the screen is still blank: Your display may use an SSD1306 controller. Replace U8G2_SH1106_128X64_NONAME_F_HW_I2C with U8G2_SSD1306_128X64_NONAME_F_HW_I2C and upload the code again.

6. Full animation code

The following code automatically searches for address 0x3C or 0x3D. It draws the character, makes it blink and look from side to side, and changes its facial expression at random intervals.

#include <Wire.h>
#include <U8g2lib.h>

// Use this line if your display uses the SH1106 controller.
U8G2_SH1106_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE);

// If SH1106 produces no image, comment out the line above and enable this one:
// U8G2_SSD1306_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE);

enum Emotion { NEUTRAL, HAPPY, SAD, SURPRISED, SLEEPY, ANGRY };

Emotion emotion = NEUTRAL;
int lookX = 0;
int targetLookX = 0;
bool eyesClosed = false;
unsigned long nextBlink = 0;
unsigned long openEyesAt = 0;
unsigned long nextAction = 0;

byte findOledAddress() {
  byte possibleAddresses[] = {0x3C, 0x3D};
  for (byte i = 0; i < 2; i++) {
    Wire.beginTransmission(possibleAddresses[i]);
    if (Wire.endTransmission() == 0) return possibleAddresses[i];
  }
  return 0;
}

void drawEye(int centerX, int centerY, bool leftEye) {
  if (eyesClosed || emotion == SLEEPY) {
    display.drawLine(centerX - 9, centerY, centerX + 9, centerY);
    display.drawLine(centerX - 7, centerY + 1, centerX + 7, centerY + 1);
    return;
  }

  int width = (emotion == SURPRISED) ? 22 : 18;
  int height = (emotion == SURPRISED) ? 30 : 25;
  int x = centerX - width / 2 + lookX;
  int y = centerY - height / 2;
  display.drawRBox(x, y, width, height, 6);

  if (emotion == ANGRY) {
    display.setDrawColor(0);
    if (leftEye) display.drawTriangle(x - 2, y - 1, x + width + 2, y - 1, x + width + 2, y + 8);
    else display.drawTriangle(x - 2, y - 1, x + width + 2, y - 1, x - 2, y + 8);
    display.setDrawColor(1);
  }
}

void drawMouth() {
  switch (emotion) {
    case HAPPY:
      display.drawLine(51, 46, 58, 52); display.drawLine(58, 52, 64, 54);
      display.drawLine(64, 54, 70, 52); display.drawLine(70, 52, 77, 46);
      break;
    case SAD:
      display.drawLine(51, 55, 58, 49); display.drawLine(58, 49, 64, 47);
      display.drawLine(64, 47, 70, 49); display.drawLine(70, 49, 77, 55);
      break;
    case SURPRISED: display.drawCircle(64, 51, 7); break;
    case SLEEPY: display.drawLine(58, 52, 70, 52); break;
    case ANGRY:
      display.drawLine(54, 55, 64, 50); display.drawLine(64, 50, 74, 55);
      break;
    default: display.drawLine(58, 52, 70, 52); break;
  }
}

void drawFace() {
  display.clearBuffer();
  drawEye(38, 29, true);
  drawEye(90, 29, false);
  drawMouth();
  display.sendBuffer();
}

void setup() {
  Serial.begin(115200);
  delay(300);
  Wire.begin(D4, D5);  // XIAO ESP32-C6: D4 = SDA, D5 = SCL

  byte address = findOledAddress();
  if (address == 0) {
    Serial.println("OLED not found. Check the wiring.");
    while (true) delay(1000);
  }

  display.setI2CAddress(address << 1);
  display.begin();
  randomSeed(micros());
  nextBlink = millis() + random(2000, 6000);
  nextAction = millis() + random(1500, 4000);

  Serial.print("OLED found at address 0x");
  Serial.println(address, HEX);
}

void loop() {
  unsigned long now = millis();

  if (!eyesClosed && now >= nextBlink) {
    eyesClosed = true;
    openEyesAt = now + 150;
  }

  if (eyesClosed && now >= openEyesAt) {
    eyesClosed = false;
    nextBlink = now + random(2000, 6000);
  }

  if (now >= nextAction) {
    if (random(100) < 40) targetLookX = random(-5, 6);
    else {
      emotion = (Emotion)random(0, 6);
      targetLookX = 0;
    }
    nextAction = now + random(1500, 4000);
  }

  if (lookX < targetLookX) lookX++;
  if (lookX > targetLookX) lookX--;
  drawFace();
  delay(33);  // Approximately 30 frames per second
}

7. Simple explanation of the code

Code sectionWhat does it do?
#include linesEnable I2C communication through Wire and OLED drawing through U8g2.
enum EmotionLists the facial expressions the character can display.
findOledAddress()Automatically detects whether the display uses address 0x3C or 0x3D.
drawEye()Draws each eye and controls its size, position, and closed state.
drawMouth()Draws a different mouth shape for the selected emotion.
setup()Runs once when the board starts and prepares the display.
loop()Runs repeatedly and manages blinking, looking, and expression changes.
delay(33)Produces approximately 30 frames per second for smooth animation.

8. Uploading the code

  1. Open a new sketch in Arduino IDE and paste the full code.
  2. Make sure XIAO_ESP32C6 is selected under Tools > Board.
  3. Select the board’s connection under Tools > Port.
  4. Click the check mark to compile the code.
  5. Click the arrow button to upload it.
  6. The display should come to life a few seconds after the upload finishes.

If the board does not appear, your USB-C cable may be a charging-only cable. Try a cable that supports data. If uploading does not start, hold the BOOT button, press RESET once, release BOOT, and try again.

9. Troubleshooting

ProblemWhat to check
The display is completely offMake sure VCC is connected to 3V3 and GND is connected to GND.
The display is powered but blankCheck SDA/D4 and SCL/D5; try the SSD1306 constructor instead of SH1106.
“OLED not found” appearsOpen Serial Monitor at 115200 baud and inspect the solder joints for breaks or short circuits.
The code does not compileConfirm that U8g2 and a current ESP32 board package are installed.
The board is missing from the port listTry another USB data cable or USB port.
The project does not run on batteryCheck that the middle and one outer switch pin are used and verify BAT+ and BAT− polarity.
The battery does not chargeMove the switch to the on position while USB-C is connected.
The board continuously restartsCharge the battery and make sure no solder joints touch each other.

10. Using a 3D-printed enclosure

The project that inspired this guide provides 3D model files on GitHub. Measure your components before printing. The OLED board is approximately 35.5 × 33.5 mm, the battery is approximately 24 × 15.5 × 6.7 mm, and the selected switch body is approximately 10.5 × 5.5 mm. You may need to enlarge the original model’s switch opening.

Conclusion

You now have a portable mini character powered by the XIAO ESP32-C6, an I2C OLED display, a small LiPo battery, and a slide switch. Running the simple “Hello!” test before uploading the full animation is the easiest way to find wiring problems.

Original project video: Building a Tiny OLED Keychain
Example source code: TechTalkies / 123_Keychain
Official XIAO ESP32-C6 getting-started guide: Seeed Studio Wiki

Share
T-Soft | Premium