Door alarm on an Arduino Uno
A reed switch and a magnet on pin 2: open the door and a buzzer and a lamp latch on until the arcade button resets them. Half-size board. The whole build, an Arduino Uno and 5 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.
Teaching? Assign it to your class in one click.
Beginner About 20 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $32. On Mokxi they're free.
What you'll learn
- Reed switches and how a magnet closes them
- Debouncing an input by requiring a steady reading
- Latching a state until a reset button clears it
- Blinking with millis instead of delay
- Difficulty: Beginner
- Time: About 20 minutes
- Board: Arduino Uno R3
- Parts: 7
How it works
A reed switch on pin 2 closes when a magnet is near, so a shut door reads LOW. When the door opens the pull-up takes the pin HIGH. The sketch waits for that reading to hold for 20 ms before it believes it, which filters out contact bounce.
An opening sets the alarm, and the alarm latches. Closing the door again does not stop it. While the alarm is on, the buzzer on pin 8 and the lamp on pin 9 blink together every 200 ms. Pressing the button on pin 3 resets it.
Parts list
7 parts, plus the jumper wires. They retail for about $32; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Half breadboard
- 1 × Reed switchIn Escape Box Kit.
- 1 × Arcade buttonIn Claw Machine Kit, Fight Stick Kit, Pinball Table Kit.
- 1 × BuzzerIn Starter Kit, Rocket Flight Computer Kit.
- 1 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 1 × LED, redIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| Resistor, 220 Ω pin 1 | Arduino Uno R3 pin 9 |
| Buzzer pin 1 | Arduino Uno R3 pin 8 |
| Arcade button pin 2 | Arduino Uno R3 pin 3 |
| Reed switch pin 1 | Arduino Uno R3 pin 2 |
| Reed switch pin 2 | Arduino Uno R3 pin GND |
| Arcade button pin 1 | Arduino Uno R3 pin GND |
| Buzzer pin 2 | Arduino Uno R3 pin GND |
| LED, red pin C | Arduino Uno R3 pin GND |
| LED, red pin A | Resistor, 220 Ω pin 2 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Door alarm: a reed switch on the frame, a magnet on the door.
//
// pin 2 the reed switch, other leg to GND, internal pull-up
// pin 3 the reset button, other leg to GND, internal pull-up
// pin 8 the buzzer, other leg to GND
// pin 9 the lamp, through 220 ohm to GND
//
// A reed switch is two steel blades in a glass tube. A magnet near it pulls
// them together and the pin reads LOW; take the magnet away and the blades
// spring apart and the pull-up takes the pin HIGH. So on a door: magnet on the
// door, switch on the frame, closed door is LOW, open door is HIGH. Drag the
// slider on the switch to move the magnet.
//
// # Two things the part will teach you if you let it
//
// The blades bounce. Not for a hundred milliseconds like the ball in a tilt
// switch, but for a fraction of one, and it is still enough to count an
// opening twice if the sketch believes the first edge it sees. So the reading
// has to hold for SETTLE_MS before it counts.
//
// The switch does not let go where it grabbed. It closes when the magnet is
// about 15 mm away and holds on out to nearly 19 mm, because once the blades
// are touching the magnetic circuit through them is better. That gap is
// hysteresis, it is on every reed switch datasheet as an operate and a release
// figure, and it is the reason a door that creaks an inch does not set this
// off.
//
// # Latching
//
// Shutting the door again does not stop the alarm: it has seen the door open,
// and that is the thing worth knowing. Press the button to reset it.
const int REED = 2;
const int BUTTON = 3;
const int BUZZER = 8;
const int LAMP = 9;
const unsigned long SETTLE_MS = 20;
const unsigned long BEEP_MS = 200;
bool alarm = false;
bool openNow = false;
bool lastRead = false;
unsigned long changedAt = 0;
unsigned long beepAt = 0;
bool beepOn = false;
int opened = 0;
void setup() {
pinMode(REED, INPUT_PULLUP);
pinMode(BUTTON, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
pinMode(LAMP, OUTPUT);
digitalWrite(BUZZER, LOW);
digitalWrite(LAMP, LOW);
Serial.begin(115200);
Serial.println("Mokxi Uno: door alarm, reed switch on pin 2");
// Start from where the door is now, so only a change after Run counts. A
// door that is already open at power-up is not a break-in.
lastRead = openNow = digitalRead(REED) == HIGH;
}
void loop() {
// HIGH is the pull-up with the blades apart, which is the door open.
bool raw = digitalRead(REED) == HIGH;
if (raw != lastRead) {
lastRead = raw;
changedAt = millis();
} else if (raw != openNow && millis() - changedAt >= SETTLE_MS) {
openNow = raw;
if (openNow) {
opened++;
alarm = true;
Serial.print("door opened, count ");
Serial.println(opened);
} else {
Serial.println("door closed");
}
}
if (digitalRead(BUTTON) == LOW && alarm) {
alarm = false;
Serial.println("alarm reset");
}
if (alarm) {
if (millis() - beepAt >= BEEP_MS) {
beepAt = millis();
beepOn = !beepOn;
digitalWrite(BUZZER, beepOn ? HIGH : LOW);
digitalWrite(LAMP, beepOn ? HIGH : LOW);
}
} else if (beepOn) {
beepOn = false;
digitalWrite(BUZZER, LOW);
digitalWrite(LAMP, LOW);
}
}
Code walkthrough
The key functions of the sketch, and what each one does.
setup sketch.ino
Sets the reed switch and button as INPUT_PULLUP and the buzzer and lamp as outputs, both off. It also reads the door once and stores it, so a door that is already open at power-up does not count as a break-in.
void setup() {
pinMode(REED, INPUT_PULLUP);
pinMode(BUTTON, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
pinMode(LAMP, OUTPUT);
digitalWrite(BUZZER, LOW);
digitalWrite(LAMP, LOW);
Serial.begin(115200);
Serial.println("Mokxi Uno: door alarm, reed switch on pin 2");
// Start from where the door is now, so only a change after Run counts. A
// door that is already open at power-up is not a break-in.
lastRead = openNow = digitalRead(REED) == HIGH;
}loop sketch.ino
It reads the reed switch and restarts a timer whenever the reading changes. Only after SETTLE_MS of steady reading does it accept the new state. An accepted opening bumps the count and sets alarm. The button clears alarm. While it is set, the buzzer and lamp toggle every BEEP_MS.
void loop() {
// HIGH is the pull-up with the blades apart, which is the door open.
bool raw = digitalRead(REED) == HIGH;
if (raw != lastRead) {
lastRead = raw;
changedAt = millis();
} else if (raw != openNow && millis() - changedAt >= SETTLE_MS) {
openNow = raw;
if (openNow) {
opened++;
alarm = true;
Serial.print("door opened, count ");
Serial.println(opened);
} else {
Serial.println("door closed");
}
}
if (digitalRead(BUTTON) == LOW && alarm) {
alarm = false;
Serial.println("alarm reset");
}
if (alarm) {
if (millis() - beepAt >= BEEP_MS) {
beepAt = millis();
beepOn = !beepOn;
digitalWrite(BUZZER, beepOn ? HIGH : LOW);
// ... 8 more lines in the editorTroubleshooting
The usual mistakes with this circuit, and the fix for each.
- The alarm goes off when the sketch starts This project
The sketch only counts changes after startup. Check the reed switch is wired between pin 2 and ground, not to 5 V. - Closing the door does not silence it This project
That is by design. Press the button on pin 3 to reset the latched alarm. - The input reads random values. Reed switch
A reed switch is just two contacts. Use INPUT_PULLUP and wire one side to the pin and the other to GND, so closed reads LOW. - It triggers several times or never closes. Reed switch
Contacts bounce, so debounce in code. The switch is most sensitive along its length, so move the magnet along the blades, not straight at the end. - The button reads pressed all the time, or never changes, when wired to a pin. Arcade button
Use the COM and NO terminals of the microswitch. Wire COM to ground, NO to the pin, and use INPUT_PULLUP. NC is the opposite and reads pressed when released. - One press counts as several presses in your code. Arcade button
Microswitch contacts bounce for a few milliseconds. Ignore changes for 10 to 20 ms after the first one, or react only to the edge and wait before checking again. - The buzzer makes a constant tone, or you cannot change its pitch. Buzzer
An active buzzer has its own oscillator, so it only beeps on and off. A passive buzzer needs tone() to set pitch. Check which type you have. - The buzzer is silent or very quiet. Buzzer
Check polarity: the plus mark goes to the pin or supply. For loud buzzers, drive them through a transistor instead of straight from a pin.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.