Mailbox sensor der holder strøm i ~12 år

Vi har desværre et godt stykke ud til vores postkasse, da vores indkørsel er ret lang. Derudover er vores postkasse lavet af metal, som gør at trådløse signaler har lidt svært ved at trænge igennem. Alt dette har jeg prøvet at løse på et par forskellige måder, men jeg har endeligt lavet en løsning, jeg er sikker på nok skal holde.

Indkøbsliste

Derudover skal du bruge en loddekolbe (jeg anbefaler TS100 selvom den er lidt dyr). Indkøbslisten er selvfølgeligt lavet, så du kan lave en tro kopi af min postkasse sensor. Anbefaler jeg det? Nok ikke. Det er ret overkill med to store 18650 batterier til 100+ kroner, en D1 Mini Pro, en MicroWakeupper osv., når der faktisk findes mange andre gode løsninger derude, der blot kræver et par modstande (og selvfølgeligt et par ESPer, hvis du vil køre ESP-NOW).

Indledning

Som jeg nævnte før, har jeg haft problemer med, at enheder ikke kan nå ind til huset, på grund af vores lange indkørsel og postkasse af metal. Det har jeg valgt at løse ved at lave noget helt fra bunden, som endte med at koste mere end hvad jeg havde håbet, men løsningen burde også være ret bulletproof nu. Den er i hvert fald lavet som en rigtig “do it yourselfer” ville have lavet det, for der er plads til en masse modificeringer!

Jeg har været kæmpe fan af Zigbee, men jeg oplevede kun problemer og atter problemer, fordi afstanden ud til postkassen var så stor. Jeg har ellers smidt en CC2652 router ind i huset lige på den anden side af muren, men det virkede kun i perioder. Jeg valgte derfor WiFi med ekstern antenne, for der kan jeg teste det lidt nemmere og få lidt mere kontrol over tingene. Men hvem ved – måske bliver det Zigbee om et par måneder, når jeg er færdig med at lege med mine EBYTE E18 Zigbee enheder (hold øje med et nyt opslag!).

Opsætning

Jeg har valgt at gå med en opsætning der kræver, at min lille D1 Mini er online så kort tid som muligt. Hvert millisekund eller sekund den er tændt, bruger den strøm, som betyder at jeg skal lade batterierne op. Det vil jeg helst ikke gøre, med mindre det er nødvendigt (ja, jeg er meget doven). For at løse det problem, har jeg brugt en MicroWakeupper til at tænde for min D1 Mini. Når magnetsensoren mister forbindelsen, går min D1 Mini i deep sleep, hvor den stort set ikke bruger strøm.

Før den går i søvn, sker der dog alt det sjove. Inde i huset har jeg nemlig opsat en anden ESP8266 som agerer som “gateway”, som sørger for at modtage en besked fra min D1 Mini og sende det op til min MQTT server. Dette gøres via et “koncept” der hedder ESP-NOW. Uden at gå for meget i detaljer, så betyder det blot, at min ESP8266 inde i huset er gateway/master og min D1 Mini i postkassen er en peer/slave. Kært barn har mange navne, men jeg vælger at kalde det for master og slave.

Når kontakten bliver brudt, er min D1 Mini kun tændt i 0.15 til 0.25 sekunder, hvorefter den går i deep sleep igen! Det er utrolig kort tid, og på al den tid formår den at koble til masteren inde i huset, aflæse batteriets spænding og sende den spænding til masteren. Hvis jeg bare brugte WiFi, tog det samme omkring 2 sekunder, og det krævede en masse små hacks, som jeg ikke er særlig stolt af.

TP4056

MicroWakeupperen har ikke nogen form for beskyttelse fra batterierne overhovedet. Jeg har derfor valgt at bruge en TP4056, da jeg havde et par stykker af den liggende. Det fede ved TP4056 er, at du også kan bruge den til at oplade batterierne, hvis de engang løber tør for strøm. Batterierne og komponenterne burde nu være beskyttet mod overcurrent, under voltage og over discharge, hvilket man bestemt har lyst til at få, når man arbejder med lithium batterier.

MicroWakeupper

Grunden til at jeg har valgt at bruge en MicroWakeupper, er fordi det er besværligt at vække en ESP8266 op fra deep sleep. Det kræver man har nogle modstande også, som bare øger kompleksiteten. Da prisen på en MicroWakeupper ikke er særlig høj, gav det god mening at bruge sådan en. Derudover passer den også lige ovenpå en D1 Mini, så du ikke skal gøre noget andet end at lodde headers på den. MicroWakeupperen har desuden også mulighed for at aflæse batteriets spænding, som der også er en fin lille metode til i hans bibliotek. Jeg måtte dog selv gange lidt til tallet, da det ikke passede helt.

Strømforbrug

Jeg har ved hjælp af et lille værktøj fundet ud af, hvor længe jeg kan holde dette projekt i live. Da jeg har 2 batterier, vil den totale kapacitet være fordoblet. Jeg har sat de fleste værdier ret højt, bare for at få et lidt mere realistisk tal ud, men det kan sagtens være at det ikke passer. Jeg har målt mig frem til det meste, og så har jeg valgt de værste tal jeg kunne finde, og selv der, burde den holde strøm i 12 år, hvis jeg åbner min postkasse én gang om dagen:

Det er fuldstændig sindssygt hvis det passer. Hvis bare det holder 1-2 år er jeg meget tilfreds!

Diagram

Jeg har prøvet at tegne et diagram over min opsætning, og det har jeg gjort så det er så let at forstå:

Polariteten på forbindelsen mellem MicroWakeupperen og dør/vindue sensoren er ligegyldig, derfor er ledningerne blot markeret med sort. Du kan spare samlemufferne væk, ved at lodde begge ledninger fra batteriholderne over på TP4056 enheden, men jeg har valgt at bruge en samlemuffe, da jeg altid gør det, når der er mere end én ledning.

ESP-NOW

Som jeg nævnte før, bruger jeg ESP-NOW til at få min D1 Mini til at sende et signal til min ESP8266 inde i huset. ESP-NOW har nogle små irriterende “fejl”, som man er nødt til at arbejde udenom. Det er blandt andet ikke muligt både at lytte efter nye beskeder og være forbundet til routeren på samme tid. Derfor har jeg været nødt til at lave et lille hack, hvor jeg først lytter efter beskeder, derefter genstarter ESPen, forbinder til WiFi, forbinder til MQTT serveren, sender beskeden og forbinder så til ESP-NOW igen, så vi kan lytte efter nye beskeder. Alt det tager omkring 2-3 sekunder, men da det sker inde i huset, skal jeg ikke bekymre mig om et batteri, da min ESP8266 er forbundet til konstant strøm.

Jeg har stjålet noget at min kode fra nettet, rettet lidt et par steder og omskrevet en del af logikken. Det er langt fra det pæneste, men nu er jeg heller ikke C++ programmør, så det må I altså lige leve med.

Montering i postkassen

Jeg har valgt at lime mine komponenter fast (nok ikke det smarteste) til en beholder, som jeg ved er vandtæt. Vi har heldigvis (men også desværre) noget der hedder tyngdekraften, som betyder at ting som regel falder nedad. Det gælder også vand. Jeg har derfor monteret min vandtætte kasse på hovedet, for det er nemlig ikke muligt for vand at løbe opad, så det burde aldrig kunne komme ind i kassen. Jeg har derfor heller ikke noget låg på, for så kan der potentielt set samle sig vand i bunden (altså i låget), og det er jeg ikke interesseret i heller.

Selve monteringen af kassen har jeg gjort med stærk 3M dobbeltklæbende tape, for jeg regner ikke med, at jeg på noget tidspunkt skal have den ud igen. Dog ser jeg limen og tapen som værende det svageste led i hele dette projekt, for jeg har sgu ikke tyngdekraften på min side, desværre.

Magnetsensoren er blot monteret på indersiden af postkassen, hvor selve magneten er monteret på låget af postkassen. Den mister forbindelsen ved at åbne låget, og så modtager jeg en besked på telefonen og i Home Assistant:

Arduino kode

Husk at hente MicroWakeupper koden herfra. Får du problemer med at compile det, så undersøg om dine board settings er korrekte. Virker koden efter compiling ikke, så kig i serial monitor og se om du får noget output.

Slave (D1 Mini)

#include <ESP8266WiFi.h>
#include <MicroWakeupper.h>
extern "C" {
#include <espnow.h>
}

MicroWakeupper microWakeupper;
float battery_multiplier = 1.0785;

uint8_t remoteMac[] = {0x33, 0x34, 0x33, 0x34, 0x33, 0x34};

#define WIFI_CHANNEL 1

volatile boolean callbackCalled;

unsigned long entry1 = millis();

void setup() {
  int i = 0;
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  Serial.printf("This mac: %s, ", WiFi.macAddress().c_str());
  Serial.printf("target mac: %02x%02x%02x%02x%02x%02x", remoteMac[0], remoteMac[1], remoteMac[2], remoteMac[3], remoteMac[4], remoteMac[5]);
  Serial.printf(", channel: %i\n", WIFI_CHANNEL);

  if (esp_now_init() != 0) {
    Serial.println("*** ESP_Now init failed");
    ESP.deepSleep(0);
  }
  
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  
  esp_now_add_peer(remoteMac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);

  esp_now_register_send_cb([](uint8_t* mac, uint8_t sendStatus) {
    callbackCalled = true;
  });

  callbackCalled = false;
}

void loop() {
  float batteryVoltage = microWakeupper.readVBatt() * battery_multiplier;
  String batteryVoltageString = (String)batteryVoltage;
  uint8_t *buffer;
  buffer = (uint8_t*)batteryVoltageString.c_str();

  esp_now_send(NULL, buffer, sizeof(buffer));

  ESP.deepSleep(0);
}

Master (ESP8266)

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
extern "C" {
#include "user_interface.h"
#include <espnow.h>
}


/*
   RET DE VÆRDIER HER
*/
char *ssid      = DIT_SSID_HER;
char *password  = DIN_KODE_HER;

IPAddress mqtt_server(192, 168, 1, 56);
#define mqtt_port 1883

#define BATTERYTOPIC "homeassistant/sensor/mailboxsensor/battery"
#define NEWMAILTOPIC "homeassistant/sensor/mailboxsensor/newmail"
/*
   INDTIL HER
*/

uint8_t mac[] = {0x33, 0x34, 0x33, 0x34, 0x33, 0x34};

void initVariant() {
  wifi_set_macaddr(SOFTAP_IF, &mac[0]);
}

WiFiClient wifiClient;
PubSubClient client(wifiClient);

String deviceMac;

struct __attribute__((packed)) SENSOR_DATA {
  char voltage[240];
} sensorData;

volatile boolean haveReading = false;

int heartBeat;

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_AP);
  initVariant();
  Serial.print("This node AP mac: "); Serial.println(WiFi.softAPmacAddress());
  Serial.print("This node STA mac: "); Serial.println(WiFi.macAddress());

  initEspNow();
  Serial.println("Setup done");
}


void loop() {
  if (millis() - heartBeat > 30000) {
    Serial.println("Waiting for ESP-NOW messages...");
    heartBeat = millis();
  }

  if (haveReading) {
    haveReading = false;
    wifiConnect();

    publishMQTT();

    client.disconnect();
    delay(200);
    ESP.restart();
  }
}

void initEspNow() {
  if (esp_now_init() != 0) {
    Serial.println("*** ESP_Now init failed");
    ESP.restart();
  }

  esp_now_set_self_role(ESP_NOW_ROLE_COMBO);

  esp_now_register_recv_cb([](uint8_t *mac, uint8_t *data, uint8_t len) {

    deviceMac = "";
    deviceMac += String(mac[0], HEX);
    deviceMac += String(mac[1], HEX);
    deviceMac += String(mac[2], HEX);
    deviceMac += String(mac[3], HEX);
    deviceMac += String(mac[4], HEX);
    deviceMac += String(mac[5], HEX);

    memcpy(&sensorData, data, sizeof(sensorData));

    Serial.print("Message received from device: ");
    Serial.print(deviceMac);
    Serial.println(sensorData.voltage);
    Serial.println();

    haveReading = true;
  });
}

void wifiConnect() {
  WiFi.mode(WIFI_STA);
  Serial.println();
  Serial.print("Connecting to "); Serial.print(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(250);
    Serial.print(".");
  }

  client.setServer(mqtt_server, mqtt_port);

  reconnectMQTT();
}

void publishMQTT() {
  String clientId = "Mailbox-";
  clientId += String(random(0xffff), HEX);

  if (!client.connected()) {
    reconnectMQTT();
  }

  String voltage = sensorData.voltage;

  client.publish(BATTERYTOPIC, voltage.c_str());
  client.publish(NEWMAILTOPIC, clientId.c_str());
}

void reconnectMQTT() {
  String clientId = "Mailbox-";
  clientId += String(random(0xffff), HEX);

  while (!client.connected()) {
    client.connect(clientId.c_str());
    delay(1);
  }
}

Home Assistant kode

Jeg har valgt at snyde lidt, fordi jeg ikke helt ved, hvordan man får Home Assistant til at tjekke om der er kommet en ny værdi, hvis den værdi er den samme. Idealt ville jeg sende “true” hvis der var kommet ny mail, men jeg har valgt at sende en tilfældig værdi ind. Du kan derfor tjekke på, om værdien ændrer sig, for så må der være kommet en ny besked i MQTT.

configuration.yaml

sensor:
  - platform: mqtt
    name: "Mailbox sensor new mail"
    state_topic: "homeassistant/sensor/mailboxsensor/newmail"
  - platform: mqtt
    name: "Mailbox sensor battery voltage"
    state_topic: "homeassistant/sensor/mailboxsensor/battery"

Node-RED flow

Burde ikke være så svært at genskabe dette:

Hjælp og kontakt

Jeg har lavet et opslag inde på Dansk Home Assistant gruppe på Facebook, så hvis du har brug for hjælp, kan du eventuelt finde mig derinde og spørge. Alternativt kan du skrive en besked under dette opslag, men jeg kan desværre ikke garantere, at jeg kan svare tilbage (har ikke brugt kommentarfeltet her på siden sååå meget).

Lidt billeder

16 Comments

  • Martin Larsen siger:

    Spændende projekt!

    Et par ting undrer mig dog.

    1. Jeg forstår ikke helt hvorfor du har brug for en microwakeupper? En ESP8266 vækkes ved at sætte RST lav. Andet skal der ikke til.

    2. I beregningen af batteritiden regner du med en duty cycle på 0.3 s. Er det ikke urealistisk at den på den korte tid kan nå at vågne op og forbinde sig til dit WiFi? Jeg har lavet et drivhustermometer efter samme princip (en kort måling, lang søvn) og her tager det 2-3 sekunder at vågne op og sende sin måling.

    • Morten siger:

      Hej Martin! Helt forståeligt at spørge ind – jeg var nemlig selv meget i tvivl, og jeg har endda lige genbesøgt dette projekt efter at have fået ny postkasse, og jeg kan “desværre” kun bekræfte at det er vejen frem.

      1. Ene og alene for at sætte strømforbruget ned. Microwakeupper slukker simpelthen for strømmen, så den bruger 0 strøm (tæt på). Der er stadigvæk, desværre, en spændingsregulator på boardet, så forbruget er et par mikroampere.

      2. De 300 millisekunder er faktisk for højt sat. Det tager ikke mere end cirka 200 millisekunder at vågne op, forbinde til den ESP-NOW masteren inde i huset, sende et payload afsted med spændingen på batteriet og så slukke igen. ESP-NOW er så sindssyg hurtigt. Jeg har købt et Power Profiler Kit II fra Nordic Semiconductors, hvor jeg kan samle 100.000 målinger i sekundet. Jeg har målt alt mellem 150 og 300 millisekunder, og jeg vil hellere være pessimistisk end optimistisk, så jeg satte den til 300 millisekunder.

      Hvis jeg havde 2x ESP inde i huset (en som ESP-NOW master og en anden til at modtage seriel data fra den anden), kunne jeg sende beskeder over MQTT ind i Home Assistant og lignende inden for 1 sekund. Hurtigere end jeg kunne nå at lukke låget til postkassen igen. Dog synes jeg det besværliggjorde projektet at have 2x ESPer, og desuden er jeg ligeglad med at vente de 1-2 sekunder på at få en notifikation. Godt nok modtager jeg mange pakker fra Kina, meeeeen jeg behøver ikke skynde mig ud for at hente dem haha.

      Giv endelig lyd hvis du har flere spørgsmål!

  • Martin Larsen siger:

    Ok, det er da ret vildt så at ESP-NOW kan koble sig på og sende sin pakke så hurtigt. Der er ret lang handshaking med alm. wifi selv om selve pakken kan sendes på nogle millisekunder. Mit termometer bruger ca. 17 uA i deepsleep, og via batteritidsberegneren (fed service i øvrigt!) kan jeg se at deepsleep-strømmen ikke betyder alverden. Om det er 17 eller 50 uA betyder ca. en dags forskel i batteritiden.

    Så det er altså den samlede on-tid som er afgørende. Nu bruger jeg en lille ESP8266-01 uden USB-chip og andre strømforbrugere på, og den får jeg som sagt ned på 17 uA når den sover. Så her ville jeg ikke kunne vinde meget med en microwakeupper.

    Ang. dine kontakter, er det reed switches? Der er vist kun to ledninger, og hall-sensorer bruger normalt tre.

    • Morten siger:

      Helt enig i at der ikke er meget forskel på en Microwakeupper og en ESP-01 i deep sleep. Problemet er at jeg stadigvæk gerne vil kunne koble USB til og reflashe den nemt. Og kæmpe bonus med min D1 Mini Pro er, at jeg kan koble en ekstern antenne til, som er lidt et krav, da forbindelsen ikke er god god ellers.

      Det er reed switches ja. Microwakeupper er så fed at jeg kan vælge NC eller NO (Normally Closed/Open), så jeg skal ikke bekymre mig om hvilken switch jeg bruger.

      • Martin Larsen siger:

        Er dine reedkontakter NC som angivet i linket til ali? Jeg spørger fordi NO er langt de almindeligste. Jeg står nemlig og skal bruge NC til et nært beslægtet projekt, nemlig at give alarm når min datter har glemt at lukke lågen til hamsterburet så det lille kræ render på springtur. Her kunne jeg godt bruge en NC magnetkontakt som er åben (dvs. uden elektrisk forbindelse) når buret er lukket og magneten er tæt på. Men når lågen skydes væk og magneten fjernes, skabes elektrisk kontakt. På den måde kan man faktisk lave en løsning der slette ikke bruger strøm i hvile.

        • Morten siger:

          Jeg har faktisk lidt en blanding af magnetkontakter. Både nogle der er NC og NO. Med Microwakeupper er det ligemeget hvad du bruger, for du kan på en kontakt bare skifte “polariteten” (hvis det giver mening).

          • Martin Larsen siger:

            Jeg er godt klar over at du med microwakeupper selv kan bestemme. Men jeg er som sagt blevet inspireret til et andet projekt hvor jeg hidtil har benyttet en hallsensor, men jeg er kommet frem til at en reedkontakt nok er bedre, det kræver så bare at den er NC. Der er tale om et simplere kredsløb der ikke engang behøver at være i dvale og hvor en microwakeupper vil være totalt overkill. Det er derfor jeg godt ville vide om den kontakt du linker til faktisk er NC som der står. Måske du kan måle den?

            • Morten siger:

              De er normally closed. De skaber forbindelse når jeg sætter magneten på 🙂

              • Martin Larsen siger:

                Jamen så er de normally open. “Normally” refererer til tilstanden når magneten ikke er der. Se fx https://www.magnelinkinc.com/blog/design-guide-reed-switches.

                Der er også en del sælgere der bytter rundt på det, det er derfor jeg ikke var sikker på at sælgeren hos Ali skrev det korrekt.

                • Morten siger:

                  Aha, ja det kan jeg da godt se. Ja det kommer jo lidt an på, hvordan det er blevet fortolket. Med/uden magnet. Jeg kan i hvert fald sige, at dem jeg har testet herhjemme, der har de alle lavet forbindelse, når magnet kom i nærheden.

                  • Martin Larsen siger:

                    Det er også det almindeligste. Men jeg tænker så: hvis nu de er uden forbindelse når magneten er der, og kredsløbet forsynes gennem reedkontakten, så bruger kredsløbet slet ikke strøm. Som i slet ikke. Når så lågen åbnes, og magneten fjernes, så sluttes strømmen til kredsløbet og og det kan udføre sin opgave. Det kan forsimple det en hel del i tilfældet med hamsterburet.

                    Som postkassesensor har den fremgangsmåde dog en oplagt ulempe: Nemlig, hvis lågen står åben hele tiden pga reklamer, så er der fuld strøm til kredsløbet hele tiden. Så her er din metode bedre.

                    • Morten siger:

                      Yes helt enig med dig, at det kunne være vejen frem med dit. I mit tilfælde kunne jeg nok også finde en NC (altså modsat af hvad jeg har) og så sætte den i serie med “voltage in”. Jeg tvivler på postkassen er åben kortere end, lad os bare sige, 500 millisekunder, og det er jo rigeligt hvis man bruger ESP-NOW.

                      Så er spørgsmålet bare om man må trække 100-200 milliampere igennem den. Det må man nok ikke

  • Martin Larsen siger:

    Jeg kommer nok til at genskabe projektet! Dog med ESP-01 da jeg har en del af dem liggende, og jeg kan godt lide at arbejde med dem. Jeg bruger bare en USB-programmer til dem. Og jeg kan se at ESP-NOW også understøtter ESP8266. Rækkevidden er jeg spændt på, men der er kun lidt længere end til drivhuset, så jeg håber det går. Men jeg kan jo flytte termometeret derhen og tjekke.

    Hvor tæt på skal magneten være før reedkontakten lukker? Jeg har kun arbejdet med hall, men fordelen ved reed er jo at den ikke er en aktiv komponent og derfor ikke bruger strøm.

    • Morten siger:

      Du kan helt sikkert godt lave det med ESP-01 – de er også rigtig fede, men lidt øv man skal have en USB programmer til dem.

      Jeg synes desværre de skal være ret tæt på, men jeg ved der findes andre modeller. Dem her er vandtætte (perfekt til udendørs brug) og kan skrues fast, men i mange tilfælde er det også nok at bruge en anden magnet end den der følger med. Gerne en der er lidt kraftigere. Jeg har brugt dem i et par projekter, og jeg synes faktisk ikke det er så slemt. Når først man har fundet det rigtige spot, så sidder den fast og flytter sig ikke 🙂

  • Martin Larsen siger:

    Jeg undrede mig over hvordan modtageren både kunne bruge ESP-NOW og WiFi, men jeg kan se af din kode at du ved modtagelse af data simpelthen forbinder til wifi og genstarter, hvorefter den jo så automatisk reinitialiserer ESP-NOW. Men ved du om det er muligt at have begge protokoller kørende på samme tid, hvis man nu ikke ønsker at genstarte. Fx hvis den er modtager for flere sendere og gerne skulle være “på” hele tiden.

    • Morten siger:

      Det kan man desværre ikke. Det nævnte jeg før, hvor jeg havde brugt en ekstra ESP og så snakkede de sammen serielt. Det er desværre den eneste måde man kan gøre det på, med mindre man vil genstarte.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.