This post is mostly a placeholder until I can update it. For now please check the main website https://gen.polyb.io

This page will contain more information about how the game works. Some useful links to the information already published.

Code used in the game (as of a week ago, the live code has changed a bit since then) https://github.com/Trikkitt/polygen

The code behind the PolyGen website. It is Jekyll based but the player portal uses javascript quite a bit to interface with the game system. https://github.com/Trikkitt/trikkitt.github.io

Game Architecture

The main building blocks of the game are:

  • The main game units deployed across the site consisting of a 3D printed case, custom PCB using an PIC microcontroller, ESP8285, DFR299 MP3 Player, RC522 RFID Reader, two neopixel strips, speaker and three 18650 batteries.
  • RaspberryPi 4 running the game consisting of an MQTT server, the game server Python script, MariaDB for storing the game details, Metabase to provide the game stats visualisation.
  • RaspberryPi running the scoreboard. This consists of a Python script using PyGame to draw the scoreboard, getting its updates via MQTT.
  • Github Pages hosting a static Jekyll website with some javascript code to provide the interactivity back to the game server via MQTT.

All the communications between components is via MQTT, with the access to MQTT locked down so that only certain topics are available for each type of client. For example the game units can submit messages on the topic /DISCS/FROM but they can only read from /DISCS/TO. You’ll find many mentions of “discs” throughout the code and documentation because originally they were circular designs, and branded PolyCoin, much of that game forms part of this one, including the PCBs!

Some topics such as the scoreboard topic are accessible via anonymous connection, giving players an option to see real-time data if they want to get into the techy side of it a bit. It would be possible to monitor for captures so you know when you’ve lost control of a unit.

Game Units

I’ll try and add some photos to help with this, but for now here is a description of the various parts and why they were setup the way they have been.

There were two driving decisions behind component selection, power management and cost. I needed to keep the component cost as low as possible to make it viable to create many units. I also needed to keep power usage down so it didn’t need lots of batteries.

The main “brain” of the unit is the PIC Microcontroller 16LF15356. The main reason behind this is power management. These processors are very low powered and can go into a very low power sleep state when idle. By making this the primary processor much of the house keeping activities can be completed without using a lot of power. The processor’s main loop consists of waking up, turning on the RFID reader and checking if a card is present, updating any LED animations required, then going back to sleep.

Most components can be power controlled by the PIC, this includes turning off power to each of the two neopixel strips and the MP3 player via FETs, using the shutdown line to the RFID reader, and using the power management of the ESP8285 to enter a sleep state. Even the power to the PIC is controlled by driving the enable pin of the power circuit. So if the PIC wishes to turn itself off it will actively drive the enable pin the other way and cut the power.

There are three 18650 lithium ion batteries connected in parallel. They then pass through a self-resetting fuse before entering the power regulation circuit, which is tuned to about 3.2 volts. With the exception of the neopixel strips everything runs from the that 3.2 volt circuit. The neopixels run directly from the battery (via the fuse). The power supply will regulate down to 3.2 volts but if the battery voltage drops below that then it will track the battery voltage as it drops with a safety cut-off at 2.5 volts to prevent damage to the cells. The PIC has its own battery voltage monitoring via a high impedance voltage divider, should it detect that the battery voltage is below 3.15v it will power itself off to help protect the batteries, but also because below this voltage the MP3 player starts failing to operate. The batteries are charged via a USB-C port on the back of the unit, this a simple LithiumIon battery charger module and connects straight to the batteries on the PCB.

A reason for the selection of this particular microcontroller model is that has in hardware two synchronous serial interfaces and two asynchronous serial interfaces, along with a Configurable Logic Cell (CLC) that can be made to do some quite clever stuff. These interfaces can be interrupt driven, allowing the PIC to maintain simultaneous communications with the RFID reader, MP3 player, ESP8285 and drive the Neopixel strings all at the same time! The RFID reader uses a normal SPI interface, the MP3 player communicates using serial along with a busy line signal, the ESP8285 communicates via serial, and the second SPI interface is combined with a hardware timer and PWM via a CLC to create the native Neopixel protocol signal. When creating a new frame of the pixel animation it places the frame content into the output buffer and signals to the SPI interface to commence sending, the hardware along with a simple interrupt route to keep the hardware output buffer full will transmit the frame while the process is off completing other activities.

The RC522 RFID reader was selected not because it is a great reader (it is probably one of the most basic available), but because it was cheap and readily available. I later found just how variable the quality of these boards can be. All the main processors are clones, and many of the supporting components are substandard. I wrote a separate article on replacing the inductors because the standard ones are too low power to work with anything beyond the very basic MiFare Classics. For my devices I removed the power LED as that just wastes power as it sits between the 3v and GND pins, so doesn’t tell you anything useful anyway. I also removed the pull-up resistor on the shutdown pin as my PIC drives that directly and so doesn’t need to waste power when driving against the resistor. I find these readers to work reasonably well, sometimes placing a card to close can cause it to not read the card. But I find in general they’re pretty good at reading cards, they have a few more issues if its an embedded RFID under the skin or a ring (it will read them, just can sometimes take a while).

The DFRobot DF299 MP3 player is available very cheaply as a clone, it actually costs more for the MicroSD card to go in them. There is special protocol to talk to these units that is fairly simple, you just give it the index of the file you wish to play, and off it goes and plays it. There are some significant drawbacks with these modules, the main one being that they’re slow. Powering up and playing the first track can take a couple of seconds, and there isn’t much you can do about that. There is also a second of delay from when you receive the notification of a track ending, immediately sending the command for which track to play next, and the sound starting. This was mitigated via a few things, merging multiple sound clips together even if that meant more sounds, so rather than splitting “Redirecting power to” and then have 4 different team names, instead have 4 different clips each with the team name, for example “Redirecting power to Polybius Biotech”. If a sound clip is already playing and you tell it to play a new clip then the gap between them is far shorter, although there is a noticeable silence it is very short. An example of this is the “Bringing generator control systems online…” which then has a rumbling sound effect that is actually very long, when the response is received from the game server the clip is cut short by playing the next sound required.

The ESP8285 is a part many will think “huh what is that? surely you mean an ESP8266”. Well no, I don’t! These are essentially an ESP8266 but with the EPROM integrated rather than off-chip as they are on the ESP8266. The reason why I opted for this is mostly around quality, I had lots of ESP8266 supplied with terrible EPROM quality. Some would fail after only a few writes, some would corrupt the storage, some would simply not work. Because the ESP8285 includes the EPROM you know it’ll be good quality. It has the added advantage of being smaller. I also opted for off-board antennas. The little ceramic or track-trace antennas work OK for short range applications with little competition between units, stick them in a field filled with WiFi devices and you need a decent strength antenna to ensure good communications. The ESP8285 run Micropython, however because of the memory constraints present on these parts the scripts have to be compiled before loading onto the modules. The Micropython code handles all the server communication, dealing connecting to WiFi, communication with MQTT to the server, validating server messages using a SHA256 hash to confirm integrity, then communicating with the PIC where appropriate. The unit identifies itself by the serial number of the ESP8285 module and stores all its configuration within the module. Live state information though stays within the PIC, as the ESP8285 is turned off when WiFi communication isn’t required. While it could have been used to run the Neopixels or check the battery voltage, that these can be managed by the PIC avoids having to power up the ESP8285 except for when WiFi is required.