Alarmanlage mit AZ-Touch MOD, ESP8266 und ESP-NOW - AZ-Delivery

Alarm mit AZ-Touch MOD, ESP8266 und ESP-NOW

In diesem Projekt werden wir einen Alarm entwickeln, der erkennt, wenn eine Tür geöffnet wird und sich eine Person oder ein Tier in einem Raum befindet. Für die Realisierung werden ein AZ-Touch-Bausatz mit einem 2,8-Zoll-TFT-Touchscreen, einem linearen magnetischen Hall-Sensor, einem passiven Bewegungssensor (allgemein als PIR-Sensor bezeichnet) und drei ESP8266-Mikrocontrollern verwendet. Für die Kommunikation zwischen den Mikrocontrollern wird das ESP-NOW-Kommunikationsprotokoll genutzt, das eine Verkabelung zwischen den Modulen vermeidet.

Das ESP-NOW Protokoll ist sehr vielseitig. Es können damit mehrere Sendemodule mit einem einzigen Empfängermodul kommunizieren, ein Sendemodul mit mehreren Empfängermodulen und ein Sender mit einem Empfänger, sowohl in einer Richtung, als auch bidirektional. Es kann auch abgefragt werden, ob die gesendeten Informationen das Ziel erreicht haben. Fangen wir an.

Benötigte Hardware und Materialien

Benötigte Software, Bibliotheken und Sketches

Schaltplan

Wenn wir das Komponentendiagramm analysieren, können wir sehen, dass wir zwei Sätze von NodeMCU Lolin ESP8266 Mikrocontrollern und Sensoren als Sender und den D1 Mini NodeMCU ESP8266 Mikrocontroller zusammen mit dem AZ-Touch MOD als Empfänger verwenden werden. Die Stromversorgung für die Sendemodule erfolgt über den Micro-USB-Anschluss.

Programmablauf und Sketches

Die beiden ESP82266 der Sensoren senden die Informationen mit den Daten der Nummer, die dem Sensor zugewiesen ist, und dem Zustand (HIGH oder LOW) des digitalen Pins. Der lineare magnetische Hall-Sensor wird am oberen Rahmen einer Tür installiert und ein kleiner Magnet wird an der Tür so nah wie möglich am Sensor angebracht. Der Sensor wird bei geschlossener Tür auf HIGH-Pegel sein, da der Magnet nahe am Sensor ist. Das ist die normale Situation und die Meldung „OK“ auf dem TFT-Bildschirm neben dem Namen des Sensors erscheint. Wenn die Tür geöffnet wird, wird der kleine Magnet vom Sensor entfernt und der Sensor geht auf „LOW Level“. Dann ändert sich die Meldung auf dem TFT-Bildschirm in "Alarm" und es erscheint eine Warnzeile mit der Meldung „Door Alarm Detected“. Der Anwesenheitssensor (PIR) wird in einer oberen Ecke eines beliebigen Raumes platziert. Er befindet sich auf LOW-Level, solange er nichts erkennt, wobei die Meldung „OK“ erscheint.  Wenn er eine Anwesenheit erkennt, geht er auf HIGH-Level über und die Meldung „Alarm“ erscheint auf dem TFT-Bildschirm. Genau wie beim anderen Sensor, werden wir über „PIR Alarm Detected“ informiert. In beiden Fällen ertönt beim Wechsel zu „Alarm“ der Summer, bis wir auf dem Bildschirm "Delete Message" drücken. Im AZ-Touch-Bausatz wird der Mikrocontroller D1 Mini NodeMCU installiert, der die Sensor-Identifikationsdaten und den Status der digitalen Pins empfängt. Er steuert auch die Anzeige für die Meldungen auf dem TFT-Bildschirm und den Ton des Summers.

Um eine Kommunikation zwischen den ESP8266 zu ermöglichen, benötigen wir die MAC-Adresse des Mikrocontrollers, den wir als Empfänger verwenden werden. Um diese Adresse zu erhalten, schließen wir den Mikrocontroller an den Rechner an, öffnen die Arduino IDE, wählen das passende Board und den Port aus, öffnen den Serial Monitor und führen den Sketch get_mac_address.ino aus. Die MAC-Adresse des Mikrocontrollers erscheint im Serial Monitor. Speichern Sie diese Information, da Sie sie später benötigen werden.

Hinweis: um den ESP8266 programmieren zu können, müssen Sie den ESP8266 Arduino Core über den Boardverwalter installieren. Dazu müssen Sie vorher in den Voreinstellungen die passende Boardverwalter-URL hinzufügen:

https://arduino.esp8266.com/stable/package_esp8266com_index.json

/*--  Sketch to Obtain MAC address ESP module  --*/  

#ifdef ESP32
#include <WiFi.h>
  
#else
#include <ESP8266WiFi.h>
#endif

void setup(){
      Serial.begin(115200);
      Serial.println();
      Serial.print("ESP Board MAC Address:  ");
      Serial.println(WiFi.macAddress());
}
 
void loop(){

}

Mit diesem Sketch können Sie die MAC-Adresse von ESP8266 und ESP32 Mikrocontrollern anzeigen lassen. Sie müssen dazu das passende Board auswählen.

Hinweis: Für den ESP32, der in diesem Projekt nicht verwendet wird, brauchen Sie ebenfalls die passende Boardverwalter-URL.

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Dieses Alarmprojekt besteht aus drei Sketches:

Die Namen sind so gewählt, dass sie leicht zugeordnet werden können. Die beiden Sensor-Sketches sind praktisch identisch. Es muss lediglich die ID-Nummer des Sensors geändert und eine Zeile mit einer Verzögerung des Anwesenheitssensors hinzugefügt werden, um einen optimalen Betrieb zu gewährleisten. Beschreiben wir den Sketch des Bewegungssensors (die beiden Sketches der Sender sind sich sehr ähnlich, daher wird nur einer von ihnen genauer beschrieben) und des AZ-Touch-Moduls.

Bewegungssensor pir_sensor_module_2.ino

Da wir ESP8266-Mikrocontroller und das ESP-NOW-Kommunikationsprotokoll verwenden werden, müssen wir die passenden Bibliotheken inkludieren, um dessen Methoden und Anweisungen zu implementieren.

#include <ESP8266WiFi.h
#include <espnow.h>

Nach den Bibliotheken müssen wir den GPIO-Pin des ESP8266 definieren, an den wir den digitalen Pin des Sensors anschließen werden. Der Anschluss-Pin an den ESP8266 ist D7, der laut Datenblatt GPIO 13 entspricht. In der nächsten Zeile müssen wir die MAC-Adresse des Moduls angeben, an das wir die Daten senden werden. Diese MAC-Adresse ist in diesem Projekt die des Empfänger-Mikrocontrollers D1 Mini NodeMCU ESP8266 des AZ-Touch. In der dritten Zeile müssen wir die Nummer konfigurieren, mit der der Sensor identifiziert wird. Für den PIR-Sensor ist es emiter_board_id 2, während für den linearen magnetischen Hall-Sensor emiter_board_id 1 gewählt wird.

int pir_sensor = 13;
uint8_t receiver_board_MAC_address[] = {0xA4, 0xCF, 0x12, 0xF4, 0xCE, 0x12};
#define emiter_board_id 2

Als Nächstes müssen wir die Struktur konfigurieren, die die Daten enthält, die wir senden werden. Sie bekommt den Namen sensor_state. Es werden dann die Variablen definiert, die wir für das Projekt verwenden werden. ID wird die Sensornummer sein (Nummer 2 für den PIR-Sensor und Nummer 1 für den magnetischen Hallsensor linear) und den Variablenwert, der den Zustandswert des digitalen Ausgangs des Sensors enthält.

typedef struct sensor_state {
    int id;
    int value;
} sensor_state;

Sobald wir die Struktur definiert haben, müssen wir ein Objekt dieser Struktur implementieren, es bekommt den Namen state.

sensor_state state

Für das Intervall der Sensorprüfung werden zwei Variablen erstellt, die die Zeit der letzten durchgeführten Prüfung lastTime und timerDelay enthalten. In diesem Fall wiederholt sich die Sensorprüfung alle 1000 ms, also im Intervall von einer Sekunde.

unsigned long lastTime = 0;
unsigned long timerDelay = 1000;

Eines der Merkmale des ESP-NOW-Protokolls ist, dass wir Informationen über den Status der gesendeten Daten erhalten können. Dazu muss ein „Rückruf“ (callback) mit der OnDataSent-Methode durchgeführt werden, deren Argumente *mac_addr, das ist die MAC-Adresse des empfangenden Mikrocontrollers und sendStatus sind, das ist das Feedback zum Senden. Eine 0 bedeutet, dass das Senden der Daten erfolgreich war. Eine 1 steht für das fehlgeschlagene Senden der Daten. Die Statusinformationen zum Senden von Daten werden im Serial Monitor angezeigt.

void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
        Serial.print("\r\nLast Packet Send Status: ");
        if (sendStatus == 0){
          Serial.println("Delivery success");
        } else{
              Serial.println("Delivery fail");
        }
}

Wir implementieren die Methode setup(), um den Anfangszustand des Mikrocontrollers zu konfigurieren, wenn er mit Strom versorgt oder zurückgesetzt wird. Als erstes initialisieren wir den Serial Monitor.

Serial.begin(115200);

Die Kommunikation zwischen den Modulen wird über Wi-Fi erfolgen. Aber wir werden das drahtlose Netzwerk des heimischen Routers nicht verwenden, also müssen wir den ESP8266 mit WiFi.disconnect() vom lokalen Netzwerk trennen und ihn als unabhängige WiFi-Station konfigurieren mit WiFi.mode(WIFI_STA).

WiFi.mode(WIFI_STA);
WiFi.disconnect();

Anschließend wird überprüft, ob das ESP8266-Modul korrekt initialisiert wurde. Wenn nicht, wird das im Serial Monitor ausgegeben.

if (esp_now_init() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Nachdem der ESP8266 initialisiert wurde, wird das Modul mit der Anweisung esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER) als Sender konfiguriert. In der nächsten Zeile erstellen wir das Register esp_now_register_send_cb, um den Callback auszuführen. Dann müssen wir einen Kommunikationskanal mit dem Empfänger erstellen, indem wir den empfangenden ESP8266 zur ESP-NOW-Kommunikationstabelle durch die Anweisung esp_now_add_peer(receiver_board_MAC_address, ESP_NOW_ROLE_SLAVE, 1, NULL, 0) hinzufügen. Die Argumente sind die MAC-Adresse des Empfängermoduls, die Rolle des Empfängers als „SLAVE“ und der Kommunikationskanal. Allgemeinen von 1 bis 13, in diesem Fall wählen wir Kanal 1. Die letzten beiden Argumente wären der Kommunikationsschlüssel und die Länge. Da hier der Zugriffsschlüssel nicht konfiguriert wird, wird er auf NULL gesetzt, also ist seine Länge 0 (das letzte Argument).

esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_register_send_cb(OnDataSent);
esp_now_add_peer(receiver_board_MAC_address, ESP_NOW_ROLE_SLAVE, 2, NULL, 0);

Die folgende Zeile ist nur im Sketch des Bewegungssensors enthalten, da der Sensor durch Anlegen einer Spannung stabilisiert werden sollte, um eine zuverlässige Erkennung zu ermöglichen. Es wird eine Wartezeit von einer Minute eingestellt.

delay (60*1000);

Mit dieser letzten Zeile haben wir die Methode setup() beendet. Die Methode loop() hat nur einen einfachen bedingten Block, der im Intervall von einer Sekunde ausgeführt wird. Um den if-Block auszuführen, prüfen wir, ob 1 Sekunde vergangen ist, indem wir die gespeicherte Zeit der letzten Datenübertragung (lastTime) mit der aktuellen Zeit (millis) subtrahieren. Ist eine Sekunde vergangen, wird ein Datenpaket gesendet. Es enthält die Felder Sensornummer und Pin-Status des Sensors, die in der Datenstruktur sensor_state definiert wurde. Die drei Argumente der Anweisung esp_now_send(0, (uint8_t *) &state, sizeof(state)) sind die MAC-Adresse des empfangenden Mikrocontrollers, in diesem Fall senden wir mit 0 die Daten an alle Adressen in der Tabelle (wir haben nur einen Empfänger), das Paket mit den beiden Daten (ID und Zustand des digitalen Pins) und die Größe des zu sendenden Datenpakets. Mit der letzten Zeile speichern wir den Zeitpunkt der letzten Datenübermittlung in der Variablen lastTime.

if ((millis() - lastTime) > timerDelay) {
  state.id = emiter_board_id;
  state.value = digitalRead (pir_sensor); 
  esp_now_send(0, (uint8_t *) &state, sizeof(state));
  lastTime = millis();
}

Empfänger AZ-Touch az_touch_receiver_esp8266.ino

Dieser Sketch wird auf den Mikrocontroller D1 Mini NodeMCU ESP8266 geladen, der im AZ-Touch installiert wird und der Datenempfänger sein wird. Die ersten beiden Bibliotheken, die eingebunden werden müssen, sind die für die WiFi-Verbindung des ESP8266 und des ESP-NOW-Kommunikationsprotokolls.

#include <ESP8266WiFi.h>
#include <espnow.h>

Die weiteren Bibliotheken sind notwendig, um die Arduino-Funktionen (Arduino.h), das SPI-Kommunikationsprotokoll (SPI.h) verwenden zu können, um mit dem TFT-Bildschirm kommunizieren zu können. Auch die Bibliotheken für die Nutzung des besagten TFT-Bildschirms (Adafruit_ILI9341.h), der grafischen Funktionsanweisungen (Adafruit_GFX.h) und des „Touchscreens“ (XPT2046_Touchscreen.h) werden benötigt. Die letzte Bibliothek (Fonts/FreeSans9pt7B.h) enthält die Bitmap der Schriftarten oder Buchstaben.

#include <Arduino.h>
#include <SPI.h>
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <XPT2046_Touchscreen.h>
#include <Fonts/FreeSans9pt7b.h>

Die nächste Zeile beschreibt als Konstante den 2,8-Zoll-Bildschirm im AZ-Touch.

#define AZ_TOUCH_MOD_BIG_TFT

Die Pins, an die der TFT-Bildschirm angeschlossen wird, sind bereits standardmäßig durch das AZ-Touch-Design vorgegeben. In der Deklaration geben wir die GPIO-Pins dafür an. Die erste Zeile ist ein Hinweis darauf, dass das Display den gelben Pin-Anschluss hat. Die zweite Anweisung (#define TFT_CS 5) ist die Verbindung zum GPIO-Pin zum Aktivieren oder Deaktivieren des TFT-Displays. Die dritte Anweisung (#define TFT_DC 4) ist die Verbindung zum GPIO-Pin, an dem der Data-Command-Pin des TFTs anliegt. Darüber wird ihm mitgeteilt, ob es Daten oder einen Befehl empfängt. Die letzte Anweisung (#define TFT_LED 15) ist die Verbindung zu dem GPIO-Pin, der die Hintergrundbeleuchtung des Displays ein- oder ausschaltet.

#define touch_yellow_header
#define TFT_CS 5
#define TFT_DC 4
#define TFT_LED 15

Anschließend werden die Pins deklariert, an die der „Touchscreen“ des TFT-Bildschirms angeschlossen wird. Diese Pins sind ebenfalls durch das Design des AZ-Touch vorgegeben. Die erste Zeile ist ein Hinweis darauf, dass der Bildschirm einen Touchscreen hat. Die zweite Anweisung (#define TOUCH_CS 0) ist die Verbindung zum GPIO-Pin, die den Touchscreen aktiviert oder deaktiviert. Die dritte Anweisung (#define TOUCH_IRQ 4) ist die Verbindung zu dem GPIO-Pin, über den signalisiert wird, dass der Touchscreen berührt wurde.

#define HAVE_TOUCHPAD
#define TOUCH_CS 0
#define TOUCH_IRQ 2

Es wird außerdem ein Buzzer verwendet, dessen Pin mit der folgenden Zeile festgelegt wird:

#define BUZZER 16

Die weiteren Konstanten sind die Parameter zur Verwendung des Touchscreens. Um damit zu interagieren, wird ein Mindestdruck auf den Bildschirm benötigt. Das wird konfiguriert mit #define MINPRESSURE 10. Außerdem werden die Grenzen der X- und Y-Achse benötigt. Es werden hier von analog nach digital konvertierte Werte verwendet, um jeweils das Minimum und Maximum anzugeben.

#define MINPRESSURE 10
#define TS_MINX 370
#define TS_MINY 470
#define TS_MAXX 3700
#define TS_MAXY 3600

Um die Methoden und Anweisungen sowohl des Bildschirms, als auch des Touchscreens zu verwenden, wird ein Objekt aus jeder Bibliothek implementiert. Als Argument wird der CS-Pin, für den Bildschirm zusätzlich der DC-Pin angegeben. Die Funktionen der einzelnen Pins wurden bereits oben erläutert.

Adafruit_ILI9341 tft_screen = Adafruit_ILI9341(TFT_CS, TFT_DC);
XPT2046_Touchscreen touch_screen(TOUCH_CS);

Es wird nun die Struktur konfiguriert, die die von den Sendermodulen gesendeten Daten empfängt. Diese Struktur muss die gleiche sein wie die, die in den beiden Sketches der Sendermodule implementiert ist. Wie Sie sich erinnern werden, wurde sie sensor_state genannt und enthält die Variablen id (Sensornummer) und den Variablenwert des Zustandes des digitalen Pins jedes Sensors. Es wird dann die Zustandsvariable dieser Struktur erstellt, um die empfangenen Daten darin zu speichern.

typedef struct sensor_state {
      int id;
      int value;
} sensor_state;

sensor_state state;

Als Nächstes erstellen wir für jeden Sender eine Variable der vorher angegebenen Struktur, der später die vom entsprechenden Sendermodul empfangenen Daten zugewiesen werden. Außerdem erstellen wir ein Array, das diese Variablen enthält.

sensor_state hall_sensor;
sensor_state pir_sensor;

sensor_state emiter_boards[2] = {hall_sensor, pir_sensor};

Wie im Sketch der Sendermodule programmiert, machen wir auch im Empfängermodul einen „Callback“, der ausgeführt wird, wenn das Empfängermodul Daten per ESP-NOW empfängt. Die Funktion void OnDataRecv() bekommt mehrere Argumente. Die MAC-Adresse des Sendermoduls mit uint8_t * mac_addr, die Statusdaten des digitalen Pins des Sendermoduls mit uint8_t *incomingData und die Größe der übermittelten Daten mit uint8_t len.

Im 18-stelligen char-Array char macStr[18] werden die von der MAC-Adresse der Module empfangenen Zeichen gespeichert und mit der Funktion snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x : %02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]) wird alles zu einem String zusammengesetzt, um ihn dann im Serial Monitor mit Serial.println(macStr) auszugeben.

void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {     
  char macStr[18];
  Serial.print("Packet received from: ");
  
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);

  Serial.println(macStr);
}

Bevor wir mit der Erklärung der Skizze fortfahren, müssen wir uns an zwei Dinge erinnern:

  • In den jeweiligen Sketches der Sender wird dem linearmagnetischen Hallsensor (#define emitter_board_id 1) die ID 1 und dem Näherungssensor die ID 2 (#define emitter_board_id 2) zugewiesen.
  • Im Sketch des Empfängermoduls wird ein Array mit den Namen der Sensoren erstellt (sensor_state emitter_boards[2] = {hall_sensor, pir_sensor}) erstellt. Im Array wird dem ersten Element die ID 0 und dem zweiten die ID 1 zugewiesen.

Es ist notwendig, sich daran zu erinnern, weil [state.id-1] verwendet wird, um den Sensor zu identifizieren, der die Informationen gesendet hat. Also sendet der ESP8266 des magnetischen Hallsensors die Informationen mit der ID 1. Es wird davon 1 subtrahiert und der Sensor überprüft, der dieser Position im Array entspricht.

Weiter im Sketch. Mit memcpy(&state, incomingData, sizeof(state)) wird der Dateninhalt der incomingData-Variablen in die state-Variable der Struktur mit den von einem der ESP8266 gesendeten Werten kopiert. Mit emitter_boards[state.id-1] wird der Sender identifiziert, der die Daten gesendet hat. Darüber wird auch der Zustand des digitalen Pins dieses Moduls ermittelt mit emitter_boards[state.id-1].value. Die Informationen des digitalen Pin-Status mit 0 oder 1 und die Länge der Informationen, normalerweise 8 Bytes, werden im Serial Monitor ausgegeben.

memcpy(&state, incomingData, sizeof(state));
Serial.printf("Sensor %u: %u bytes\n", state.id, len); 

emiter_boards[state.id-1].value = state.value;
Serial.printf("state: %d \n", emiter_boards[state.id-1].value);
Serial.println();

Die Informationen, die auf dem TFT-Bildschirm angezeigt werden, werden unterteilt in statischen Text (den Titel, die Namen der Sensoren und die Zeile zum Löschen der Meldungen) und einen dynamischen Text (Status der Sensoren und die Zeile mit den Informationen des Sensors, der das Eindringen festgestellt hat). Da sich der statische Text nicht ändert, wird er in der Methode setup() programmiert. Der dynamischen Text wird in der Funktion OnDataRecv programmiert, die ständig ausgeführt wird. Folgend wird beschreiben, wie der dynamische Text angezeigt wird.

Da der digitale Pin-Status der Sensoren HIGH oder LOW sein kann und es zwei Sensoren gibt, wird eine verschachtelte Bedingung programmiert. So wird zuerst der vom digitalen Pin-Status empfangene Wert geprüft. In jeder Bedingung wird mit einer Switch-Anweisung eine mehrfache Bedingung programmiert, um zu prüfen, welcher der Sensoren den Wert gesendet hat.

Dann wird als erste Bedingung geprüft, ob der Zustand des digitalen Pins der empfangenen Daten HIGH ist (if(state.value == HIGH)). Wenn diese Bedingung erfüllt ist, werden die Anweisungen des if-Blocks ausgeführt, wenn er LOW ist, wird der else-Block ausgeführt.

if(state.value == HIGH) {                                           // If the value is a 1, this block is executed
  switch (state.id-1) {                                         // Emitter module check
    case 0:                                                   // Hall sensor module,the first position in the array
        Serial.println("Hall sensor normal situation"); 
        ...
    case 1:
        Serial.println("PIR Sensor Intrusion Detected");
        ...
  }
} else {                                                            // The value is not 1, then this other block is executed 
  switch (state.id-1) {                                         // Emitter module check
    case 0:
        Serial.println("Hall Sensor Intrusion Detected ");
        ...
    case 1:
        Serial.println("PIR Sensoe Normal Situation ");
        ...
  }
}

In der Switch-Anweisung wird über (state.id-1) geprüft wird, welcher der Sensoren den Wert gesendet hat. Der Sensor mit Position 0 der Matrix ist, ist der lineare Hall-Sensor. Über den Serial Monitor wird die Nachricht "Hall sensor normal situation" ausgegeben. Die folgenden Anweisungen zeigen den dynamischen Text auf dem TFT-Bildschirm:

  • Schriftart festlegen mit setFont(&FreeSans9pt7b)
  • Textgröße festlegen auf 1 mit setTextSize(1)
  • Cursor auf die Koordinaten x=180 und y=45 setzen mit setCursor(180, 45)
  • Textfarbe auf Schwarz festlegen mit setTextColor(ILI9341_BLACK)
  • den Text „Alarm“ mit println("Alarm") ausgeben, um ihn zu löschen, da er die gleiche Farbe hat wie der Hintergrund
  • Cursor auf die Koordinaten x=150 und y=45 setzen mitsetCursor(150, 45)
  • Textfarbe auf grün setzen mit setTextColor(ILI9341_GREEN)
  • den Text „OK“ mit println("OK") auf grün setzen

Wenn im Gegensatz dazu bei der Überprüfung des Sensors die ID 1 ist, bedeutet dies, dass die Dateninformationen vom Bewegungssensor gesendet wurden und die Anweisungen für Fall 1 ausgeführt werden. Diese sind:

  • „PIR Sensor Intrusion Detected“ im Serial Monitor ausgeben
  • Schriftart des Textes festlegen mit setFont(&FreeSans9pt7b)
  • Textgröße festlegen mitsetTextSize(1)
  • Cursor mit setCursor(150, 70) auf die Koordinaten x=150 und y=70 setzen
  • Textfarbe auf Schwarz setzen mit setTextColor(ILI9341_BLACK)
  • Den Text „OK“ schreiben mit println("OK"), um den Text in diesen Koordinaten zu löschen, da die Hintergrundfarbe des Bildschirms genau wie der Text schwarz ist
  • Cursor mit setCursor(180, 70) auf die Koordinaten x=180 und y=70 setzen
  • Textfarbe auf Rot setzen mit setTextColor(ILI9341_RED)
  • den Text „Alarm“ ausgeben mit println("Alarm")
  • Cursor mit setCursor(2, 145) auf die Koordinaten x=2 und y=145 setzen
  • Textfarbe auf Schwarz setzen mit setTextColor(ILI9341_BLACK)
  • den Text „Door Alarm Detected“ ausgeben mit println("Door Alarm Detected"), um den Text an diesen Koordinaten zu löschen, da die Hintergrundfarbe des Bildschirms auch schwarz ist.
  • Cursor mit setCursor(2, 145) auf die Koordinaten x=2 und y=145 setzen
  • Textfarbe auf Rot setzen mit setTextColor(ILI9341_RED)
  • den Text PIR „Alarm Detected“ ausgeben mitprintln("PIR Alarm Detected")
  • Buzzer ertönt mit einer Frequenz von 4000 Hz mit tone(buzzer, 4000), bis die Alarmmeldung später gelöscht wird

Für den Fall, dass der digitale Pin der Sensoren LOW ist, wird wie oben beschrieben der else-Block ausgeführt. Die Befehle ähneln sehr dem if-Block.

Sehen wir uns nun an, was zu implementieren ist, um die Alarmmeldung vom TFT-Bildschirm zu löschen und den Ton auszuschalten. Dazu wird eine Bedingung programmiert, da zum Löschen der Nachricht ein Bereich des TFT-Bildschirms mit einem Druck berührt werden muss. Er muss größer sein, als das konfigurierte Minimum. Wenn Sie in den durch die Koordinaten x>4 und y>280 Pixel begrenzten Bereich klicken und einen Druck größer als einen Wert von 10 ausüben, wird auf dem Bildschirm ein schwarzes Kästchen mit einer Breite von 239 und einer Höhe von 30 Pixeln gezeichnet, dessen linke obere Ecke bei den Koordinaten x=0 und y = 145 liegt. Also wird alles innerhalb dieser Box gelöscht. Auch der Zustand des GPIO-Pins des Buzzers wird auf LOW geändert, sodass er aufhört zu piepen.

if (touch_screen.touched()) {
  TS_Point p = touch_screen.getPoint();
  if (p.x > 4 && p.y > 280 && p.z > MINPRESSURE) {
    tft_screen.fillRect (0, 145, 239, 30, ILI9341_BLACK); 
    digitalWrite(buzzer, LOW);        
  }
}

Soweit die OnDataRecv()-Funktion. Es folgt die Beschreibung der setup()-Funktion. Als erstes wird die Initialisierung des Serial Monitors mit Serial.begin(115200) programmiert.

Wie beim ESP8266 der Sendermodule wird das WLAN des heimischen Routers nicht genutzt. Also wird der ESP8266 mit WiFi.disconnect() vom lokalen Netzwerk getrennt und als eigenständige WiFi-Station mit WiFi.mode(WIFI_STA) konfiguriert.

WiFi.mode(WIFI_STA);
WiFi.disconnect();

Es wird auch geprüft, ob das ESP8266-Modul korrekt initialisiert wurde. Wenn nicht, wird es im Serial Monitor ausgegeben.

if (esp_now_init() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Mit esp_now_set_self_role(ESP_NOW_ROLE_SLAVE) wird der Empfänger als „SLAVE“ konfiguriert. In der nächsten Zeile erstellen wir das Register esp_now_register_recv_cb(OnDataRecv), um die Funktion OnDataRecv aufzurufen, wenn die Daten empfangen werden.

esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
esp_now_register_send_cb(OnDataRecv);

Mit der Funktion pinMode(TFT_LED, OUTPUT) wird der Pin des ESP8266, an den die Hintergrundbeleuchtung des TFT-Bildschirms angeschlossen ist, als Ausgang konfiguriert.

In den folgenden Zeilen werden der TFT-Bildschirm mit tft_screen.begin() und der Touchscreen mit touch_screen.begin() initialisiert. Im Serial Monitor werden die Informationen der Breite (X-Achse) und Höhe (Y-Achse) des Bildschirms in Pixeln ausgegeben. Mit der letzten Zeile wird der gesamte Bildschirm mit Schwarz gefüllt.

Serial.println("Init TFT and Touch ...");      
tft_screen.begin();         
touch_screen.begin();         
Serial.print("TFT x = ");         
Serial.print(tft_screen.width());       
Serial.print("TFT y = ");         
Serial.print(tft_screen.height());      
tft_screen.fillScreen(ILI9341_BLACK);

Mit der Anweisung digitalWrite(TFT_LED, HIGH) wird der GPIO-Pin des Mikrocontrollers, an dem die Hintergrundbeleuchtung des TFT-Bildschirms angeschlossen ist, auf einen HIGH-Zustand gesetzt. So wird dieser eingeschaltet. Der restliche Code im setup() ist die Ausgabe des statischen Textes auf dem Bildschirm.

In diesem Sketch ist die loop()-Funktion leer.

Viel Spaß mit diesem Projekt und wir freuen uns auf Ihre Kommentare und Vorschläge, vielen Dank.

 

 

Esp-8266SensorenSmart home

8 comentarios

Lutz

Lutz

Ein Link zu einer Beschreibung ,die das mit der Benutzung der Verschlüsselung zeigt. Man sollte sich aber nicht zuviel davon versprechen, es sind eben nur 128 Bits (16*8). Und die Anzahl der Aktoren wird auf ca. 6 begrenzt
https://www.14core.com/how-to-esp32-encrypted-data-transmission-send-receive-data-with-esp-now-protocol/

Miguel Torres

Miguel Torres

Hi Sven,

We are glad to hear that you liked this project and will be using it.

Thank you very much and best regards,

Miguel Torres Gordo

Miguel Torres

Miguel Torres

Hi Ilija,

Thanks for the comment about MQTT.

Best regards,

Miguel Torres Gordo

Sven Hesse

Sven Hesse

Hallo Miguel,

vielen Dank für dieses Tutorial.
Da bei mir immer einige Teile auf “Halde” liegen – so auch alle benötigten für diese Alarmanlage – habe ich direkt aufgebaut.
Nachdem ich einen, durch zu schnelles Lesen entstandenen, Fehler beseitigt habe, funktioniert alles bestens.
Da der Stromverbrauch recht gering ist, werde ich diese Anlage wohl für meine Gartenlaube verwenden (hier habe ich nur Solarstrom zur Verfügung).

Also – nochmals vielen Dank.
Sven

Ilija Iliev

Ilija Iliev

Hi Freddy,
MQTT need server to re-transmit messages between units. This need additional resources as Raspberry or Esp32 as server and it cannot go to sleep mode, so need much more energy. In addition MQTT can be hacked easy, if you want stable project, then you should activate security on server. Activating security/encryption is nightmare and need cerificates, so not an easy game.
Regards
Ilija

Miguel Torres

Miguel Torres

Hello Freddy Aout,

For powering the ESP8266 external batteries with 5VDC outputs have been used in this project to charge cell phones. The power consumption of the ESP is low, so the battery life should be great and depends on the battery capacity.

From what I have been able to read, the MQTT communication protocol is compatible with ESP8266, but the sketch would have to be adapted to the new communication protocol and tested.

Best regards,
Miguel Torres Gordo

Freddy Aout

Freddy Aout

Qu’utilisez vous comme batterie pour alimenter les ESP8266 ? Combien de temps tiennent elles ?
Une autre question : Pourrait on remplacer EPS-NOW par des messages MQTT ?

What do you use as a battery to power the ESP8266? How long do they last?
Another question: Could EPS-NOW be replaced by MQTT messages?

Joachim

Joachim

Schönes Projekt.
Schade das Sie für eine Alarmanlage keine verschlüsselte Übertragung gewählt oder beschrieben haben.

Deja un comentario

Todos los comentarios son moderados antes de ser publicados