A door that counts
A door sensor that counts openings and times each one. The block goes on the frame and the magnet on the door, so the switch is closed while the door is shut. The one thing counting adds to the first read is debouncing: a change counts only once SIGNAL has held it for 20 ms, because one closing can bounce into several edges.
One closing, several edges
The blades are springs. When they meet they can bounce apart and meet again, more than once, before they settle. RMCIP's sheet gives no bounce time of its own; it gives an operating time of 1 ms "including bounce", so all of it is over within a millisecond.
Press Play with each sketch. A loop that counts every change from LOW to HIGH sees each bounce as a closing and counts three for one magnet. A loop that waits for 20 ms of steady level counts one. The trace is drawn to show the shape, not measured: nobody has put this switch on a scope.
The first read did not need any of this. It printed every change, so a bounce only meant a repeated line. A counter keeps its mistakes.
How the sketch debounces
raw is the last thing read, and rawSince is when it last changed. Every
bounce resets rawSince. steady changes only when raw has been
different from it for DEBOUNCE_MS, which a bounce never is. So one real
change is one change of steady, and the count and the timing hang off
that.
There is no delay() in loop(). The debounce is a comparison with
millis(), so the loop keeps reading thousands of times a second and
nothing is missed while it waits.
What you should see
At 115200 the serial monitor prints door shut with the magnet on the
glass. Take the magnet away: door opened, time 1. Bring it back after a
few seconds: door shut after 3.2 s, or however long it was. Each opening
counts once, however fast you move the magnet.
Faster things
The switch is rated to 100 closings a second, and the maker's figure for its life is up to 100 million closings at a light load. That is plenty for a door, a lid, a rain gauge's tipping bucket or a bicycle wheel. For a motor shaft, the 20 ms debounce is the limit first, then the switch; that is the job for a Hall sensor.
The code
Reads SIGNAL on every pass of loop(), believes a change only once it has held for 20 ms, and then counts and times the openings. No delay() anywhere, so nothing is missed while it waits.
/*
Reed Switch - a door that counts TK41 / /p/tk41
Wiring, the same as the first read. Count from the square pad on
the TinkerBlock board, parts up, header at the bottom:
GND -> GND
VCC -> 3V3 on an ESP32, ESP32-S3 or Pico; 5V on an Uno
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 4 on an ESP32-S3, GPIO 25 on an ESP32,
D2 on an Uno, GP15 on a Raspberry Pi Pico
Mounting: the block on the frame, the magnet on the door, so
the switch is closed (HIGH) while the door is shut.
Arduino IDE
Tools > Board your board, e.g. ESP32S3 Dev Module
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
No library needed.
*/
// The pin SIGNAL is wired to.
// Uno: 2. ESP32: 25. ESP32-S3: 4. Pico: 15.
const int REED_PIN = 4;
// A change counts once it has held this long.
const unsigned long DEBOUNCE_MS = 20;
int raw; // the last reading
int steady; // the last reading that held
unsigned long rawSince; // when raw last changed
unsigned long openedAt; // when the door last opened
unsigned long openings = 0;
void setup() {
Serial.begin(115200);
pinMode(REED_PIN, INPUT); // the board has its own pull-down
raw = digitalRead(REED_PIN);
steady = raw;
rawSince = millis();
openedAt = millis();
Serial.println(steady == HIGH ? "door shut" : "door open");
}
void loop() {
int level = digitalRead(REED_PIN);
if (level != raw) { // a bounce, or a real change starting
raw = level;
rawSince = millis();
}
// Believe a change only once it has held for DEBOUNCE_MS.
if (raw != steady && millis() - rawSince >= DEBOUNCE_MS) {
steady = raw;
if (steady == LOW) { // magnet gone: the door opened
openings++;
openedAt = millis();
Serial.print("door opened, time ");
Serial.println(openings);
} else { // magnet back: the door shut
Serial.print("door shut after ");
Serial.print((millis() - openedAt) / 1000.0, 1);
Serial.println(" s");
}
}
}With the magnet on the door the switch is closed, HIGH, while the door is shut, so an opening is a change to LOW. Mounted the other way round, swap the two branches. The sketch compiles for an ESP32-S3 and an Uno.
View on GitHub · blocks/tk41-reed-switch/arduino/reed_door_counter/reed_door_counter.ino @ v1.0When it does not work
The sketch is counting bounces. Each closing and opening of the contacts can flicker for a fraction of a millisecond, and a loop that counts every change sees each flicker. Keep the 20 ms debounce, and do not add a delay() that makes the loop miss the settled level.
The magnet has not moved far enough to let the switch go: it releases farther out than it closes. Mount the magnet closer to the glass so the shut door is well inside the closing distance.
The magnet sits near the edge of its range and the door moves a little in its frame. Bring the magnet closer, lay it along the glass, and check SIGNAL and GND are firm.
Slowly, yes: a bicycle wheel turns a few times a second. The switch is rated to 100 closings a second, and a debounce of 20 ms limits the count to about 25 a second, so shorten DEBOUNCE_MS for faster wheels, or use a Hall sensor.
Edit this page — content/books/reed-switch/a-door-that-counts.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Reed Switch
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.