DIY low powered esp8266 door/window/mailbox sensor

I wanted to share my open source, DIY, very low powered windows/door/mailbox/“whatever open and close” sensor (can also be used for other things).

Note1:
I have a active question on electronics.stackexchange were I try to get some help improving this circuit, but I’m not sure there is much to improve, but if you see something please give a comment here or there. You can also check that post for more in depth understanding of the circuit.
Link: https://electronics.stackexchange.com/questions/519758/improving-edge-detector-with-latching-circuit-for-esp8266/519912#519912
Note2:
Currently I’m using a Lipo battery directly connected to the esp8266-12e. By testing I see everything is ok, but at a full charge (4.2Vdc) it is more than recommended for the esp8266 (3.6Vdc). This might work for a long time, or it can break down. I have seen many discussion about this but none that have had problems when only going to 4.2Vdc (5Vdc yes, that is a problem).

You can buy your own circuit, almost 100% soldered, only missing the esp8266-12e and connectors, from jlcpcb. Link: https://easyeda.com/jakibsgaard/low-powered-rising-and-falling-power-on-circuit
I bought 30pcs for 18$ with parts and assembly (again not with the esp8266-12e, connectors and reed switch).

The device is quite small, 20mm wide, 31mm long and about 10mm thick. This is without the enclosure and reed switch.
The power consumption is quite good, since I’m not using the esp8266 deep sleep (~20uA), but with a latching circuit I get ~3uA in closed switch state and ~0.4uA in open switch state. On a 200mAh battery I get over 2 years calculated operating time, this includes 15% overhead in capacity.

You can use a reed switch or some other type of switch. But my circuit is not meant for a momentary switch, like a vibration sensor.

Picture of one side of the circuit:


Picture of the side where the esp8266-12f would be soldered:

Picture of my crudely put together for testing and power measurement:

PS.I have updated my schematics on easyeda so the resistor I have connected is not necessary.

This is the code I have flash on my esp8266-12e. In home assistant I have added a long lived token and a input_boolean.

code

// last tested on Arduino IDE 2.2.1 with esp8266 v3.1.2 (http://arduino.esp8266.com/stable/package_esp8266com_index.json)
// all libraries are included when you install the esp8266 board
// check this link to add unique id to your entity: https://community.home-assistant.io/t/ha-core-rest-api-post-unique-id-for-entities/216122/4
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
#include <algorithm>
#include <string>
#include "secrets.h" // add this file in the same location as this ino sketch, in the file you write #define SECRET_SSID "yourSSID" etc

String ssid = SECRET_SSID;
String password = SECRET_PASS;
String haIP = SECRET_HAIP;
String apiKey = SECRET_HAKey;

// variables needed later in the code
String payload;
String macAddress;

// the name of the device on the network and in home assistant
String hostName = "esp12_reedsw"; // change this to your liking (uniqueness is added later in the code)
// PS!! A very long name could cause issues, I haven't found any good source that describes this, just be aware if you get a compile error or missing some characters in HA or on your network controller.

// IPaddress if static is needed/wanted, will speed things up with wifi connection
IPAddress ip(192,168,1,154); // change these, remember commas, not period between numbers
IPAddress gw(192,168,1,1);
IPAddress dns(192,168,1,2);
IPAddress subnet(255,255,255,0);

int sensorPin = 12; // ping to check if open or closed
int enablePin = 5; // pin to keep the power on until finnished
int sensor; // used to check if the switch is open or closed
int code; // used to check the http return code

//Enable getvcc
ADC_MODE(ADC_VCC);

void setup() {

  //Enable power signal as soon as possible
  pinMode(enablePin, OUTPUT);
  digitalWrite(enablePin, HIGH);

  pinMode(sensorPin,INPUT);

//  Serial.begin(115200);
//  Serial.println();

  //Connect to WIFI
  WiFi.mode(WIFI_STA);
  
  // create a unique hostName from the last 3 octets of the mac address
  macAddress = WiFi.macAddress();
  macAddress = macAddress.substring(8);
  std::replace( macAddress.begin(), macAddress.end(), ':', '_');
  hostName = hostName + macAddress;

  WiFi.hostname(hostName);
  // uncomment to set static ip
  //WiFi.config(ip, subnet, gw, dns);
  WiFi.begin(ssid, password);

  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    // Serial.println("WiFi failed, retrying.");
  }
  
  HTTPClient http;
  WiFiClient client;

  //Check if update is needed
  http.begin(client, "http://" + haIP + ":8123/api/states/input_boolean.ota_update");
  http.addHeader("Authorization", "Bearer "+apiKey);
  http.addHeader("Content-Type", "application/json");
  int httpCode = http.GET();

//  Serial.println(httpCode);

  if (httpCode > 0){
    payload = http.getString();
    // Serial.println(payload);
  }
  http.end();

  if (payload.indexOf("\"state\":\"on\"") >= 0){
    
    // go to http://deviceIP/update and update the firmware
    ESP8266WebServer httpServer(80);
    ESP8266HTTPUpdateServer httpUpdater;

    MDNS.begin(hostName);

    httpUpdater.setup(&httpServer);
    httpServer.begin();
  
    MDNS.addService("http", "tcp", 80);
    
    //Turn off the update toggle
    http.begin(client, "http://" + haIP + ":8123/api/services/input_boolean/turn_off");
    http.addHeader("Authorization", "Bearer "+apiKey);
    http.addHeader("Content-Type", "application/json");
    http.POST("{\"entity_id\": \"input_boolean.ota_update\"}");
    http.writeToStream(&Serial);
    http.end();

   //Handle the update, continue forever, after the update it will reboot, first time you will ever see me use while(true) and only since there is no state to actually check ;)
    while (true){
      httpServer.handleClient();
      MDNS.update();
      delay(10000);
    }
  }

  //Get the battery voltage and send to HA
  float vcc = ESP.getVcc();
  vcc = vcc / 1000;
  String svcc = String(vcc,3);
//  Serial.println(svcc);
  http.begin(client, "http://" + haIP + ":8123/api/states/sensor."+hostName+"_vcc_voltage");
  http.addHeader("Authorization", "Bearer "+apiKey);
  http.addHeader("Content-Type", "application/json");
  code = http.POST("{\"state\": \""+svcc+"\", \"attributes\": {\"unit_of_measurement\": \"V\", \"icon\": \"mdi:flash\"}}");
//  Serial.println(code);
  http.writeToStream(&Serial);
//  Serial.println();
  http.end();
  sensor = digitalRead(sensorPin);
  
  //Send new data to HA
  http.begin(client, "http://" + haIP + ":8123/api/states/sensor."+hostName+"_switch");
  http.addHeader("Authorization", "Bearer "+apiKey);
  http.addHeader("Content-Type", "application/json");
  if (sensor == 0){
    code = http.POST("{\"state\": \"on\", \"attributes\": {\"device_class\": \"opening\", \"icon\": \"mdi:electric-switch\"}}");
  }
  else if (sensor == 1) {
    code = http.POST("{\"state\": \"off\", \"attributes\": {\"device_class\": \"opening\", \"icon\": \"mdi:electric-switch-closed\"}}");
  }
  
//  Serial.println(sensor);
//  Serial.println(code);
  http.writeToStream(&Serial);
//  Serial.println();
  payload = http.getString();
  http.end();

  //Turn of the latching circuit
  digitalWrite(enablePin, LOW);
  
}

void loop() {
  //Don't want to loop anything
}

Battery
I don’t want to post any links to ebay or aliexpress. But if you search for “200mah lipo” you will find a fitting battery. (They are probably not 200mah, just 140mah but the size is good for the box)
Update 21 June 2021
I have used this outside on my mailbox. Works quite good, the box has been almost 100% waterproof. Battery lasted around 6 months, but my mailbox has very poor wifi reception so the ESP uses sometimes up to a minute before transmitting the message.
Also the batteries I bought were not 200mah, only 140mah.

Box
I have modified the scad file from https://www.thingiverse.com/thing:1680291
From this I made this stl file: Box for esp8266 low powered window/door/mailbox sensor by johnarvid - Thingiverse
Enough room for the ESP and the battery.

Let me know if there are any questions and I will update this post.

Also if anyone want to use this in another low powered sensor and needs help, let me know and I can try to help. I would also like if you shared what you made with the community.

4 Likes

Picture???

Can you link to the question rather than electronics stack exchange?

Adding pictures now.

Sorry, forgot to add that link. Adding it now.

Power consumption:
After testing I found that the sleep current in closed state is ~3uA and in open state ~0.40uA.
So if it wakes up two times a day, uses 3 seconds to boot and do what it should do at ~80mA, it will last over 2 years on a 200mAh battery (15% capacity derated in calculations).

Can you actually connect to wifi and send the sensor state in 3 seconds? I only have experience with waking an ESP from deep sleep and sending an mqtt message but it takes 10 times this long.

Have you measured the current while transmitting wifi? I’ve found it to be considerably higher than 80mA.

Also, neglecting the current drain of your XOR gate, your RC time constant on input B is 1s for charging and 10s for discharging, unless I’ve missed something?

How long does it take to turn off (discharge C1)?

Yes with my testing the time is ~ 3 seconds, and that is with dhcp enabled. I haven’t tested with the static ip enabled as in the current code. And I am having problems measuring any less than 3 seconds with my hands and eyes moving.

I haven’t tried mqtt, but that is something I wanted to try at a later point. It shouldn’t be any slower but maybe the library makes it slower?

The ~80mAh is a average for the time the device is turned on. So at boot it will use less, but when using the highest power consumption on transferring data it will use more, but not the whole time it is awake. It also seems it is using less power when using a “n” wifi than “b” wifi. Ref table 5-3 in :https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
Maybe this also have something to do with the response time?

If i understood you correctly. I have a current drain on both A and B input on the XOR (R2 and R3). The time for discharging is longer than charging, but not that much in practice, I think that has to do with the voltage drop on D1 and the threshold levels on the XOR.

I don’t have the equipment to test that properly, but I don’t have any issues with opening and closing the reed switch quickly. If I do it too quickly the esp8266 is still booting and will give the proper state either way.
But it is to difficult for me to calculate the time C1 discharges, cause the XOR threshold is a bit different on some voltages, and the Diode D1 has a different reverse current leaking on different voltages which then is affected by R4 and R5.
I have tried to calculate this in theory but I found that it worked good from 2.5Vdc to 4.2Vdc with both normal and quick open/close.

Hope this makes some sense, this is my first time creating a circuit.

I mean if you open the reed switch, how long does it take for C1 to discharge and let the latch power turn off?

By my simple calculations (C*R, 10M * 1uF = 10sec). Now it could take up to 5 times that long to discharge completely, but allowing for some minor current drain and a non zero threshold level in the XOR gate that’s still going to be a lot longer than 3 seconds. Perhaps you could use one of the unused gpio to discharge C1 when you are ready to switch off?

Or just use a smaller RC time constant.

Understand.
I tested it and it takes ~3 seconds for it to turn off the latch power. So this should be optimized if the esp8266 awake time is shorter than that.
But I think it should be optimized either way, since I only need 300ms for the esp8266 to wake up and keep the latching circuit turned on.

But, then again, I don’t want to take away those situations where the time between open/close is so short that the capacitor haven’t had time to charge/discharge enough for the signal to be long enough for the esp8266 to wake up.

@tom_l
Do you have an example code that I can easily implement to test mqtt? I haven’t worked with mqtt before and wanted to ask you before trying to patch something together from other examples.

Ps, Soon I have a 3d printable enclosure were I can use a 14500/14505 LifePo4 battery inside. Which then avoids the overvoltage situation (without adding a LDO), but at a cost of size.

No, I use ESPhome for that.

Ok, that could be a reason for it to be slower than the code I have.
I have tried ESPhome on a simple wifi button before (no mqtt) and it was using around 7-10 seconds from sleeping to the state being updated in home assistant.

Why not use a LiFePo4 battery to avoid the 4.2 volt condition. I use a 400 mAh LiFePo4 AA cell for my ESP32 door switch and I can go for over a year before a recharge is required.

And what is the reaction time?

Yes that is a good solution if you accept the increased size.
As I said in a earlier post I am trying to make an enclosure for the 14500/14050 LifePo4 battery (same size as AA), but I’m having some difficulties.
And later I will add a LDO to the circuit so it won’t be a problem. (Only problem is that I won’t get a different battery reading before the input is lower than 3.3VDC when using ADC_VCC, unless I find some other solution for that problem)

This is what I get from my testing. Will try mqtt at a later point to see if that library is faster.

Update
Added 3d printed box information, battery information and fixed typos.

I have used this outside on my mailbox. Works quite good, the box has been almost 100% waterproof. Battery lasted around 6 months, but my mailbox has very poor wifi reception so the ESP uses sometimes up to a minute before transmitting the message.
Also the batteries I bought were not 200mah, only 140mah.

hello

I’am planning to build 20 of your shared project for my house heating system
with a goal to shutdown the heaters when you open a window more than 2 minutes for ex…
or another usage, should be notifying when i left the house and forgot to close a window…

Do you have some feedback with the batery life time ?

since a year did you make some improvements ?

How do home assistant discover this new devices ? with API ?

Where can i find the differents Libraries ? arduino IDE ?

Thank you for sharing this project i was looking for this for a While !

Best reggards

Answer in PM

I have been looking for this for a long time.
Is it possible to use an esp01s in place of this MCU ? I have seen that gpio5 is needed in this circuit but can we substitute this for any pin the esp01s.

Also is there any revisions in the circuit?

Yes it is possible to use an esp01, but you would need to use a different gpio as you say, and you need to test that it works as expected, also depends on what esp01 board you use.

The only revision is a change I made where I forgot to add a resistor to the board. But you can edit the circuit as you wish.

1 Like