
01 · Brief
The box from the authentication console holds three data disks, cardboard floppies for guidance, trajectory, and navigation, each with an RFID card inside. It also holds round cardboard tokens and a set of shorter logic games, one per disk. Solving a game on the cardboard grid tells the players which file on that disk is the right one.
Inserting a disk into the console scans the card and the LCD lists the files on it. The rotary encoder scrolls the list and a push loads the highlighted file. The wrong file throws an error on screen. The right one shows a successful upload and lights that disk’s blue LED.
With all three LEDs lit, the LCD confirms that navigation, guidance, and trajectory data are loaded and displays a success code. That code opens a physical lock on the next box.
02 · System
03 · Source
Escape_Game_Final_Floppydisc.ino
// STRUCTURES
// This data structure encapsulates all the properties associated with an individual file
struct file {
char fileName[16]; // The name for this file as will appear on the display
unsigned int fileSize; // From 0-65,535
unsigned long fileDate; // Timestamp
};
// This data structure contains info relating to each "disk" (RFID card) that is scanned
struct card {
byte rfidUID[4]; // Unique identifier of the RFID tag
file contents[4]; // The array of files this card contains
byte correctFileID; // The file that needs uploading from this disc
};
// CONSTANTS
// The number of different cards players can insert
const int numTags = 3;
// The number of files contained on each card
const byte numFiles = 4;
// Define the data held on each "disk"
//A37708DA, 43702BDA, 5C 7B E4 AF,8E 92 AF 9F
// nav is card A, guid is card Y, traj is card F
const card cardList[numTags] = {
{ {0x43,0x70, 0x2B, 0xDA}, { {"ORION.nav", 100, 1}, {"HERCULES.nav", 200, 1}, {"LEO.nav", 100, 1}, {"BOOTES.nav", 100, 1}, }, 3 },
{ {0x5C,0x7B, 0xE4, 0xAF}, { {"Alpha_6.guid", 300, 1}, {"Alpha_9.guid", 200, 1}, {"Alpha_3.guid", 100, 1}, {"Alpha_8.guid", 300, 1}, }, 1},
{ {0x8E,0x92, 0xAF, 0x9F}, { {"07685.traj", 400, 1}, {"52301.traj", 200, 1}, {"91254.traj", 100, 1}, {"82316.traj", 200, 1}, }, 2},
};
// GPIO pins attached to each component
// Rotary encoder/button
const byte encDataPin = 6; //sw
const byte encClockPin = 7; //dio
const byte buttonPin = 8; //clk
// Green LED that indicates floppy drive is active
const byte floppyLedPin = A0;
// Chip select line to the RFID reader
const byte rfidSS = 10; ///sck
// Blue LEDs that indicate which data has been loaded
const byte ledPins[] = {2, 3, 4};
// GLOBALS
// Initialise the LCD display (the HD44780 library auto-detects I2C address)
hd44780_I2Cexp lcd;
// Create an instance of the MFRC522 class, using the specified chip select pin
// We won't use a RST line, so set that to UINT8_MAX
MFRC522 rfid(rfidSS, UINT8_MAX);
// Is a disc currently inserted?
bool isDiscPresent = false;
// The index of the currently inserted disc
int8_t currentCard = -1;
// The file selected on the currently inserted disc
uint8_t selectedFile = 0;
// Timestamp at which we last checked whether disc was changed
unsigned long timeSinceLastScan;
// The cards whose data has been successfully loaded
bool dataLoaded[] = {false, false, false};04 · Lessons
I really, really wanted to use actual floppy disks with embedded RFID tags. Unfortunately I couldn't find any, so it had to be cardboard.
This game concept originated on the Playful Technology youtube channel and the majority of the code was written by Alastair Aitchison. I only did minor edits to match my game material. While I did the wiring here, the schematic I followed came from Playful technology.