Reed Sensor Module (MagSwitch) Tutorial: How Reed Switches Work, NO/NC Behavior, Arduino/ESP32 Wiring, Debounce, Door/Window Alarms, RPM Sensing, and Reliable Magnet Placement
This tutorial is a detailed, practical guide to using the Reed Sensor Module (MagSwitch) (Leobot Product #202) for magnetic detection: door/window state sensing, limit switches, proximity triggers, and simple RPM/tachometer inputs. You’ll learn what a reed switch actually is (a tiny sealed glass switch), how the module is typically wired (digital output + indicator LED), how to read it reliably on Arduino/ESP32 (including debounce and noise filtering), and how to mount magnets correctly so you get a stable, repeatable trigger every time.
1) What a reed switch is (and why it’s still useful)
A reed switch is a tiny mechanical switch sealed inside a glass tube. Inside are two thin ferromagnetic blades (“reeds”). When a magnet comes close, the reeds become magnetized and move together (or apart) to change the circuit state.
Reed switches are popular because they are:
- Simple (no complex electronics required)
- Low power (almost zero standby current if used as a plain switch)
- Reliable for door/window sensing and position detection
- Galvanically isolated from the magnet (no physical contact needed)
2) What’s on the Reed Sensor Module (VCC/GND/DO, LED, comparator)
Reed “modules” often contain:
- The reed switch itself
- A pull-up/down resistor network
- An indicator LED (shows trigger state)
- Sometimes a comparator or buffer stage (depends on exact module)
Most modules expose:
- VCC (typically 3.3V–5V)
- GND
- DO (digital output)
3) Normally Open vs Normally Closed behavior (and how to test yours)
Reed switches come in two common behaviors:
- Normally Open (NO): open with no magnet; closes when magnet is near
- Normally Closed (NC): closed with no magnet; opens when magnet is near
Some “MagSwitch” modules are essentially NO reeds (most common), but you should confirm:
- Power the module
- Read DO (or watch the LED)
- Bring the magnet close and observe whether the output goes HIGH?LOW or LOW?HIGH
4) Wiring to Arduino/ESP32 (pull-ups, logic levels, and safe wiring)
4.1 Basic wiring
- Module VCC ? Arduino 5V (or ESP32 3.3V if supported)
- Module GND ? MCU GND
- Module DO ? MCU digital input pin
4.2 Logic level considerations
- Arduino UNO/Nano: 5V logic inputs
- ESP32: 3.3V logic inputs (do not feed 5V into GPIO)
4.3 Internal pull-ups
Many modules already have pull-ups/pull-downs. If you’re using a bare reed switch, you would normally use:
pinMode(PIN, INPUT_PULLUP)and connect the switch to GND for an active-low input
5) Magnet placement: distance, polarity, alignment, and repeatability
Reed switches are very sensitive to how you place the magnet. For reliable triggers:
- Distance: closer = stronger field = more reliable switching. Start very close and move away until it becomes unreliable.
- Alignment: reed switches respond best when the magnet field lines run along the length of the reed.
- Movement direction: design your mechanical motion so the magnet approaches and leaves the reed consistently.
- Vibration: avoid situations where the magnet “hovers” on the edge of the trigger point (causes chatter).
6) Debounce and filtering (stop false triggers)
A reed switch is mechanical. When it closes/opens, it can bounce (rapidly flicker) for a few milliseconds. Also, magnets near the threshold can cause repeated switching.
Debounce strategies
- Software debounce: ignore changes for 10–50ms after a state change
- State confirmation: require the new state to remain stable for N ms before accepting it
- Hardware filter: RC low-pass + Schmitt input (advanced, usually not required)
7) Arduino Example 1: Basic door/window sensor
This reads the DO pin and prints whether the door is open/closed.
Adjust ACTIVE_LOW after testing your module with a magnet.
/*
Reed Sensor Module (MagSwitch) (#202) - Basic Door Sensor
Wiring:
VCC -> 5V (Arduino) / 3.3V (ESP32 if supported)
GND -> GND
DO -> D2
Note:
Some modules output LOW when magnet is present (active-low).
Test yours and set ACTIVE_LOW accordingly.
*/
const int PIN_REED = 2;
const bool ACTIVE_LOW = true; // set after testing
void setup() {
pinMode(PIN_REED, INPUT);
Serial.begin(115200);
delay(200);
}
void loop() {
int raw = digitalRead(PIN_REED);
bool triggered = ACTIVE_LOW ? (raw == LOW) : (raw == HIGH);
Serial.println(triggered ? "MAGNET PRESENT (door closed)" : "NO MAGNET (door open)");
delay(200);
}
8) Arduino Example 2: Debounced state + event logging
This version reports only stable state changes (no spam from bounce).
/*
Reed Sensor Module (MagSwitch) (#202) - Debounced State Change
- Reports "OPEN/CLOSED" only when stable for DEBOUNCE_MS.
*/
const int PIN_REED = 2;
const bool ACTIVE_LOW = true;
const unsigned long DEBOUNCE_MS = 30;
bool stableState = false; // debounced state (triggered or not)
bool lastReadState = false; // last instantaneous reading
unsigned long lastChangeMs = 0;
bool readTriggered() {
int raw = digitalRead(PIN_REED);
return ACTIVE_LOW ? (raw == LOW) : (raw == HIGH);
}
void setup() {
pinMode(PIN_REED, INPUT);
Serial.begin(115200);
delay(200);
stableState = readTriggered();
lastReadState = stableState;
Serial.println(stableState ? "CLOSED (magnet present)" : "OPEN (no magnet)");
}
void loop() {
bool nowRead = readTriggered();
unsigned long now = millis();
if (nowRead != lastReadState) {
lastReadState = nowRead;
lastChangeMs = now;
}
// Accept change only if stable for DEBOUNCE_MS
if (nowRead != stableState && (now - lastChangeMs) >= DEBOUNCE_MS) {
stableState = nowRead;
Serial.println(stableState ? "CLOSED (magnet present)" : "OPEN (no magnet)");
}
delay(5);
}
9) Arduino Example 3: RPM / rotation sensing with a magnet
Put a magnet on a rotating shaft and mount the reed module nearby. Each pass produces a pulse. Then RPM:
- RPM = (pulses per minute) / (magnets per revolution)
/*
Reed Sensor Module (MagSwitch) (#202) - Simple RPM Counter
- Counts pulses in a time window and estimates RPM.
- Use minimal debounce (or none) depending on speed.
*/
const int PIN_REED = 2;
const bool ACTIVE_LOW = true;
volatile unsigned long pulseCount = 0;
void isrPulse() {
pulseCount++;
}
void setup() {
Serial.begin(115200);
delay(200);
pinMode(PIN_REED, INPUT);
// Interrupt on CHANGE catches both edges; you can also use FALLING/RISING.
attachInterrupt(digitalPinToInterrupt(PIN_REED), isrPulse, CHANGE);
}
void loop() {
pulseCount = 0;
unsigned long start = millis();
const unsigned long windowMs = 1000;
while (millis() - start < windowMs) {
// just counting
}
unsigned long pulses = pulseCount;
// If using CHANGE, you may get 2 edges per pass. Use FALLING for 1 pulse per pass.
// Here we assume 1 pulse per pass. Adjust if needed.
float rpm = (pulses * 60.0f) / (windowMs / 1000.0f);
Serial.print("Pulses=");
Serial.print(pulses);
Serial.print(" RPM~");
Serial.println(rpm, 1);
delay(200);
}
10) Practical projects
Project A: Door/window alarm
- Reed module on frame, magnet on door
- MCU triggers buzzer/notification when door opens
- Add debounce and “alarm delay” logic
Project B: Limit switch for linear motion
- Use magnet as “end-stop” indicator
- Great where mechanical switches would get dirty or wear out
Project C: Low-cost rotation counter
- Magnet on wheel/shaft
- Count rotations and compute distance/speed
- Use for DIY odometer, small conveyor counters, etc.
11) Troubleshooting
Always triggered / never triggered
- Cause: logic inverted. Fix: flip ACTIVE_LOW in code or interpret output differently.
- Cause: magnet too far or wrong alignment. Fix: move magnet closer and align along reed axis.
- Cause: wrong supply voltage or wiring. Fix: verify VCC/GND/DO and measure DO with a multimeter.
Triggers randomly without magnet
- Cause: floating input / weak pull-up. Fix: use INPUT_PULLUP if using bare switch, or confirm module has stable pull resistors.
- Cause: strong nearby magnets/steel. Fix: relocate sensor; add shielding; increase distance from magnetic sources.
- Cause: vibration near threshold. Fix: mount magnet so it clearly moves in/out of range.
Works on Arduino but not ESP32
- Cause: 5V output into 3.3V GPIO. Fix: power module from 3.3V or level shift DO.
12) Quick checklist
Reed Sensor Module (MagSwitch) (#202) Checklist
-----------------------------------------------
VCC/GND/DO wired correctly; common ground is required
Confirm NO/NC behavior by testing with a magnet (set ACTIVE_LOW accordingly)
Mount magnet with a clear ON zone and OFF zone (avoid threshold hovering)
Add debounce for door/window sensing (20–50ms typical)
For RPM: use interrupts and beware mechanical speed limits (Hall sensors for high RPM)
If using ESP32: ensure DO is 3.3V-safe (power module from 3.3V or level shift)