Перейти к содержимому
Все проекты
08 · DRIVER LIBRARIES · ELECTRONICS FOR A ROLE-PLAYING GAMEНа сайт

Someday: 11 driver libraries that powered the devices at the 2026 game

Стек:

  • C++
  • Arduino
  • ESP32
  • FreeRTOS
  • PlatformIO
  • MFRC522
  • PN532
  • NDEF
  • TinyGPSPlus
  • ArduinoJson
  • FastLED
  • U8g2
  • OneButton

использовал я

Роль
All the software, libraries author
Команда
3 people: software, hardware, enclosures
Срок
Since January 2025, libraries since October 2025
Статус
In development, field-tested at the 2026 game

What I did

  • The someday-lib coreFreeRTOS tasks, thread-safe state, serializable game effects and RFID on RC522 for Mifare Classic and Ultralight cards.
  • Module driversButtons, LEDs, an addressable LED strip, the battery, a display with Cyrillic, Wi-Fi, GPS, RFID on PN532 and a Serial console with commands.
  • Library architectureShared modules versioned with git tags instead of copied code in every firmware. Arduino and PlatformIO were my choice as well.
  • Rules for the AI assistantClaude Code helps me make sense of C++ and writes separate pieces. For it I made the someday-guard plugin with hooks and rules: a driver template is created quickly, and I review and finish it myself.

Context and starting point

The project

KB Someday is a team of enthusiasts building electronics for a S.T.A.L.K.E.R. field role-playing game in the Urals. The project is non-commercial and has no external client: tasks come from the game idea of the location.

There are three of us: I write all the software, the second member handles the hardware (circuits, soldering, assembly), and the third makes the enclosures. The libraries are used by the firmware of the game devices, and the devices are used by players on the field.

Situation

At first every device was written from scratch, and code repeated from firmware to firmware: buttons, LEDs, RFID, communication. I moved the shared code into the someday-* libraries, and a new device started coming together from ready-made modules faster.

Field conditions

  • POWERBattery

    A device has to run for several days on a battery, so we save power: sleep, turning off the backlight.

  • OFFLINENo internet

    There is no internet and no stable Wi-Fi on the field. Devices work on their own or talk to each other directly.

  • FIELDOutdoors and players

    Debouncing, protection against careless handling, fast recovery after a failure.

  • BUDGETSmall budget

    Cheap modules, ESP32 and Chinese sensors.

Goal

Make the role-playing game more varied with our own devices and build every new device from ready-made modules instead of writing it from scratch.

Process, architecture and decisions

Architecture

The libraries split into a core and module drivers. They all follow the same rules, so modules from different libraries live together in one firmware without extra work.

  • COREThe someday-lib core

    FreeRTOS tasks on CRTP, a value with a lifetime behind a mutex, serializable game effects: radiation and psi healing, a timer, death, revival and reset. RFID on RC522 with strategies for Mifare Classic and Ultralight.

    • Task<Derived>
    • Singleton
    • GuardedState<T>
    • EffectData
  • DRIVERSModule drivers

    Several buttons in one firmware, an LED, a WS2812B addressable strip with the pin as a template parameter, a battery with a mock mode, a thread-safe 128×64 display with Cyrillic and PWM backlight, Wi-Fi in access point and client modes, GPS, RFID on PN532, a Serial console with commands, BLE artifact types.

    • someday-button
    • someday-diod
    • someday-address-led
    • someday-accumulator
    • someday-display
    • someday-wifi
    • someday-gps
    • Someday_RFID
    • Someday_SerialCommander
    • someday-types
  • CONVENTIONSShared rules

    Every module has its own namespace. Modules are guarded by mutexes and never block: process() is called from the loop or from a task. Built through library.json for PlatformIO, versions on git tags.

    • someday::<module>
    • process()
    • library.json

What the devices are built from

The firmware of six game devices runs on the libraries: a dosimeter, a scanner, a geo-tagger, a PKS, a BLE artifact with a detector and a master device for RFID cards. Below is what each firmware pulls in.

  • SOMEDAY-LIBCore
    • device-uyut
    • device-scanner
    • device-candle
    • rfid-tool
  • MODULESGPS, Wi-Fi, buttons, light, Serial console
    • device-uyut
    • device-scanner
    • device-candle
  • DISPLAY · POWERDisplay and battery
    • device-uyut
    • device-candle
  • RFIDSomeday_RFID
    • device-uyut
    • rfid-tool
  • SOMEDAY-TYPESBLE artifact types
    • device-artefact
    • device-otklick

Hardware and buses

  • MCUESP32-S3 and ESP32-C3

    Including ESP32-S3 N16R8 with PSRAM.

  • RFIDRC522 and PN532

    RC522 over SPI, PN532 over UART.

  • GPSAT6558 / GP-02

    UART at 9600 baud, NMEA and CASIC commands.

  • DISPLAYJLX12864G-086

    128×64 on the ST7567 controller, software SPI, PWM backlight.

  • LIGHTWS2812B and LEDs

    The addressable strip through FastLED, buttons through OneButton.

  • POWERTwo 18650 batteries

    Voltage is read through a divider on the ADC: 1250–2100 mV map to 0–100 %.

Why Arduino and PlatformIO

The project was my way into embedded; before that I worked on the web. Arduino and PlatformIO give a fast start and plenty of ready-made libraries: for an embedded newcomer it is the fastest path.

Along the way I learned C++ for microcontrollers, ESP32, FreeRTOS, buses and datasheets. Claude Code helped me make sense of C++.

Integrations

  • MFRC522
  • PN532 + NDEF
  • TinyGPSPlus
  • ArduinoJson
  • FastLED
  • U8g2
  • OneButton

подключал я

Third-party libraries talk to the hardware directly, and someday-* wrap them into modules with shared rules.

Quality and releases

For someday-lib I wrote Unity unit tests, about 1800 lines, which run right on the device. MockGps and the battery mock mode help to debug without hardware.

Everything else was tested by hand, in three stages.

  1. 01BenchWe assemble the device and run scenarios through the SerialCommander Serial console and mocks
  2. 02Field testA check on location before the game
  3. 03GameThe final check at the 2026 game

The libraries are versioned with git tags: someday-gps v2.1.0, Someday_RFID v1.1.0, the rest v1.0.x. Devices pin a version by tag or commit, so a new library version does not change firmware that is already built.

Every library has a README in Russian, and RFID and SerialCommander also have one in English. The someday-gps README runs to 670 lines.

Challenges

One RFID bus for several tasks

Проблема
Several FreeRTOS tasks worked with the PN532 reader over one UART, and the ACK responses got mixed up.
Решение
I put one mutex on the whole Someday_RFID driver. Player data is written to the card as an NDEF record through the templated write<T> and read<T>.
Итог
We found the problem on the bench while debugging, before the game. At the game RFID worked reliably.

Type-safe writes to the card

Проблема
Game data is written to the players' RFID cards, and the firmware must not write anything to a card that cannot be read back.
Решение
In someday-lib, readData<T> and writeData<T> accept only serializable POD types through SFINAE and static_assert. After a write the data is verified by reading it back.
Итог
An unsuitable type will not compile: the error shows up at build time, not on the field.

Metrics and results

  • 11someday-* driver libraries
  • 6game device firmwares built on them
  • 18–20 hof device runtime on two 18650s with no optimizations
  • ~30players went through the location's quests

At the 2026 game the team played as the Clear Sky faction: a game-tech location with a set of devices built on these libraries, 2–3 units of each. A chain of quests led players through working with different devices, and players spoke well of both the location and the devices.

I came to embedded from the web and wrote driver libraries that devices ran on at a real game. Today I would study the theory more closely at the start and maybe pick C or Rust instead of Arduino: Arduino has a number of serious limitations when working with controllers, and rewriting a finished ecosystem is now expensive.

Need firmware for an ESP32 device or drivers for your own hardware?

I will build C++ and FreeRTOS firmware from modules: RFID, GPS, display, LEDs, Wi-Fi.