reed switch/Using it/08. A door that counts
Using it · 08 of 9

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.

One closing, three edges
The sketch
Magnets
0
Counted
0
Settled after
...
The magnet arrives and the blades meet. Press Play to watch the first millisecond of SIGNAL.

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

reed_door_counter.ino

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.0

When it does not work

It counts two or three openings for one.

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.

Opening the door a little does not count.

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 count goes up with the door shut.

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.

Can I count a turning wheel with the same sketch?

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.

Where this goes next

The LED, then the wires: what to check, in order.

When it does not switch →

Edit this page — content/books/reed-switch/a-door-that-counts.mdx

Community

Questions about this product

See what other owners have asked, and read their solutions.

Ask a question ↗

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.

Browse Modules and blocks on the forum →