Life Support System

Life Support System

This tutorial creates a spacecraft life support control panel using four toggle switches and LED indicators. This logic puzzle challenges players to activate systems in the correct sequence to restore life support. Each switch affects multiple systems in different patterns, requiring careful observation and logical deduction to solve. Features dual-color LED feedback and serial communication for integration with escape room control systems.

Gameplay Mechanics

The Challenge

Players must toggle switches into ON / OFF positions. Changing each toggle switch, changes the pattern of the red and green LEDs. Players need to discover the correct ON / OFF combination for the four switches.

With 2 positions per switch, there are 16 possible combinations (24), making brute forcing the puzzle a likely option.

How Players Interact

  • Observe initial state: All systems show red (offline)
  • Test switches: Flip each switch to see which LEDs it affects
  • Map relationships: Create a mental model of switch-to-LED connections
  • Execute solution: Flip switches in the correct sequence
  • Verify success: All green LEDs indicate life support restored

Required Components

Hardware

  • 1x Arduino Uno R3
  • 4x Toggle switches (SPDT)
  • 4x Red LEDs (5mm)
  • 4x Green LEDs (5mm)
  • 8x 220Ω resistors (for LEDs)
  • Jumper wires
  • Breadboard

Software Requirements

  • Arduino IDE (1.8.0 or later)

Wiring Diagram

Life Support System wiring diagram

Switch 1

  • Switch Common → A5
  • Switch Terminal A → GND
  • Switch Terminal B → Internal pull-up enabled
  • Green LED → Pin 2
  • Red LED → Pin 3

Switch 2

  • Switch Common → A3
  • Switch Terminal A → GND
  • Switch Terminal B → Internal pull-up enabled
  • Green LED → Pin 4
  • Red LED → Pin 5

Switch 3

  • Switch Common → A2
  • Switch Terminal A → GND
  • Switch Terminal B → Internal pull-up enabled
  • Green LED → Pin 6
  • Red LED → Pin 7

Switch 4

  • Switch Common → A20
  • Switch Terminal A → GND
  • Switch Terminal B → Internal pull-up enabled
  • Green LED → Pin 8
  • Red LED → Pin 9

LED Configuration

  • All LED anodes → through 220Ω to pins
  • All LED cathodes → GND

Serial Communication

  • Used for debugging
  • Reset command: "RESETQ"
  • JSON output sent to Escape Room server
Important: Each switch affects multiple LEDs! Switch 1 toggles LED 1, Switch 2 toggles LEDs 1 & 3, Switch 3 toggles LEDs 2 & 3, and Switch 4 toggles LEDs 1 & 4. This interconnection creates the puzzle logic.

The Code

1Define Constants and Variables

Set up the pin assignments and state tracking variables:

const String shortName = "LIFE";

// SWITCHES AND LEDs
// Switch 1
const int BTN1 = A5;
const int GRN1 = 2;
const int RED1 = 3;
int RED1_state = 1;  // Start with red ON (system offline)
int GRN1_state = 0;  // Start with green OFF
int btn_1_state = 0;
int btn_1_old = 0;

// Switch 2
const int BTN2 = A3;
const int GRN2 = 4;
const int RED2 = 5;
int RED2_state = 1;
int GRN2_state = 0;
int btn_2_state = 0;
int btn_2_old = 0;

// Switch 3
const int BTN1 = A2;
const int GRN1 = 6;
const int RED1 = 7;
int RED1_state = 1; 
int GRN1_state = 0;  
int btn_1_state = 0;
int btn_1_old = 0;

// Switch 4
const int BTN2 = A0;
const int GRN2 = 8;
const int RED2 = 9;
int RED2_state = 1;
int GRN2_state = 0;
int btn_2_state = 0;
int btn_2_old = 0;

int LED_setup = 0;        // Initialization flag
int victoryAchieved = 0;  // Track if puzzle is solved

Variable organization:

Button pins: Using analog pins as digital inputs (A0, A2, A3, A5) for the switches.

LED pairs: Each system has a red LED (offline) and green LED (online) for clear status indication.

State tracking: Separate variables track current and previous button states for edge detection.

Victory flag: Prevents sending redundant "unsolved" messages before first solution.


2Setup Function

Initialize all pins and serial communication:

void setup() {
    // Configure all button pins with internal pull-up resistors
    pinMode(BTN1, INPUT_PULLUP);
    pinMode(RED1, OUTPUT);
    pinMode(GRN1, OUTPUT);  
    
    pinMode(BTN2, INPUT_PULLUP);  
    pinMode(RED2, OUTPUT);
    pinMode(GRN2, OUTPUT);
    
    pinMode(BTN3, INPUT_PULLUP);  
    pinMode(RED3, OUTPUT);
    pinMode(GRN3, OUTPUT);
    
    pinMode(BTN4, INPUT_PULLUP);  
    pinMode(RED4, OUTPUT);
    pinMode(GRN4, OUTPUT);

    Serial.begin(9600);
}

Setup explained:

INPUT_PULLUP: Enables internal pull-up resistors, eliminating the need for external resistors.

LED outputs: All 8 LEDs configured as outputs for direct digital control.

Serial communication: 9600 baud rate for compatibility with most serial monitors and systems.


3Switch Logic Implementation

Each switch affects different combinations of LEDs, creating the puzzle logic:

Switch 1 - Toggles LED 1 Only

/* SWITCH 1 TOGGLE FUNCTION */
if(btn_1_state != btn_1_old){
    // Toggle LED 1
    RED1_state = !RED1_state;
    GRN1_state = !GRN1_state;
    digitalWrite(GRN1, GRN1_state);
    digitalWrite(RED1, RED1_state);        
    btn_1_old = btn_1_state;

    sendUpdate(shortName, "UPDATE", btn_1_state, btn_2_state, 
               btn_3_state, btn_4_state, "1", "false");
    checkVictory(GRN1_state, GRN2_state, GRN3_state, GRN4_state);   
}

Switch 2 - Toggles LEDs 1 and 3

/* SWITCH 2 TOGGLE FUNCTION */
if(btn_2_state != btn_2_old){
    // Toggle LED 1
    RED1_state = !RED1_state;
    GRN1_state = !GRN1_state;
    digitalWrite(GRN1, GRN1_state);
    digitalWrite(RED1, RED1_state);
    
    // Toggle LED 3
    RED3_state = !RED3_state;
    GRN3_state = !GRN3_state;
    digitalWrite(GRN3, GRN3_state);
    digitalWrite(RED3, RED3_state);        
    btn_2_old = btn_2_state;
}

Switch 3 - Toggles LEDs 2 and 3

/* SWITCH 3 TOGGLE FUNCTION */
if(btn_3_state != btn_3_old){
    // Toggle LED 2
    RED2_state = !RED2_state;
    GRN2_state = !GRN2_state;
    digitalWrite(GRN2, GRN2_state);
    digitalWrite(RED2, RED2_state);
    
    // Toggle LED 3
    RED3_state = !RED3_state;
    GRN3_state = !GRN3_state;
    digitalWrite(GRN3, GRN3_state);
    digitalWrite(RED3, RED3_state);
}

Switch 4 - Toggles LEDs 1 and 4

/* SWITCH 4 TOGGLE FUNCTION */
if(btn_4_state != btn_4_old){
    // Toggle LED 1
    RED1_state = !RED1_state;
    GRN1_state = !GRN1_state;
    digitalWrite(GRN1, GRN1_state);
    digitalWrite(RED1, RED1_state);
    
    // Toggle LED 4
    RED4_state = !RED4_state;
    GRN4_state = !GRN4_state;
    digitalWrite(GRN4, GRN4_state);
    digitalWrite(RED4, RED4_state);
}

4Victory Checking and Reset

Monitor for success condition and handle remote reset commands:

// Function to check for victory condition
void checkVictory(int btn1, int btn2, int btn3, int btn4){
    if(btn1 == 1 && btn2 == 1 && btn3 == 1 && btn4 == 1){
        // All systems online - puzzle solved!
        Serial.println("{\"shortName\":\"" + shortName + 
                         "\",\"type\":\"SOLVE\",\"solved\":true}");
        victoryAchieved = 1;
    } else if(victoryAchieved == 1){
        // Was solved but now isn't - send unsolved message
        Serial.println("{\"shortName\":\"" + shortName + 
                         "\",\"type\":\"SOLVE\",\"solved\":false}");
    }
}

// Programmatic reset function
void(* resetFunc) (void) = 0; // Reset function at address 0

// Check for reset command in main loop
if(victoryAchieved == 1){
    if(Serial.available()){
        thisChar = Serial.read();
        if(thisChar != 'Q'){
            incomingString += thisChar;
        } else {
            if(incomingString == "RESET"){
                resetFunc(); // Call reset function
            }
        }
    }
}

Victory and reset logic:

Success condition: All four green LEDs must be on (all systems online).

JSON output: Sends structured messages for integration with escape room control systems.

Software reset: Responds to "RESETQ" command to restart the puzzle remotely.

State tracking: Only sends "unsolved" message if puzzle was previously solved.


5Main Loop and LED Initialization

The main loop handles initialization and continuous monitoring:

void loop() {
    // Set initial LED values: Red on, Green off
    if (LED_setup == 0) {
        digitalWrite(RED1, HIGH);
        digitalWrite(GRN1, LOW);
        digitalWrite(RED2, HIGH);
        digitalWrite(GRN2, LOW);
        digitalWrite(RED3, HIGH);
        digitalWrite(GRN3, LOW);
        digitalWrite(RED4, HIGH);
        digitalWrite(GRN4, LOW);
        LED_setup = 1;
        
        // Send initialization message
        sendUpdate(shortName, "INITIATION", btn_1_state, btn_2_state, 
                   btn_3_state, btn_4_state, "-", "false");
    }
    
    // Read button states
    btn_1_state = digitalRead(BTN1);
    btn_2_state = digitalRead(BTN2);
    btn_3_state = digitalRead(BTN3);
    btn_4_state = digitalRead(BTN4);
    
    // Switch logic checks here...
    
    delay(200); // Debounce delay
}

Testing Your Life Support System

1Understanding the Solution

The puzzle solution requires all four green LEDs to be on. Based on the switch logic:

Solution Analysis:

Starting from all LEDs red (offline), the optimal sequence is:

  • Flip Switch 3 - HIGH: Turns on LEDs 2 and 3 (green)
  • Flip Switch 4 - HIGH: Turns on LEDs 1 and 4 (green)

Result: All four systems online with just two switch flips!

Why this works:

  • Switch 3 affects LEDs 2 & 3 - both start red, so both turn green
  • Switch 4 affects LEDs 1 & 4 - both are still red, so both turn green
  • No LED is toggled twice, so all end up green

2Hardware Test Sketch

Test your wiring with this simple verification sketch:

void setup() {
    Serial.begin(9600);
    
    // Configure all pins
    for(int pin = 2; pin <= 9; pin++) {
        pinMode(pin, OUTPUT);
    }
    
    pinMode(A0, INPUT_PULLUP);
    pinMode(A2, INPUT_PULLUP);
    pinMode(A3, INPUT_PULLUP);
    pinMode(A5, INPUT_PULLUP);
    
    // Test all LEDs
    Serial.println("Testing all LEDs...");
    for(int pin = 2; pin <= 9; pin++) {
        digitalWrite(pin, HIGH);
        delay(200);
        digitalWrite(pin, LOW);
    }
}

void loop() {
    // Print button states
    Serial.print("Buttons: ");
    Serial.print(digitalRead(A5));
    Serial.print(" ");
    Serial.print(digitalRead(A3));
    Serial.print(" ");
    Serial.print(digitalRead(A2));
    Serial.print(" ");
    Serial.println(digitalRead(A0));
    delay(500);
}

3Troubleshooting Common Issues

LED Problems

  • Check LED polarity (long leg = anode)
  • Verify 220Ω resistors are connected
  • Test LEDs with simple blink sketch
  • Ensure common ground connections
  • Try swapping red/green if colors reversed

Switch Issues

  • Verify pull-up resistors are enabled
  • Ensure switches connect to ground
  • Try external 10kΩ pull-ups if needed

Logic Not Working

  • Verify switch-to-LED mapping
  • Check state variables are updating
  • Add Serial.print debugging
  • Ensure 200ms debounce is sufficient
  • Test each switch individually first

Possible Enhancements

Timer System

Add a countdown timer that triggers an alarm if life support isn't restored quickly enough, increasing pressure on players.

LCD Display

Connect an I2C LCD and add system names and status messages like "OXYGEN CRITICAL" or "TEMPERATURE STABLE".

Randomized Logic

Implement different switch-to-LED mappings that change each game, preventing memorization of solutions.

Progressive Difficulty

Start with 3 systems and add the 4th after initial success, or change the logic patterns between rounds.

Status Display

Add a 7-segment display showing the number of systems online (0-4) for quick status reference.

Get in touch!

We are currently looking for educators and students to collaborate with on future projects.

Get in Touch!

hello@escapehumber.ca