My first post about this got removed because it was basically “look at my thing” without enough of the actual ESP32/build details. Fair enough, so here’s a better explanation of what’s going on inside it.
This started because I wanted a little screen I could leave next to me during a game instead of checking my phone every few minutes. I used a LAFVIN ESP32-S3 board with a built-in 1.69” 240x280 ST7789 display.
I picked that particular board mostly because it already combined the ESP32-S3, display, USB-C and LiPo charging on one small PCB. I knew I wanted the finished thing to be tiny, so avoiding a separate display board and charging circuit made the physical build a lot easier.
The display is driven with Arduino_GFX using the ESP32 SPI/ST7789 drivers. I originally just needed something that worked reliably with this board and gave me direct control over drawing the scoreboard UI, and it has done the job well enough that I never had much reason to move to a heavier UI framework.
The device runs off an internal 3.7V LiPo. I designed the enclosure around the PCB and battery and went through several prints getting that right. The first one didn’t hold the board securely, I managed to put some of the button access on the wrong side, and there were a bunch of smaller clearance problems that only became obvious once I had the actual print in my hand.
On the software side, I decided pretty early not to have the ESP32 talk directly to every sports/fantasy API.
There’s an iPhone app that handles the API calls, authentication, fantasy roster logic, etc. It reduces everything down to the small amount of information the display actually needs and sends that to the ESP over BLE.
A typical game update is basically just league, away/home team, away/home score, status and clock. The ESP receives that, keeps track of the current game/league and renders it.
That split has worked pretty well because the ESP doesn’t need to know anything about whether the original data came from an NFL feed, fantasy provider, golf leaderboard, etc.
BLE caused more trouble than I expected once I started using the thing normally. I had to fix queue/race issues between received packets and the rendering/navigation side, and at one point USB logging itself could block long enough to interfere with navigation and BLE callbacks. Those are the kinds of bugs I never saw when I was just sending one test packet at a time.
At this point it can show live sports scores, fantasy football scoring alerts and golf leaderboards. The fantasy part is probably my favorite — the phone knows my roster, so instead of sending every event happening in every game, it can surface an update when somebody I actually have scores.
I’m also experimenting with adding Wi-Fi as an alternate mode. I still don’t really want the ESP handling provider APIs and credentials itself, so the direction I’m leaning is having it connect to a backend that sends the same sort of small normalized payloads the phone does now. Bluetooth would still be there for people who want the phone-driven version.
Firmware and the current enclosure .3mf are here:
https://github.com/againstthespread/scrbrd
iPhone app:
https://github.com/againstthespread/scrbrd-mobile
There’s still plenty I want to clean up, but it has crossed the line from “prototype I can make display a score” to something I can actually leave running and use.
If anyone sees something in the ESP/BLE architecture that you’d have approached differently, I’m definitely interested. This project has mostly been me finding the next thing I didn’t know I needed to learn. Thinking about adding a wifi option for anyone wanting to keep it on their desk/in the same place instead of taking it with them.