DIY OLED name badge with Arduino (SSD1306)
I made the first one for a friend's desk. Nano, 0.96" blue OLED, USB cable permanently plugged into a power bank. On boot the name rains in. Then it just sits there. People poke it every time they walk past.
You do not need a custom PCB. You need clean wiring, a short animation that fits in flash, and a name that is not fifteen syllables long. This is a full build notes page — parts, pins, animation export, power, and the mistakes I made on version one.
What you will end up with
- A small Arduino + OLED that plays a name intro on power-up
- Optional idle screen after the intro (static name or dim icon)
- A sketch you can re-export when you gift it to someone else
Parts list (what I actually buy)
- Arduino Nano or Uno (Nano fits a badge case better)
- 0.96" SSD1306 128×64 I²C OLED
- Dupont wires or a short soldered harness
- USB power, or a small LiPo + boost if you want untethered
- Optional: 3D-printed stand or a leftover business-card holder
Blue OLEDs are cheap and common. White looks a bit sharper for thin fonts. Animation code is the same either way.
Wiring that does not fight you
| OLED | Nano / Uno | ESP32 |
|---|---|---|
| GND | GND | GND |
| VCC | 5V | 3.3V |
| SDA | A4 | GPIO 21 |
| SCL | A5 | GPIO 22 |
Full pin tables and Hello World: I2C OLED tutorial. If the badge boots blank, fix address / wiring before you touch animation code — blank screen checklist.
Make the name animation
Open Name Assemble, type the name, pick a style. For badges I like Outside Random or Top→Bottom. Heavy 3D styles chew flash.
- Keep the name under ~10 characters on Uno, or use two lines
- Preview on the mockup until spacing looks right
- Export Adafruit SSD1306 (or U8g2 if that is your habit)
- Set board + I²C address in the tool header
- Upload once, leave USB plugged in, call it done
Want a logo instead of letters? Import a PNG on the Import tab and assemble every lit pixel. Same Get Code button. Logo-focused notes: OLED logo splash.
More background on how name frames work: name animation guide.
Bill of materials with approximate cost (India hobby market, 2026)
Prices move, but this is what students usually spend for one desk badge:
| Item | Notes | Ballpark |
|---|---|---|
| Arduino Nano clone | CH340 is fine for USB power toys | low |
| 0.96" SSD1306 I²C | Confirm 4-pin I²C, not SPI-only | low |
| Dupont wires / header | Soldered harness lasts longer | very low |
| USB cable + phone charger | Skip LiPo on version one | you probably own this |
| Optional stand | Print or cardboard | optional |
If your module has seven pins, it may be SPI. This tutorial assumes four-pin I²C. SPI works for animations too, but wiring and library setup differ — stick to I²C for the badge.
Build order that avoids half-finished messes
- Breadboard Hello World (static name) — no case yet
- Export a short Name Assemble intro and confirm upload size
- Add idle screen after intro
- Only then hot-glue / print a stand
- Change the name last when gifting (re-export + flash)
I used to case first. Then a dry joint meant opening everything again. Do electronics first.
Idle screen ideas after the intro
- Static name at text size 2, centered
- Name + small “Hello” subtitle
- Dimmer contrast via
display.ssd1306_command(SSD1306_SETCONTRAST); display.ssd1306_command(0x20); - Display off after 10 minutes, wake on a button to GND
void showIdleName() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(16, 24);
display.print(F("ASHISH"));
display.display();
}
Classroom / workshop variant
For a 90-minute lab I pre-cut wires and keep one “golden” Nano that already shows Hello World. Students copy that wiring, then each person types their own name in Name Assemble on a shared laptop, downloads the .ino, and flashes. The win condition is not a perfect case — it is their name assembling on their own OLED.
Safety and honesty notes
- Do not leave LiPo packs charging unattended in a school bag
- USB desk power is enough for almost every gift badge
- Cheap OLED flex cables tear — support the glass when plugging Duponts
Sketch structure I use for badges
void setup() {
initDisplay();
playIntroOnce(); // Name Assemble export
showIdleName(); // static or dim
}
void loop() {
// optional: button to replay intro
// optional: DISPLAYOFF after 10 minutes
}
Version one looped the intro forever. Cool for five minutes. Annoying by dinner. Replay-on-button is a nicer compromise.
Power and burn-in habits
OLEDs can leave ghosts if you park the same bright pixels for weeks. For a desk toy that stays on all day I either:
- Play the intro once, then show a dimmer static layout, or
- Call display-off after a timeout and wake on a button
More on contrast and sleep: OLED power & battery life.
USB from a wall cube or power bank is the path of least drama. LiPo + boost works for a wearable, but you own charging, a switch, and a case that does not short the module. Most people should stay on USB for v1.
Case and mounting ideas
- Hot-glue the OLED bezel to a small 3D stand, Nano underneath
- Slide the sandwich into a clear business-card box
- For workshops: leave it on a breadboard so students can rewire
Do not stress the OLED flex cable. I cracked one bending it “just a little” to fit a case.
Gift tip
Change the name in Name Assemble, re-export, flash. Five minutes. That is why I stopped hand-editing hex for birthday badges.
Related searches: oled name badge arduino · diy oled name plate · ssd1306 name display · personalized oled arduino · greeting oled animation
Frequently asked questions
Can I wear this as a badge on a lanyard?
Possible with a LiPo and a tiny case. Most people leave it on the desk USB-powered. Safer and simpler.
Blue or white OLED?
Blue is common and cheap. White looks sharper for thin fonts. Animation code is the same.
Will a long surname fit?
On 128×64, maybe at small font or two lines. Preview in Name Assemble before you solder a gift.
Uno sketch too big?
Shorten the style or use Nano/ESP32. See PROGMEM limits.
How do I replay the intro without looping it forever?
Wire a momentary button from D2 to GND, use INPUT_PULLUP, and call the Name Assemble player once when the pin reads LOW. Debounce with millis() so one press does not restart the intro five times. Leave loop() on the idle name the rest of the time.
The badge is black on a Mega and fine on a Nano. Same sketch. Why?
Nano I2C is A4 and A5. Mega 2560 is pins 20 and 21. ESP32 badges use GPIO21 and GPIO22 with the OLED on 3.3 V. ESP8266 NodeMCU uses D2 and D1. The name frames do not change when you change boards; the four wires do.
Hello World works at 0x3C and the badge export stays black. What should I edit?
The exported begin() address. Some modules are 0x3D, and the tool header sometimes still says 0x3C. Match the scanner. Also confirm reset is -1 on a 4-pin module so the sketch does not clamp RES.
What contrast should the idle screen use so it does not ghost?
After the intro, send SSD1306_SETCONTRAST and a mid value such as 0x20 for a desk badge that stays on all day. 0xCF is for the intro, when you want the name obvious across a room. A contrast of 0x00 looks like a failed upload.
Idle name, then a replay button
Version two of the desk badge plays the Name Assemble intro once, then parks a short name at text size 2. A button on D2 replays the intro. I use a Nano because it fits under a card holder; the OLED is the usual 4-pin SSD1306 on A4 and A5, VCC on 5V, address 0x3C. The idle string is six letters. At size 2 each character is 12 pixels wide, so “ASHISH” is 72 pixels and the cursor goes at (128 - 72) / 2 = 28. Guessing 16, as I did on the first gift, leaves the name looking shoved left.
const uint8_t BTN = 2;
uint32_t lastReplay = 0;
void showIdleName() {
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(0x20); // dimmer than the intro
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(28, 24); // (128 - 6*12) / 2
display.print(F("ASHISH"));
display.display();
}
void loop() {
if (digitalRead(BTN) == LOW && millis() - lastReplay > 800) {
lastReplay = millis();
display.ssd1306_command(SSD1306_SETCONTRAST);
display.ssd1306_command(0xCF);
playIntroOnce();
showIdleName();
}
}
In setup(), call pinMode(BTN, INPUT_PULLUP), display.begin(SSD1306_SWITCHCAPVCC, 0x3C) with reset -1, then playIntroOnce() and showIdleName(). The 800 ms gap is the debounce. Without it, a cheap button contact replays the rain animation until the flash has been admired more than anyone wanted.
Count letters before you center. A 10-character name at size 2 is 120 pixels and barely fits; at that point drop to size 1 (6 pixels per character) or two lines. The mockup in Name Assemble is the check. A surname that fits the mockup and then clips on the glass usually means setTextSize(2) was left on after a size-1 export, or the panel is 128×32 and the constructor still says 64. A 128×32 badge uses height 32 and a cursor nearer y=8.
Flash budget is the other limit. Each full 128×64 intro frame is about 1024 bytes. A short Outside Random intro of eight to twelve frames fits a Nano. A heavy style plus the idle text plus a second logo will not. If the IDE reports the sketch is too large, shorten the style. Do not “fix” it by deleting display.display() — that only makes a successful upload look like a dead badge.
Badge faults that are not the animation
- USB plug in, no port in the IDE. Nano clones often use a CH340 USB chip. Install that driver, then pick the new COM port. The OLED cannot show a sketch that never uploaded. This feels like a blank screen and it is a laptop problem.
- Intro plays on the bench, black after you close the case. The flex tail or a Dupont plug pulled off SDA when you bent the display into the stand. Reseat all four wires. If the image returns when you press the header, solder the harness. Breadboard contact is not a gift.
- Name appears, shifted a couple of columns, only on one module from the bag. That module is an SH1106 (132×64 RAM, column offset) even though the listing said SSD1306. Use the SH1106 constructor for that badge. The button code stays the same.
- Power bank badge reboots in the middle of the intro. The bank shut off because the Nano’s current was below its load detector, or the cable is thin and the rail dipped during
display(). A bank with an “always on” mode, or a wall cube, is the fix. A second 4.7k pull-up is not. - Two badges on one Uno for a booth, both dark. Both modules are at
0x3C. Change one address jumper to0x3D. Two 1024-byte buffers also crowd Uno SRAM; an ESP32 is the easier booth controller, with SDA on GPIO21 and SCL on GPIO22, OLED VCC on 3.3 V. - Idle screen ghosts after a month on a shop counter. The same pixels have been at full contrast the whole time. Dim to
0x20after the intro, or turn the display off after a timeout and wake it from the D2 button.
Nano, Mega, and ESP boards for the same gift
| Board | Where the OLED goes | Badge note |
|---|---|---|
| Nano / Uno | SDA A4, SCL A5, VCC 5V | Best v1. Reset argument -1. Keep the intro short |
| Mega 2560 | SDA 20, SCL 21, VCC 5V | Physically large for a desk card. Only the I2C pins change |
| ESP8266 NodeMCU | SDA D2, SCL D1, VCC 3.3V | Call Wire.begin(D2, D1) before begin. More flash for longer names |
| ESP32 | GPIO21 / GPIO22, VCC 3.3V | Use this when the style is dense. Do not power the module from 5V or the pull-ups will over-voltage the pins |
I2C is the right bus for a badge. Two signal wires survive a small case; SPI’s DC, CS, and RST do not earn their keep for a clip that plays once. If you later add a high frame-rate bitmap behind the name, that is the moment to look at SPI, not before the first gift is soldered.
Whichever board you pick, run an I2C scan before you hot-glue the bezel. A scanner that prints 0x3C or 0x3D means the case can close. A scanner that prints nothing means the animation file is irrelevant until the jumper seats.