Real practical uses for magnetic reed switch

I picked up a couple of cheap reed switches with the intention of integrating them into my setup.
But.
Im not actually sure how.
I mean, I have tested the function and have a working script and can get the necessary data into HAS via mqtt, but is the actual physical wiring that’s the issue.
My original plan was to put one on the front door, so I could monitor whenever the door is opened (I have a bad habit of not shutting it fully)…but the Pi to which the switches would be connected is no where near the door, so would mean running wiring the full length of the house…not practical.

Has anyone got any real life, practical implementatins they could share?
Im thinking along the lines of a nodemcu or something similar…but again, id need lengthy wiring to power it? :thinking:

Check this out

I usually run tiny sensors like that off 433MHz, since I have an RFXtrx hanging on my HASS-box.

433 is good for this sort of thing, because a NodeMCU will be hard to keep in batteries for very long since it has to wake up every so often to keep alive on the wifi etc.

I pasted in an old post I made on the forum of my previous home automation software for a homemade ATTiny85-based sensor, the code itself and the post in general details a blink counter I made for my power meter, but it shouldn’t be hard to adapt to a simple binary sensor, or even switch out the x10 for a library that does HomeEasy or some other protocol.

The interesting bits are the watchdog timers for sleep and the interrupts for waking, even doing a couple hundred blinks a minute my sensor lasted about 5 years before it had drained 4 AAA-batteries. I’m sure a button cell would easily last several months or more. A capacitor inline with the batteries might eke out some more power as well.

The total counter of the meter will reset when power is lost, I correct for this in software - currently my value for the powermeter is “(Value1 / 10) + 305300”.

As for the code, it is using the watchdog timer in the chip to time the minutes that are used for calculating current consumption in watts, this is not 100% accurate to a minute, and so the calculation may also be slightly off, in mine it is fairly close though and only drifts about three seconds every hour.

I added a drawing of the circuit. The resistors used are a 10kΩ resistor for the LDR and the ATtiny reset, and a 680Ω one for the LED. Adjust that one as necessary for the light level you want. The LED also is not necessary, but it is nice to have some sign of life from the circuit.

#include <x10rf.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define tx 0           // Pin for 433MHz transmitter
#define reps 1         // Repeats for RF-command
#define ledpin 4       // Pin for transmit led (0 = don't blink)

const int blinks_per_unit = 1000;       // Number of blinks per 1 unit (kW, m3 etc.)
const int transmit_interval = 31;       // Number of watchdog intervals between transmits (each interval is ~2 sec, needs adjustment for each chip)
const int current_multiplier = 6;       // Number to multiply the amount of blinks the last minute to get an hours consumption. (Normally 60, set to 6 here as I am counting 0.1 units).

x10rf x10 = x10rf(tx, ledpin, reps);    // x10 transmit object

unsigned long totalUnits = 0;           // Counter for total number of units used
int counterUnits = 0;                   // Temporary counter for calculation of total consumption

volatile long totalCounter = 0;         // Counter for current consumption
volatile int wdCounter = 0;             // Counter for current consumption
volatile int currentCounter = 0;        // Counter for current consumption

void setup() {
  resetWatchdog ();  // do this first in case WDT fires

  x10.begin();

  pinMode(0, OUTPUT);  // Set pins, all unused pins to input for power savings
  pinMode(1, INPUT);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, OUTPUT);

  GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  PCMSK |= _BV(PCINT2);                   // Use PB3 as interrupt pin
  ADCSRA &= ~_BV(ADEN);                   // ADC off

  if(ledpin > 0) {
    for (int k = 0; k < 8; k = k + 1) {
      digitalWrite(ledpin, !digitalRead(ledpin));   // Run a blink sequence to show the circuit lives on boot
      delay(100);
    }
  }

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}

void transmit() {
  x10.RFXmeter(11, 0, totalUnits);                            // Transmit total units consumed
  x10.RFXmeter(12, 0, currentCounter * current_multiplier);   // Transmits current unit consumption
  currentCounter = 0;                                         // Resets counter for last interval
}

void sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  MCUSR = 0;
  sleep_cpu();                            // sleep

  sleep_disable();                        // Clear SE bit
}

void resetWatchdog ()
{
  MCUSR = 0;                                                  // clear various "reset" flags
  WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);                // allow changes, disable reset, clear existing interrupt
                                               // set interrupt mode and an interval (WDE must be changed from 1 to 0 here)
  WDTCR = bit (WDIE) | bit (WDP2) | bit (WDP1) | bit (WDP0);  // set WDIE, and 2 seconds delay
  wdt_reset();                                                // pat the dog
}  // end of resetWatchdog

void loop() {
  if (wdCounter >= transmit_interval) {  // Check if we have run the required number of wakeups
    wdCounter -= transmit_interval;
    transmit();                          // Run radio transmission
  }

  if (totalCounter >= blinks_per_unit) {
    totalCounter -= blinks_per_unit;
    totalUnits++;                       // Increases total counter unit
  }

  sleep();
}

ISR(PCINT0_vect) {
  if (digitalRead(2) == HIGH) {
    totalCounter++;                        // Increase counter for total current consumption
    currentCounter++;
  }
}

ISR(WDT_vect) {
  resetWatchdog();
  wdCounter++;
}

I have a reed switch in my chicken coop on the door. It is paired with a nodemcu and runs the bruh code mentioned above.

I have a few doors in the house setup the same way. I have outlets somewhat close to the doors and just run low voltage lines tucked under the modeling and a magnet on the back of the door.

Thanks for this, I actually am running 2 ‘Bruh Multisensors’ and they work great, and ill try to get the reed switch into one just as proof of concept.

But (isn’t there always) it still presents the problem of having to hardwire the power to the sensor close to the door.

Unfortunately I do not have any power outlets near enough the door to be useful, nor do I have any modelling to hide the cables.

Thanks for the confirmation on the code above though, made me even more determined to try it!

This is really interesting, and looks like a good compromiser of a solution.
I have some spare RF transmitters knocking about so I may well be spending my days of next week playing with this.

If you simply want to know if a door is open, I suppose you can go the easy way and use a 433Mhz door sensor:

You’ll have to have a small MQTT/433Mhz bridge in your house, there is many example based on esp8266 on this forum.

You can also take a look at MySensors - you basically build the sensors out of an Arduino pro mini and an RF transmitter with battery power and you can add on whatever functions you want (motion sensor, temperature sensor, or in your case reed switch). Then you build a gateway out of another Arduino and RF transmitter and plug that into HA, then use the MySensors component to get the entities into HA. Excellent range and battery life on the sensors and a fairly easy and fun DIY project. Plus the components can be had for cheap!

1 Like