Arduino Uno OLED Animation Memory Limits — How Many Frames Fit?
Every workshop I run, someone hits the same wall: the animation looks fine in the browser, the sketch compiles… then the Arduino IDE says the sketch is too big. Or worse — it uploads, then the board resets in a loop because RAM ran out.
This post is the math I write on the whiteboard. No marketing fluff. Just how many 128×64 OLED frames you can actually store on an Arduino Uno, and what to do when you need more.
The hard numbers (Uno)
- Flash: 32 KB total. Bootloader usually keeps ~0.5 KB. You get roughly 31.5 KB for code + data.
- SRAM: 2 KB. The Adafruit SSD1306 buffer alone uses 1024 bytes for 128×64.
- One full-frame bitmap: 128 × 64 ÷ 8 = 1024 bytes (1 KB).
So each full-screen frame costs about 1 KB of flash if you store it in PROGMEM. Leave that array in regular RAM and you are already nearly out of SRAM before your own variables start.
How many frames fit in practice?
Your sketch is not only bitmaps. Adafruit GFX + SSD1306 + Wire + your loop() easily eat
10–14 KB of flash on a typical animation sketch. That leaves roughly
16–20 KB for frames.
| Frame size | Bytes / frame | Realistic max on Uno* |
|---|---|---|
| 128×64 full screen | 1024 | ~12–18 frames |
| 64×64 sprite | 512 | ~24–36 frames |
| 32×32 icon | 128 | ~80–120 frames |
| 128×32 banner | 512 | ~24–36 frames |
*After libraries. Always check the IDE compile bar — “Sketch uses X bytes” is the truth, not a blog estimate.
Store frames in PROGMEM (required)
If you forget PROGMEM, the compiler may put the array in SRAM. On Uno that often means
instant crash or weird resets. Pattern that works:
#include <avr/pgmspace.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// 1 KB frame — lives in flash, not the 2 KB SRAM
const uint8_t frame0[] PROGMEM = {
// 1024 bytes from your converter…
0x00, 0x00 /* … */
};
const uint8_t* const frames[] PROGMEM = { frame0 /*, frame1, … */ };
const uint8_t FRAME_COUNT = 1;
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}
void loop() {
static uint8_t i = 0;
display.clearDisplay();
// pgm_read_word because frames[] itself is in PROGMEM on AVR
const uint8_t* f = (const uint8_t*)pgm_read_word(&frames[i]);
display.drawBitmap(0, 0, f, 128, 64, SSD1306_WHITE);
display.display();
i = (i + 1) % FRAME_COUNT;
delay(80);
}
On ESP32 / SAMD you often do not need the pgm_read_word dance the same way — but on Uno you do.
If the image looks like garbage, check that first.
What actually ate my flash in class projects
- Too many full-screen frames. A 24-frame walk cycle at 128×64 is ~24 KB of bitmaps alone. Uno cannot take that plus libraries.
- Serial debug left on. Extra strings and
Serial.printadd up. Fine for debugging; strip them for the final upload. - Unused library features. Pulling in huge font sets or multiple display drivers wastes space.
- Duplicating similar frames. Blink animations often only need 2–4 frames. Exporting 20 “almost the same” frames is the #1 student mistake.
Tricks that actually help on Uno
1. Smaller sprites, not full-screen every frame
Draw a static background with GFX (drawRect, text), and only animate a 32×32 or 48×48 sprite.
Memory drops fast. The free tool’s shape export is useful here because vector-style GFX code is tiny
compared with bitmaps.
2. Shorter loops
A 6-frame loop at 10 FPS looks smoother than a 20-frame loop you cannot fit. Cut frames that do not change much.
3. 128×32 displays
Half the pixels → half the bytes per frame. If the project only needs a status strip, buy 128×32 and suddenly you have room again.
4. Move up when you outgrow Uno
Nano Every, Mega, and especially ESP32 change the game. ESP32 flash is measured in megabytes. If your animation needs 40+ full frames, stop fighting the Uno — change the board.
How I check before uploading
- Export animation → look at frame count × 1024.
- Add ~12 KB for a typical Adafruit sketch.
- If total > ~28 KB, cut frames or shrink sprites before pasting into the IDE.
- After compile, read “Global variables use X bytes of dynamic memory.” If SRAM > ~1500 bytes used, you are in the danger zone on Uno.
Quick FAQ
Why does the IDE say the sketch fits but the board resets?
Flash was OK; SRAM was not. Usually the bitmap was not in PROGMEM, or you created a second full display buffer somehow.
Can I stream frames from an SD card?
Yes, but SD + file parsing on Uno is slow and fiddly for beginners. For class projects I still prefer fewer PROGMEM frames or an ESP32.
Does MicroPython on Pico have the same limit?
No — Pico has far more RAM/flash. Different platform, different budget. This article is specifically about classic AVR Uno/Nano.
Related
- SSD1306 animation playback
- ESP32 OLED guide (when Uno is too small)
- GIF to OLED — then trim frames
Preview frame count before you hit Uno limits
Build the animation in the browser, keep an eye on frame count, export Adafruit code.
Open the free tool →