🎨 ESP32-S3 · Sketch 005

Pixel Art Canvas
on the Touchscreen

Finger-draw on a 30×30 pixel grid with a 12-colour palette. Erase, clear, and save each painting to SD card as a 24-bit BMP file.

FT6336U Touch
🎨 12-Colour Palette
💾 SD Card BMP Save
🤖 Claude Sonnet 4.6
Session Transcript
Building the Pixel Canvas
Step 1 · Request
👤
Richard

i want to draw pixel art on the touchscreen. grid of pixels, colour palette, and i want to be able to save my drawings to the SD card

Claude

Layout plan: the 240×320 screen splits into a 30×30 drawing canvas (top 240 px, each pixel = 8×8 screen pixels — fills width exactly) and an 80 px toolbar at the bottom with a colour palette row and three buttons.

AreaY rangeContent
Canvas0–23930×30 grid, 8 px per cell
Palette row244–27112 colour swatches, 20 px wide each
Button row276–311ERASE · CLEAR · SAVE
Step 2 · Colour Palette
Claude

12 colours chosen to cover the primary/secondary spectrum plus a neutral grey:

BLACK, WHITE, RED, ORANGE, YELLOW, LIME,
DARK GREEN, CYAN, BLUE, PURPLE, MAGENTA, GREY

Selected colour gets a white border ring. The ERASE button toggles eraser mode (paints C_BG = black); while active it turns orange and the palette ring disappears — clear visual mode indicator.

Touch routing separates canvas draws from toolbar taps using a touchStartedInCanvas flag — prevents a finger dragging off the canvas from accidentally tapping a colour.

Step 3 · BMP Save to SD
👤
Richard

how does the BMP save work exactly?

Claude

The canvas stores 30×30 RGB565 values in SRAM. On SAVE, the sketch writes a valid 24-bit BMP directly to the SD card using SD_MMC (pins CMD=38, CLK=39, D0=40).

BMP quirks handled correctly:

  • Bottom-up row order — BMP stores rows from bottom to top, so rows are written in reverse
  • BGR byte order — BMP uses B G R not R G B
  • Row padding — rows padded to 4-byte boundary (30 px × 3 bytes = 90, padded to 92)
  • RGB565 → RGB888 conversion — 5-bit R/B expanded to 8-bit with (v5 << 3) | (v5 >> 2)

Files auto-numbered: canvas_001.bmp, canvas_002.bmp, … Scans SD to find the next free slot. A green SAVED! overlay confirms success; red SAVE FAILED if SD is not mounted.

// Auto-number: find next free canvas_NNN.bmp
for (int i = 1; i <= 999; i++) {
    snprintf(path, sizeof(path), "/canvas_%03d.bmp", i);
    if (!SD_MMC.exists(path)) return i;
}
✓ Valid 24-bit BMP Auto-numbered files Opens in any image viewer
Step 4 · Flash
Claude

Wrote flash-sketch-005-pixel-canvas.sh. Libraries: TFT_eSPI + FT6336U (touch) + SD_MMC (built into ESP32 Arduino core — no extra install).

./flash-sketch-005-pixel-canvas.sh

# Sketch uses 36% of flash, 14% of RAM
# Wrote 376832 bytes at 0x00010000 in 4.8 seconds
# Hash of data verified.
# Hard resetting via RTS pin...
✓ Compiled — 36% flash ✓ Flashed successfully Canvas ready to draw SD saves enabled
Session Summary
Claude — What We Built
FileWhat it does
sketches/pixel_canvas/pixel_canvas.ino30×30 touch pixel art editor with palette, erase, clear, SD BMP save
sketches/pixel_canvas/User_Setup.hTFT_eSPI pin config for FNK0086
flash-sketch-005-pixel-canvas.shFull compile + flash automation