<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu" -->

---
title: I connected a local LLM to a $30 ESP32 display, and it...
description: A hobbyist connected a self-hosted LLM agent (Hermes Agent, running on Proxmox) to a $30 Elecrow CrowPanel 1.46-inch round ESP32-S3 display, letting the agent...
canonical: https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: I connected a local LLM to a $30 ESP32 display, and it designs a new screen for every question I ask | daily.dev
og:description: A hobbyist connected a self-hosted LLM agent (Hermes Agent, running on Proxmox) to a $30 Elecrow CrowPanel 1.46-inch round ESP32-S3 display, letting the agent...
og:url: https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu
og:image: https://api.daily.dev/og/posts/HewzqePYU.png
og:image:alt: I connected a local LLM to a $30 ESP32 display, and it designs a new screen for every question I ask
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# I connected a local LLM to a $30 ESP32 display, and it designs a new screen for every question I ask

**[XDA Developers](https://daily.dev/sources/xda-developers)** · 10 min read · 0 upvotes · 0 comments

## Summary

A hobbyist connected a self-hosted LLM agent (Hermes Agent, running on Proxmox) to a $30 Elecrow CrowPanel 1.46-inch round ESP32-S3 display, letting the agent design a fresh HTML screen for any request, rendered via headless Chromium and pushed as a PNG screenshot to the panel. The writeup covers the architecture (content-addressed image caching with SHA-256, native fallback card types for simple data), and a firmware debugging saga where Elecrow's vendored LovyanGFX fork silently swaps in JD9855 init commands under an ST77961 class name, causing a blank screen when built against upstream LovyanGFX 1.2.7. Also covered: SPI clock and DMA transaction bugs causing stale pixel columns, and examples of the agent autonomously trimming headlines and prioritizing network scan results to fit the tiny display.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://www.xda-developers.com/connected-local-llm-esp32-display-designs-new-screen-every-question>

## Questions this post answers

### Why does my Elecrow CrowPanel ESP32 display stay black even though gfx.init() succeeds with upstream LovyanGFX?

Elecrow's example code instantiates lgfx::Panel_ST77961, but their product page lists a JD9855 controller. Their vendored repository forks LovyanGFX and replaces Panel_ST77961::getInitCommands() with a JD9855 init sequence. Building against real upstream LovyanGFX 1.2.7 sends a valid ST77961 init list that the JD9855 controller accepts but cannot execute, leaving the screen black with no error reported anywhere.

_Debugging obscure display driver mismatches like this is easier when daily.dev surfaces others' ESP32 firmware writeups._

### Why does my LovyanGFX ESP32 display show vertical columns of stale pixels?

This happens when startWrite() is called once and never properly closed per frame, because LovyanGFX only waits for DMA completion on the outermost endWrite(), so pushes race against the prior transfer. Running SPI at 80MHz can also cause bits to arrive late on some clock edges; dropping the bus speed to 40MHz resolved the stale column artifacts on a CrowPanel 1.46 build.

_Track down DMA and SPI timing quirks like this by following hands-on ESP32 hardware projects on daily.dev._

### How can an LLM agent generate dynamic screens for a small ESP32 display without reflashing firmware?

An agent can write each screen as HTML, have a headless Chromium instance render it at the exact panel resolution (360x360), screenshot it as a PNG, and push that image over the local network to the display, which simply stores and shows it. This decouples screen design from firmware, so adding a new screen type requires no reflash, only CSS skill from the model.

_Following practical local-LLM hardware integrations on daily.dev helps when designing agent-driven displays._

## Similar posts on daily.dev

- [Elecrow CrowPanel Advanced HMI Display Review: A Tinkerer's Touchscreen](https://daily.dev/posts/elecrow-crowpanel-advanced-hmi-display-review-a-tinkerer-s-touchscreen-9akh9nkvh) · It's Foss · 0 upvotes · 0 comments
- [This $35 ESP32 touchscreen makes Meshtastic feel less like a commitment, and you still get a great display if it doesn't stick](https://daily.dev/posts/this-35-esp32-touchscreen-makes-meshtastic-feel-less-like-a-commitment-and-you-still-get-a-great-d-wqrhhyhac) · XDA Developers · 0 upvotes · 0 comments
- [An ESP32-S3 desktop display that tracks AI coding assistant usage \(Crowdfunding\)](https://daily.dev/posts/an-esp32-s3-desktop-display-that-tracks-ai-coding-assistant-usage-crowdfunding--1qrljcbuc) · CNX Software · 0 upvotes · 0 comments
- [Build a Local AI Agent Terminal With OpenClaw and DGX Spark](https://daily.dev/posts/build-a-local-ai-agent-terminal-with-openclaw-and-dgx-spark-j0iukwall) · Callstack Blog · 1 upvotes · 0 comments
- [A Cheap And Easy Control Screen For Home Assistant](https://daily.dev/posts/a-cheap-and-easy-control-screen-for-home-assistant-rb9h4sswz) · Hackaday · 0 upvotes · 0 comments

---

Tags: [#llm](https://daily.dev/tags/llm), [#iot](https://daily.dev/tags/iot)

[View this post on daily.dev](https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"I connected a local LLM to a $30 ESP32 display, and it designs a new screen for every question I ask","url":"https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu"},"datePublished":"2026-08-23T00:04:11.250Z","dateModified":"2026-08-23T00:04:49.489Z","description":"A hobbyist connected a self-hosted LLM agent (Hermes Agent, running on Proxmox) to a $30 Elecrow CrowPanel 1.46-inch round ESP32-S3 display, letting the agent...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ed06c062d0f509b613a1af7b775e876f?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/ed06c062d0f509b613a1af7b775e876f?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"XDA Developers","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"XDA Developers","logo":"https://media.daily.dev/image/upload/s--kCg6yyAP--/f_auto,q_auto/v1774964407/logos/xda-developers?_a=BAMAMiWQ0","url":"https://daily.dev/sources/xda-developers"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"llm,iot","timeRequired":"PT10M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"XDA Developers","item":"https://daily.dev/sources/xda-developers"},{"@type":"ListItem","position":3,"name":"I connected a local LLM to a $30 ESP32 display, and it designs a new screen for every question I ask"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/i-connected-a-local-llm-to-a-30-esp32-display-and-it-designs-a-new-screen-for-every-question-i-ask-hewzqepyu#faq","mainEntity":[{"@type":"Question","name":"Why does my Elecrow CrowPanel ESP32 display stay black even though gfx.init() succeeds with upstream LovyanGFX?","acceptedAnswer":{"@type":"Answer","text":"Elecrow's example code instantiates lgfx::Panel_ST77961, but their product page lists a JD9855 controller. Their vendored repository forks LovyanGFX and replaces Panel_ST77961::getInitCommands() with a JD9855 init sequence. Building against real upstream LovyanGFX 1.2.7 sends a valid ST77961 init list that the JD9855 controller accepts but cannot execute, leaving the screen black with no error reported anywhere. Debugging obscure display driver mismatches like this is easier when daily.dev surfaces others' ESP32 firmware writeups."}},{"@type":"Question","name":"Why does my LovyanGFX ESP32 display show vertical columns of stale pixels?","acceptedAnswer":{"@type":"Answer","text":"This happens when startWrite() is called once and never properly closed per frame, because LovyanGFX only waits for DMA completion on the outermost endWrite(), so pushes race against the prior transfer. Running SPI at 80MHz can also cause bits to arrive late on some clock edges; dropping the bus speed to 40MHz resolved the stale column artifacts on a CrowPanel 1.46 build. Track down DMA and SPI timing quirks like this by following hands-on ESP32 hardware projects on daily.dev."}},{"@type":"Question","name":"How can an LLM agent generate dynamic screens for a small ESP32 display without reflashing firmware?","acceptedAnswer":{"@type":"Answer","text":"An agent can write each screen as HTML, have a headless Chromium instance render it at the exact panel resolution (360x360), screenshot it as a PNG, and push that image over the local network to the display, which simply stores and shows it. This decouples screen design from firmware, so adding a new screen type requires no reflash, only CSS skill from the model. Following practical local-LLM hardware integrations on daily.dev helps when designing agent-driven displays."}}]}
```

