Secret knock lock on an Arduino Uno
An SW-420 vibration sensor on the door listens for a secret rhythm, three quick knocks and one after a pause: the right one opens the servo bolt, anything else flashes red. The whole build, an Arduino Uno and 6 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
IntermediateRuns in your browser. Free, and no account needed.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Secret knock lock: an SW-420 vibration sensor taped to the door, a servo
// that slides the bolt, and two lamps.
//
// pin 2 the SW-420's DO (low when still, pulses high on a knock)
// pin 9 the servo's signal wire (its red wire on 5 V, brown on GND)
// pin 7 through 220 ohm to the green LED
// pin 6 through 220 ohm to the red LED
//
// The secret is a rhythm, not a count: knock, knock, knock, pause, knock. The
// gaps are short, short, long, the long one twice the others. Knocking faster
// or slower is fine, because the sketch compares the gaps with the longest
// one, not with a clock.
//
// # Hearing one knock
//
// A knock is not one clean pulse on DO. The switch inside the can bounces for
// a few tens of milliseconds, so DO pulses high several times. The sketch
// takes the first edge as the knock and ignores DO for 100 ms after it.
//
// # The rhythm
//
// After 1.5 s with no knock the sequence is over. Each gap is scaled so the
// longest is 100, and each has to be within 25 of the secret's.
#include <Servo.h>
const int SENSOR = 2;
const int BOLT = 9;
const int GREEN_LED = 7;
const int RED_LED = 6;
const int LOCKED = 0;
const int OPEN = 90;
const int MAX_KNOCKS = 10;
const unsigned long DEBOUNCE_MS = 100;
const unsigned long DONE_MS = 1500;
const int TOLERANCE = 25;
// The secret, as gaps scaled to the longest: short, short, long.
const int SECRET[] = {50, 50, 100};
const int SECRET_GAPS = sizeof(SECRET) / sizeof(SECRET[0]);
Servo bolt;
unsigned long knockAt[MAX_KNOCKS];
int knocks = 0;
void setup() {
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: secret knock lock");
pinMode(SENSOR, INPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
bolt.attach(BOLT);
bolt.write(LOCKED);
}
bool rhythmMatches() {
if (knocks - 1 != SECRET_GAPS) return false;
unsigned long longest = 1;
for (int i = 1; i < knocks; i++) {
unsigned long gap = knockAt[i] - knockAt[i - 1];
if (gap > longest) longest = gap;
}
for (int i = 1; i < knocks; i++) {
int scaled = (int)((knockAt[i] - knockAt[i - 1]) * 100 / longest);
Serial.print(" gap ");
Serial.print(scaled);
Serial.print(" (want ");
Serial.print(SECRET[i - 1]);
Serial.println(")");
int off = scaled - SECRET[i - 1];
if (off < -TOLERANCE || off > TOLERANCE) return false;
}
return true;
}
void unlock() {
Serial.println("unlocked");
digitalWrite(GREEN_LED, HIGH);
bolt.write(OPEN);
delay(4000);
bolt.write(LOCKED);
digitalWrite(GREEN_LED, LOW);
Serial.println("locked");
}
void refuse() {
Serial.println("wrong knock");
for (int i = 0; i < 3; i++) {
digitalWrite(RED_LED, HIGH);
delay(150);
digitalWrite(RED_LED, LOW);
delay(150);
}
}
void loop() {
unsigned long now = millis();
if (digitalRead(SENSOR) == HIGH) {
if (knocks == 0 || now - knockAt[knocks - 1] > DEBOUNCE_MS) {
if (knocks < MAX_KNOCKS) {
knockAt[knocks] = now;
knocks++;
Serial.print("knock ");
Serial.println(knocks);
}
}
}
if (knocks > 0 && now - knockAt[knocks - 1] > DONE_MS) {
if (rhythmMatches()) {
unlock();
} else {
refuse();
}
knocks = 0;
}
}
Parts list
8 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R3
- 1 × Half breadboard
- 1 × Vibration sensor, SW-420
- 1 × Hobby servo
- 2 × Resistor, 220 Ω
- 1 × LED, green
- 1 × LED, red
How it is wired
8 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 9; Hobby servo pin PWM
- Arduino Uno R3 pin 7; Resistor, 220 Ω (1) pin 1
- Arduino Uno R3 pin 6; Resistor, 220 Ω (2) pin 1
- Arduino Uno R3 pin 2; Vibration sensor, SW-420 pin DO
- Arduino Uno R3 pin 5V; Vibration sensor, SW-420 pin VCC; Hobby servo pin VCC
- Ground: Arduino Uno R3 pin GND; Vibration sensor, SW-420 pin GND; Hobby servo pin GND; LED, green pin C; LED, red pin C
- Resistor, 220 Ω (1) pin 2; LED, green pin A
- Resistor, 220 Ω (2) pin 2; LED, red pin A
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.