Goal: make the ESP32-2432S028 (aka Cheap Yellow Display) draw pixels and respond to touch without lying to me.
Spoiler: it draws pixels. Eventually.
SPI situation (why are there two?)
Display and touch are not on the same SPI bus. Display = HSPI. Touch = VSPI. Nowhere obvious in the listing. No schematic in the box. TFT_eSPI assumes one bus. That was a dead end.
Switched to LovyanGFX. It lets you assign SPI hosts directly. That solved 80% of the pain.
// display on HSPI cfg.spi_host = HSPI_HOST; // touch on VSPI SPI.begin(25, 39, 32, 33); ts.begin();
After that: at least I had a black screen instead of nothing.
Black screen, but technically alive
Serial looked fine. init() returned. Still black. Backlight is on GPIO21. Defaults LOW. You must pull it HIGH before display.init().
pinMode(21, OUTPUT); digitalWrite(21, HIGH); display.init();
Once that went high: pixels. Very wrong pixels, but pixels.
Diagonal tearing / half-screen offset
Image split diagonally like a broken framebuffer. Turned out to be panel vs memory dimensions mismatch. ILI9341 RAM is 240x320. Board is mounted 320x240. LovyanGFX calculates offsets from those values. If they don’t match physical layout → chaos.
cfg.panel_width = 320; cfg.memory_width = 320; cfg.panel_height = 240; cfg.memory_height= 240; display.setRotation(4);
That fixed the split. Rotation 4 = rotation 0 + mirror. Feels wrong. Works.
RGB backwards
White text rendered blue. Red looked cyan. ILI9341 variant swaps color order.
cfg.rgb_order = true;
One boolean. 20 minutes of confusion.
Touch mapping (XPT2046 fun)
Touch panel mounted portrait inside landscape enclosure. Raw axes swapped and inverted. So p.x is basically screen Y (inverted). p.y is screen X.
TS_Point p = ts.getPoint(); int16_t sx = map(p.y, 300, 3800, 0, 320); int16_t sy = map(p.x, 3900, 200, 0, 240); sx = constrain(sx, 0, 319); sy = constrain(sy, 0, 239);
After calibration it behaves. Mostly.
End of Day 1 state
- Full-screen RGB565 backgrounds from LittleFS
- Theme JSON per background (accent + hero color)
- Swipe left/right to switch backgrounds
- On-screen touch keyboard for WiFi password
- WiFi connects + fallback on bad credentials
- Hero book count rendered on top
- OTA enabled over LAN
SD card shares VSPI with touch. CS juggling was annoying. Dropped SD. Using LittleFS in flash instead. ~2.5MB available with custom partition table.
app0, app, factory, 0x10000, 0x180000 spiffs, data, spiffs, 0x190000, 0x270000
Background frames: 320x240 RGB565 → 153,600 bytes each. About 16 fit comfortably.
Tooling
Wrote a small Python converter to batch PNG → raw .bin + .theme skeletons. No runtime decoding. Just stream to display.
python tools/convert_image.py img/ data/ pio run -e cyd --target uploadfs
Next
- Actual book list UI
- books.json schema in LittleFS
- Basic suggestion logic
Hardware is stable enough to build UI on top. Finally feels like a platform instead of a demo sketch.
Julia M
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.