OLED Animation Maker OLED Maker
🎵 Free Arduino project · SSD1306

Kalayani Song OLED Animation

Play the Kalayani song as a looping mono animation on a 0.96" SSD1306 — 148 PROGMEM frames, ready-to-flash Adafruit sketch, free on GitHub.

By Ashish Sep 16, 2026 ~10 min read Arduino · ESP8266 · ESP32
🎞️

148 song frames

Full Kalayani visuals as 1024-byte PROGMEM bitmaps for 128×64.

⚡

Plug & play sketch

Adafruit SSD1306 + GFX — open code.ino and upload.

🔌

Clear wiring

Uno / ESP8266 / ESP32 pin tables included below.

🆓

Free on GitHub

Clone or ZIP download — no paywall, no signup.

Want the Kalayani song to come alive on a tiny 0.96" SSD1306 OLED? This project plays a full 148-frame mono animation loop using Adafruit SSD1306 — perfect for desk toys, classroom demos, music-themed makers, and GIF-to-OLED experiments.

⬇ Free download — Kalayani OLED code

Full code.ino with all PROGMEM frames · ZIP or git clone

Open GitHub repo →

Parts list

  • Board: ESP8266 NodeMCU / Wemos D1 Mini, ESP32, or Arduino Mega (recommended)
  • Display: 0.96" SSD1306 I2C OLED, 128×64, usually 0x3C
  • 4 Dupont wires (VCC, GND, SDA, SCL)
  • USB cable + Arduino IDE

Connection / wiring

Match your board. Wrong SDA/SCL is the #1 blank-screen cause.

OLED pinArduino Uno / NanoESP8266 (NodeMCU)ESP32
VCC5V (or 3.3V if module requires)3.3V3.3V
GNDGNDGNDGND
SDAA4D2 (GPIO4)GPIO21
SCLA5D1 (GPIO5)GPIO22

On ESP8266, call Wire.begin(4, 5) before display.begin() if default I2C pins fail. If the screen stays black, try address 0x3D and read OLED blank screen fixes.

Libraries

  1. Arduino IDE → Tools → Manage Libraries
  2. Install Adafruit SSD1306
  3. Install Adafruit GFX Library
  4. Select your board + correct COM port

How the player works

All frames are stored as const uint8_t PROGMEM frameN[1024]. In loop() the sketch advances the index on a timer and draws the current bitmap:

void loop() {
  static uint8_t frameIdx = 0;
  static unsigned long lastMs = 0;
  const uint8_t* frames[] = { frame0, frame1, /* ... */ frame147 };
  const uint8_t numFrames = 148;

  if (millis() - lastMs >= 318) {
    lastMs = millis();
    display.clearDisplay();
    display.drawBitmap(0, 0, frames[frameIdx], 128, 64, SSD1306_WHITE);
    display.display();
    frameIdx = (frameIdx + 1) % numFrames;
  }
}

Change 318 to speed up or slow down the song timing. Smaller = faster FPS (example: 100 ≈ 10 fps).

Upload & run

  1. Open kalayanionoled → download ZIP or clone
  2. Open code.ino in Arduino IDE
  3. Install Adafruit GFX + SSD1306
  4. Pick ESP8266 / ESP32 / Mega + COM port
  5. Click Upload
  6. Watch Serial at 115200 — if you see SSD1306 allocation failed, fix power/wiring/address

Ready to flash?

Get the complete Kalayani code.ino from GitHub now.

⬇ Download code

Make your own song animation

Kalayani was exported from oledanimationmaker.com:

  1. Open the free tool in Chrome/Edge
  2. Go to Import → drop a short GIF or video clip
  3. Tune FPS / frame count for your board flash
  4. Click Get the Code → Adafruit SSD1306 Arduino
  5. Paste into IDE (or push to your own GitHub)

Related guides: GIF to OLED, Image to byte array, SSD1306 animation basics.

Troubleshooting

  • Sketch too big — use ESP8266/ESP32 or fewer frames
  • Blank OLED — 3.3V on ESP, check SDA/SCL, try 0x3D
  • Slow / laggy — keep frame delay ≥ 50–80 ms; solid USB power
  • Compile OOM — on ESP8266 set higher flash size in Tools
  • Garbage at end of file — delete stray characters after the last } in code.ino

FAQ

Is the Kalayani OLED code free?

Yes — github.com/itzmeAshish/kalayanionoled.

Does it play audio?

No — this is a visual OLED animation only. Pair a speaker separately if you need sound.

Can I change the song?

Yes. Import a different GIF/video into OLED Animation Maker and export a new sketch.

Build more OLED song & GIF animations

Pixel editor, GIF import, WebSerial live preview, Arduino & MicroPython export — free in the browser.

Open OLED Animation Maker →

What code.ino holds for Kalayani

The GitHub repo itzmeAshish/kalayanionoled is a single Adafruit sketch, code.ino. It is not a library and it does not read a GIF at runtime. Everything the OLED will ever show is already compiled into the file: 148 bitmaps named frame0 through frame147, each const uint8_t PROGMEM and each exactly 1024 bytes. A pointer table lists those arrays in order. setup() starts Serial at 115200, starts the SSD1306 at 0x3C, and loop() draws one bitmap every 318 ms.

Kalayani here is the picture loop only. The sketch has no audio pin, no MP3 decoder, and no lyric text. If you want the song itself, that is a separate player. This build is the 0.96" visual that goes with the title.

Arduino IDE wants the folder name to match the file. After you unzip, rename the folder to code and then open code.ino. Leaving the folder named kalayanionoled is a common reason the IDE asks to move the sketch or creates a second copy. The file is not main.ino in this repo, so do not rename the folder to main unless you also rename the file.

Kalayani timing table

The stock step is 318 ms, about 3.1 fps. One pass of all 148 frames is 148 × 318 ms ≈ 47 seconds. That slow step is why this loop still reads clearly on a 100 kHz I2C bus: pushing 1024 bytes takes on the order of 90 ms, and 318 ms leaves the transfer room to finish before the next index.

Delay in loop()Approx. fpsFull 148-frame passWhen to use it
500 ms2~74 sA desk piece you glance at, not a music cue
318 ms (stock)~3.1~47 sThe timing shipped in code.ino
200 ms5~30 sA bit snappier, still comfortable on default I2C
100 ms10~15 sBusy motion; raise the I2C clock if frames skip

Edit the number in the millis() test only. Leave numFrames at 148 unless you also delete bitmap arrays. Setting the count higher than the table reads off the end of the pointer list and the panel fills with garbage. Setting it lower plays a prefix of the loop and then jumps back to frame0, which is a fair way to preview wiring before you trust the whole 47 second cycle.

Wiring when the comment still mentions Uno

The sketch comment lists Uno pins because that is the usual teaching default: SDA on A4, SCL on A5, VCC on 5V. Many 0.96" modules accept 5V thanks to an onboard regulator, and the address is 0x3C. Use those pins only if you have shortened the animation. For this file as published, move to a board that can store it.

  • ESP8266 NodeMCU: VCC to 3.3V, GND to GND, SDA to D2 (GPIO4), SCL to D1 (GPIO5). If the panel stays dark, add Wire.begin(4, 5) before display.begin().
  • ESP32: VCC to 3.3V, SDA to GPIO21, SCL to GPIO22. Do not use the Uno A4/A5 labels on an ESP32 DevKit. Those pins are not the I2C defaults.
  • Arduino Mega 2560: the hardware I2C pins are still SDA 20 and SCL 21 (not A4/A5). Mega has 256 KB of flash, so the 148 KB of bitmaps can fit. The comment’s “A4/A5” line is the Uno map, not the Mega map.

Four dupont wires are enough. Keep them short. A 30 cm jumper pair on SDA and SCL is a frequent cause of a panel that works on the desk and dies when you move the project.

Why a classic Uno cannot play these 148 frames

Flash on the ATmega328P is about 32 KB, and the bootloader already keeps a slice of that. The bitmaps alone are 148 × 1024 = 151,552 bytes, roughly 148 KB, before Adafruit GFX, SSD1306, and Wire. That is several times the whole Uno. The IDE error is “sketch too big,” and no optimizer will squeeze a 148 KB table into 32 KB.

Nano (the classic one, not Nano ESP32 or Nano Every) has the same 32 KB ceiling. Mega 2560 can hold this particular sketch. An ESP32, or an ESP8266 module with 4MB of flash, is the comfortable choice and matches the other long loops on this site. If you only own an Uno, reopen the clip in OLED Animation Maker, cut the frame count into the low teens, and export again. Do not delete random frameN arrays in the middle of code.ino unless you also rebuild the pointer table. A hole in that list is worse than a short loop.

Changing the 318 ms step

Find the comparison millis() - lastMs >= 318. Replace 318 with a value from the table, upload again, and watch one full pass before you decide. The index wraps with frameIdx = (frameIdx + 1) % numFrames, so the loop is endless. You do not need a second timer for “end of song.” There is no audio to stay in sync with.

If you type a delay below about 80 ms, display() becomes the real clock. The OLED will still advance, but the gap you typed is a minimum, not a promise. For Kalayani’s stock 318 ms you will not hit that floor. Go slower (a larger delay) when you are filming and want each picture to sit long enough for a phone to catch it.

A recording that shows the Kalayani loop honestly

Film the module, not the GitHub page. Fill the phone frame with the glass. Kill the ceiling light behind you so the cover glass does not mirror the room. OLED pixels are either lit or not. A wide shot of the whole bench makes 128 columns look like dust.

Record at least 50 seconds so one 47 second pass completes on camera. You should see the picture change, return to the opening frame, and continue. A take that stops at 10 seconds only proves the first handful of bitmaps. If the motion looks slower than the song you remember, that is the 318 ms step, not a dropped upload. This project does not play the track. A silent video of the panel is the correct result.

When upload succeeds and the panel does not

  • Black screen: ESP boards must feed VCC from 3.3V. A 5V pin on a NodeMCU is not the logic supply for the display. Reseat SDA and SCL. On ESP8266, D2 and D1 are easy to swap because the silk is tiny.
  • Wrong address: SSD1306 allocation failed on Serial at 115200 usually means begin() did not see 0x3C. Change the address to 0x3D and upload once. If both fail, the chip is not on the bus. Check GND before you change libraries.
  • IDE board mismatch: a sketch compiled as “Arduino Uno” and sent to a NodeMCU will not run this file, and a sketch compiled as ESP32 will not run on an 8266. Pick the board that matches the USB chip, then pick the port that appears when you plug the cable in. Install the ESP8266 or ESP32 board package if the menu has no entry for your module.
  • Not enough flash: on ESP8266 open Tools → Flash Size and choose the 4MB option that matches the module. A 512 KB or 1MB setting rejects a 148 KB bitmap table even when the chip is larger. The Uno error is the same problem with no menu that can fix it.

Kalayani bench questions

Does this sketch play the Kalayani audio?

No. code.ino is 148 monochrome frames on a 128×64 SSD1306. There is no speaker code. The title is the song name. The OLED plays the visual only.

I cloned kalayanionoled and the IDE complains about the sketch name. What folder do I use?

The file is code.ino, so the folder must be named code. It is not the main.ino layout used by some of the other song repos. Rename the folder, then open the file from inside it.

Can I keep the 148 frames and still use an Uno if I lower the fps?

No. The delay only changes timing. The bytes stay in flash. 148 KB does not fit in 32 KB at any frame rate. Use ESP32, a 4MB ESP8266, or a Mega, or export a much shorter frame list.

How do I know the 318 ms loop is actually running?

Time one pass with a watch. From the first picture back to the same picture should be about 47 seconds. A pass near 15 seconds means the delay was edited to 100 ms. A frozen first frame means the loop is not advancing, which points back at upload, power, or begin() failing before loop() draws.

Related posts