Capstone · Embedded + Mobile

Interactive Gameboard

Capstone: hex-tile tabletop board with NFC figurines and a .NET MAUI controller app

Overview

A seven-hex tile module for tabletop play. Each hex has an RGB LED underneath and an NFC reader inside, so the board can light up terrain and recognize figurines placed on it. Characters live on NTAG215 tags glued under the figurine bases — no cloud, no accounts. A .NET MAUI phone app runs the game (character creation, terrain layout, turns, level-ups) and talks to the board over Wi-Fi. When a character levels up, the new stats get written back to the tag through the reader the figurine is sitting on. Built as my capstone project with a small team.

How it works

A Raspberry Pi Pico W runs the board firmware in MicroPython. It exposes a TCP socket and exchanges JSON messages with the MAUI app: which figurine is on which hex, which tile should be what color, write-back requests when a character's tag needs updating. Two phones can connect to the same server so both players see the same game state. LEDs are driven by a TLC5947 PWM driver over SPI because the Pico doesn't have enough native PWM channels for seven RGBs.

Technology Stack

Hardware

  • Raspberry Pi Pico W
  • RC522-mini NFC Readers
  • NTAG215 NFC Tags
  • TLC5947 PWM LED Driver (SPI)
  • RGB LEDs
  • 3D-Printed Components

Software

  • .NET MAUI Mobile App
  • MicroPython Firmware
  • TCP Sockets + JSON Messages
  • SPI Protocol
  • NFC/RFID Integration

Concepts

  • IoT / embedded networking
  • MicroPython multi-threading
  • Real-time sync over Wi-Fi
  • Mobile (.NET MAUI)

Project Media

Interactive Gameboard with hexagon tiles, NFC readers, and RGB LEDs

Architecture & Design Choices

MicroPython's threading is experimental and we hit it early. The first attempt put the socket server on a secondary thread so NFC polling could keep running on the main one. Clients dropped messages and connections got flaky. Inverting the split — server on the main thread, NFC polling on the worker — fixed it. The lesson was that "main thread" isn't ceremonial in MicroPython; the runtime treats it specially and you want your latency-sensitive work there.

I assumed the Pico's hardware PWM channels would cover seven RGB LEDs. They don't — that's twenty-one channels and the Pico has sixteen. The TLC5947 is a 24-channel constant-current PWM driver that takes SPI in and gives PWM out, which let me keep one bus to the board and offload all LED timing to the driver.

NFC reads off the RC522 mini are zone-tight — the figurine has to land squarely on the tile or the read misses. Inverting the readers under the printed caps got the antenna close to the tag, which helped, but placement is still something players learn rather than something the board forgives.

We wanted to fab a custom PCB to fold the wiring into the printed chassis, but the lead time on a board run didn't fit the capstone schedule. The shipped version has hand-wired connections between modules instead. It works, but it's the rough edge of the build.

What Works Today

One seven-tile module, end-to-end. Create a character in the app, write it to a blank tag, place the figurine on the board, and it gets recognized. The app drives terrain colors on the physical tiles, two phones can join the same session and stay in sync, and stat changes from in-app battles write back to the tag through the reader the figurine is sitting on. Good enough to demo; not productized.