Escape Room - Webclient - Arduino + Ethernet

Escape Room is an interesting way of spending time and having fun. Can torment brain threads in puzzles, digital tasks by solving which players progress in the game. I also decided to put in the Escape Room an interactive way of entering the code in the room. Arduino has five buttons for sending / changing numbers (depending on the implementation). The buttons are debugged via the millis () timer function; with debounter time (treatment of button flickers) 50 ms. The input method of the buttons is in the initial value INPUT_PULLUP, when they are connected to the 5V by an internal pullup resistor. They're turning against the ground. Switches are used, not expandable.

The LCD display is used to represent the entered numbers from the user with their real-time visualization. It is possible to use LCD 20x4 / 16x2 with I2C converter. The statement is only executed on 2 lines.

The display also shows the address on the LAN, indicating connectivity or a network problem. Arduine is plugged Ethernet shield W5100 from Wiznet, which via HTTP protocol communicates over the network with the webserver, which sells the entered number from the user.

Datas are transferred by the POST method. The answer of the server is payload with confirmation / rejection of the received number.


Confirmation is performed if the correct code is guessed. The result of the confirmation is the unlocking of the door by means of an electromagnetic relay which controls the solenoid door lock. It is also possible to use the SSR relay if the solenoid door lock is on AC voltage. (SSR relays have a problem with opening the DC voltage circuit - see triac in the frequently used relay OMRON G3MB-202P.) The relay is switched by reverse logic, ie. active low. At 5V (log 1), the relay is open, at 0V (log 0), and the solenoid lock is open. In the case of an unpredictable number, an error is indicated on the display / additional LED for the user with an incorrect code number.

The web interface for the administrator includes a login system with the ability to change data and the ability to change the search number for all 3 game modes that are supported. The first mode consists of sending one number with buttons 1-5. By pressing the button, the HTTP POST request is immediately sent to the webserver and the webserver responds with the result of the verification to the payload. There are only 5 possible combinations, the search is fast. This game mode is not equipped with a display.

The second game mode employs four repeatable numbers, i. from 0000-9999. So there are a total of 10,000 combinations, with only one right. The four buttons are used to set the numbers. Each button operates its position by incrementing a number from 0-9. The fifth button serves as Enter and when pressed, the entered four-combination is sent to the web interface.

The third mode is almost identical to the second mode, it works without repeating numbers. In total there are 5040 possible combinations with one right.

All 3 game modes can be operated from one web interface. The administrator can select a search number for each game. The change is applied immediately (even during the game). The web interface can be further supplemented by the use of MySQL database for individual connections from Arduino. Use for statistics, success of competitors competing with the entered numbers, number of attempts, time period. The website is treated for number inputs for each of the game modes (taking into account repetition, non-repetition, number code length).

ESP32, ESP8266 with WiFi connectivity can also be used as microcontroller. They also support HTTPS encrypted connection to the website. For ESP32 it is possible to use own certification authority, HTTPS certificate. The project is actually deployed and it is a paid solution to which I am able to deliver software, wiring diagram. Included in this article is one code for the Arduino and Ethernet W5100, which in a quartered version offers part of the first game mode with a single number search. The number is fixed in the .php file of the website to which the Arduino with Ethernet shield connects, does not include a database connection, admin interface. The paid version also includes an integrated watchdog that Arduino restarts in the event of a hang.
More projects can be found on my site: https://arduino.php5.sk/?lang=en
Wiring diagram for all 3 game modes:

Program pre Arduino with Ethernet W5100:

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xAA, 0xBB, 0xCC, 0xAA, 0xBB, 0xCC };
IPAddress ip(192, 168, 1, 101);
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
char serverName[] = "192.168.1.254"; //or hostname
int serverPort = 80;

const int buttonPin1 = 9;
const int buttonPin2 = 8;
const int buttonPin3 = 7;
const int buttonPin4 = 6;
const int buttonPin5 = 5;
const int relay = 3;

int buttonState1 = HIGH;
int buttonState2 = HIGH;
int buttonState3 = HIGH;
int buttonState4 = HIGH;
int buttonState5 = HIGH;

int lastButtonState1 = HIGH;
int lastButtonState2 = HIGH;
int lastButtonState3 = HIGH;
int lastButtonState4 = HIGH;
int lastButtonState5 = HIGH;

unsigned long lastDebounceTime1 = 0;
unsigned long lastDebounceTime2 = 0;
unsigned long lastDebounceTime3 = 0;
unsigned long lastDebounceTime4 = 0;
unsigned long lastDebounceTime5 = 0;
unsigned long debounceInterval = 50;



EthernetClient client;
int number = 0;
String url = "/sendnumber.php";
void setup() {
  Serial.begin(115200);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, HIGH); //lock door
  pinMode(buttonPin1, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
  pinMode(buttonPin4, INPUT_PULLUP);
  pinMode(buttonPin5, INPUT_PULLUP);
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  Serial.println("IP address set to Ethernet shield:");
  Serial.println(Ethernet.localIP());
  delay(2000);
  Serial.println("Ready");
}

void send_datas() {
  String my_datas = String(number);
  String data = "number=" + my_datas;
  if (client.connect(serverName, serverPort)) {
    client.println("POST " + url + " HTTP/1.0");
    client.println("Host: " + (String)serverName);
    client.println("User-Agent: ArduinoEthernetWiznet");
    client.println("Connection: close");
    client.println("Content-Type: application/x-www-form-urlencoded;");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
    while (client.connected()) {
      //HTTP HEADER
      String line = client.readStringUntil('\n'); //HTTP header
      if (line == "\r") {
        break; //blank line between HTTP header and payload
      }
    }
    String line = client.readStringUntil('\n'); //Payload first line
    if (line == "Access") {
      Serial.println("Access gained!");
      digitalWrite(relay, LOW); //unlock door to next level
    } else {
      Serial.println("Access denied!");
      digitalWrite(relay, HIGH); //lock door
    }
  } else {
    Serial.println("Error connecting to webserver!");
  }
  client.stop();
}

void loop() {
  int reading1 = digitalRead(buttonPin1);
  int reading2 = digitalRead(buttonPin2);
  int reading3 = digitalRead(buttonPin3);
  int reading4 = digitalRead(buttonPin4);
  int reading5 = digitalRead(buttonPin5);

  if (reading1 != lastButtonState1) {
    lastDebounceTime1 = millis();
  }

  if (reading2 != lastButtonState2) {
    lastDebounceTime2 = millis();
  }

  if (reading3 != lastButtonState3) {
    lastDebounceTime3 = millis();
  }

  if (reading4 != lastButtonState4) {
    lastDebounceTime4 = millis();
  }

  if (reading5 != lastButtonState5) {
    lastDebounceTime5 = millis();
  }
  if ((millis() - lastDebounceTime1) > debounceInterval) {
    if (reading1 != buttonState1) {
      buttonState1 = reading1;
      if (buttonState1 == HIGH) {
        number = 1;
        send_datas();
      }
    }
  }

  if ((millis() - lastDebounceTime2) > debounceInterval) {
    if (reading2 != buttonState2) {
      buttonState2 = reading2;
      if (buttonState2 == HIGH) {
        number = 2;
        send_datas();
      }
    }
  }

  if ((millis() - lastDebounceTime3) > debounceInterval) {
    if (reading3 != buttonState3) {
      buttonState3 = reading3;
      if (buttonState3 == HIGH) {
        number = 3;
        send_datas();
      }
    }
  }

  if ((millis() - lastDebounceTime4) > debounceInterval) {
    if (reading4 != buttonState4) {
      buttonState4 = reading4;
      if (buttonState4 == HIGH) {
        number = 4;
        send_datas();
      }
    }
  }
  if ((millis() - lastDebounceTime5) > debounceInterval) {
    if (reading5 != buttonState5) {
      buttonState5 = reading5;
      if (buttonState5 == HIGH) {
        number = 5;
        send_datas();
      }
    }
  }
  lastButtonState1 = reading1;
  lastButtonState2 = reading2;
  lastButtonState3 = reading3;
  lastButtonState4 = reading4;
  lastButtonState5 = reading5;

}

-----------------------------------------------------------------------------------------------------------------
Program forwebserver (PHP) sendnumber.php:

<?php
$secret_number = 3;
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $number = $_POST['number'];
  $number = trim( $number );
  if (is_numeric($number)){
    if($number==$secret_number){
      echo "Access";
    }else{
      echo "Problem";
    }   
  }
}else{
  echo "Unsupported METHOD! Use POST instead of GET/PUT/PATCH!";
}   
?>