RFID Sensor

Der RFID-Sensor bietet die Möglichkeit Signale eines bestimmten Tags zu erkennen. Diese Signale werden für die Öffnung der Tür des Briefkasten genutzt, wenn der erkannte Tag autorisiert ist.

Der verbaute MFRC522 RFID-Sensor nutzt das SPI-Interface des Wemos D1 Mini und benötigt daher sieben verschiedene Pins um alle nötigen Daten zu übertragen.
Die Schaltung muss, wie in Abb.1 zu sehen, verbunden werden, sodass der RFID-Sensor einwandfrei funktioniert.

Abb 1: RFID Schaltplan1

Im Programm wird zunächst überprüft, ob ein neuer RFID-Tag erkannt wird. Erkennt der RFID-Sensor einen neuen Tag, wird die Variable „ChipID” zurückgesetzt, um mögliche IDs aus vorherigen Erkennungen zu löschen.
Folgend wird die ID des neu ausgelesenen Tags in „ChipID” gespeichert und zur Erkennung in der Konsole ausgegeben.

 /* Nutzt RFID Sensor, um neu gelesenen Chip mit angegebener ChipID zu vergleichen.
   * Wenn der passende Chip gelesen wird, wird true zurueckgegeben, sonst false.
 */
  boolean RFIDDetected(){
    if (mfrc522.PICC_IsNewCardPresent()){
       //ChipID wird resettet
       chipID = 0;
       mfrc522.PICC_ReadCardSerial();
       
       // Neue ChipID in Variable laden
       for (byte i = 0; i < mfrc522.uid.size; i++){
         chipID=((chipID+mfrc522.uid.uidByte[i])*10);
       }
       Serial.println(chipID);


Nach dem Auslesen der ID wird diese mit einem, im Programmkopf festgelegten, Array „grantedChipIDs” verglichen. Dieses Array enthält alle IDs, die dazu berechtigt sein sollen, die Tür des Briefkasten zu öffnen.
Ist die neu ausgelesene „ChipID” in dem Array enthalten, wird der boolescher Wert „grant” auf „true” gesetzt.

 //gelesene ChipID mit allen erlaubten ChipIDs vergleichen
       boolean grant = false;
       for(int i = 0; i < sizeof(grantedChipIDs); i++){
         long tempChipID = grantedChipIDs[i];
         if(chipID == tempChipID){
           grant = true;
         }
       }

Im weiteren Verlauf wird „grant” genutzt, um als Rückgabevariable ein „true” oder „false” zurückzugeben. Ebenfalls wird in der Konsole eine Information zur Zulassung des Tags geschrieben.
Wird kein Chip erkannt, wird dies ebenfalls auf der Konsole wiedergegeben und der Wert „false” zurückgegeben.

//Je nach Ergebnis des Vergleichs wird true oder false zurueckgegeben
       if (grant){
         Serial.println("Zugang gewaehrt!");
         return true;
       } else {
         Serial.println("Chip hat keine Zugangsrechte!");
         return false;
       }
    } else {
      Serial.println("keinen Chip erkannt");
      return false;
    }
  }

In Abb.2 ist die Konsolenausgabe nach dem Erkennen eines zugelassenen Tags zu sehen.

Abb. 2: Konsole nach Erkennung eines zugelassenen Tags

1 MFRC522 RFID Reader am ESP8266 D1 Mini, 08.21.2020 makesmart.net/mfrc522-rfid-reader-esp8266-d1-mini/

Motorsteuerung

Das Projekt enthält zwei Motoren, die die Türen des Briefkastens öffnen. Dabei handelt es sich um Gleichstrommotoren, die mit maximal 12 Volt betrieben werden können. Die Motoren haben zwei Anschlüsse für Plus und Minus. Je nachdem, wie man beide Anschlüsse polt, dreht sich der Motor links- oder rechtsherum. Da der Mikrocontroller nur 5 Volt abgeben kann, die Motoren aber um die 12 Volt brauchen, muss eine externe Stromquelle genutzt werden. Zudem sind fast alle Pins am Mikrocontroller besetzt, wenn die beiden Motoren, der RFID-Sensor und der Abstandsensor angeschlossen werden. Also wird das D1Z Motodriver D1 Shield benötigt (siehe Abb.1). Mit dem Motordriver kann man zwei Motoren ansteuern und eine externe Spannungsquelle verwenden. An den Pins „VM” und „GND” wird die externe Spannungsquelle angeschlossen. An den Pins „A1″, „A2″, „B1″ und „B2″ wird jeweils paarweise ein Motor angeschlossen. Als externe Spannungsquelle werden sechs AA-Batterien verwendet. Der Motordriver kann einfach auf den Mikrocontroller gesteckt werden.

Abb.1: D1Z Motodriver D1 Shield 1

Das Motorshield wird über eine Bibliothek2 gesteuert, die man manuell in der Arduino IDE installieren muss.

//Motor Library
#include "WEMOS_Motor.h"
//Motor shiled I2C Address: 0x30
//PWM frequency: 1000Hz(1kHz)
Motor M1(0x30,_MOTOR_A, 1000);//Motor A
Motor M2(0x30,_MOTOR_B, 1000);//Motor B
//Hilfsvariable damit sich Türen nicht überdrehen
boolean isOpen = false;

	//Oefnnet die Tueren des Briefkasten
	void openDoor(){
    //Abfrage damit Türen sich nicht überdrehen
    if(isOpen){
      return;
    }
    //Motoren drehen sich im Uhrzeigersinn mit Geschwindikeit SPEED
    M1.setmotor( _CW, SPEED);
    M2.setmotor(_CCW, SPEED);
    //Motoren drehen sich für 1500 ms
    delay(1500);
    //Motoren werden angehalten
    M1.setmotor(_STOP);
    M2.setmotor(_STOP);
    //Wird gesetzt damit sich Tuer wieder schliessen kann
    isOpen = true;
	}

	//Schliesst die Tueren des Briefkastens
	void closeDoor(){
     if(!isOpen){
      return;
     }
     M1.setmotor( _CCW, SPEED);
     M2.setmotor(_CW, SPEED);
     delay(1500);
     M1.setmotor(_STOP);
     M2.setmotor(_STOP);
     isOpen = false;
	}

Zuerst werden die beiden Motoren „M1″ und „M2″ definiert. Dazu ist eine Konstante für die Drehgeschwindigkeit und eine Hilfsvariable festgelegt. Die Hilfsvariable sorgt dafür, dass sich die Türen nicht überdrehen. In der Methode „openDoor” wird als Erstes überprüft, ob die Tür schon offen ist. Falls dies zutrifft passiert nichts. Sonst wird die Tür geöffnet. Ein Motor dreht sich im Uhrzeigersinn. Der Andere gegen den Uhrzeigersinn. Beide Motoren werden mit der Geschwindigkeit SPEED geöffnet und nach 1500 Millisekunden wieder angehalten. Nach dieser Zeit haben sich die Türen um ca. 90 Grad gedreht. Die Methode „closeDoor” funktioniert analog nur mit der entgegengesetzten Drehrichtung.

Die Schwierigkeit bei den Motoren war nicht der Programmcode an sich, sondern die technische Umsetzung. Gemeint ist das Finden der passenden Bibliothek, das Verschalten einer externen Stromquelle mit dem Mikrocontroller, die Funktionsweise des Motorshields und weiteres.


1 „D1Z Motodriver D1 Shield” https://www.reichelt.de/de/de/d1-shield-dual-motortreiber-tb6612fng-d1z-motodriver-p266073.html?r=1 (reichelt.de)

2 „WEMOS_Motor_Shield_Arduino_Library” 07.2016 https://github.com/wemos/WEMOS_Motor_Shield_Arduino_Library (Wemos)

Taster

Für den Briefkasten wird ein Taster benötigt, damit man nach ablegen eines Pakets wieder die Tür schließen kann.

Sobald der Taster gedrückt wird, soll an einem Pin des Mikrocontrollers ein „High”-Signal anliegen. Ansonsten liegt ein „Low”-Signal vor. Dies kann mit der Schaltung in Abb.1 realisiert werden.

Abb.1: Schaltung für den Taster

Wenn der Taster gedrückt wird, dann wird die Spannung von der Spannungsquelle zum Pin des Mikrocontrollers durchgelassen. Wenn der Taster nicht gedrückt wird, dann liegt, durch den Widerstand, am Pin ein „Low”-Signal an.

Der dafür benötigte Programmcode ist kurz.

void button(){
  taster = digitalRead(D0);
  if(taster == HIGH){
  closeDoor();
}

Zuerst wird das Signal am Pin, an dem der Taster angeschlossen ist (hier D0), ausgelesen und in der Variable „taster” gespeichert. Wenn die Variable „taster“ den Wert „HIGH” hat, dann wird die Methode „closeDoor()” ausgeführt, die in einem anderen Blogeintrag erläutert wird.

Abstandssensor

Der Abstandssensor dient dazu eine Pushnachricht über Blynk zu senden, wenn sich ein Paket im Briefkasten befindet. Zuerst wurde recherchiert wie der Abstandssensor funktioniert. Der Abstandssensor wird mit 5 Volt betrieben und der „Out”-Pin wird an einen analogen Pin des Mikrocontrollers angeschlossen. Den Abstandssensor ist entsprechend mit dem Mikrocontroller verkabelt und wurde mit dem seriellen Monitor getestet. In dem seriellen Monitor werden Werte ausgegeben, welche der Abstandssensor misst. Sofern sich ein Gegenstand vor dem Abstandssensor befindet, wird ein anderer Wert ausgegeben, als wenn kein Gegenstand vor dem Abstandssensor stände. Dabei wurde auch noch die Empfindlichkeit des Abtsandsensors variiert. Beim Testen wurden zuerst scheinbar zufällige Werte ausgegeben, unabhängig davon, ob ein Gegenstand vor dem Abstandssensor steht oder nicht. Danach wurde selbiges in einer etwas abgedunkelten Umgebung gemacht. Dadurch wurden vernünftige Werte ausgegeben, wenn ein Gegenstand erkannt wurde. Mit diesen Informationen konnte die folgende Methode geschrieben werden.

void loop() {
  while(Blynk.connected() == false){
    Blynk.connect();
    Serial.print(".");
  }
  Blynk.run();
  if(packageDetected()){
    delay(2000);
    Blynk.notify("Du hast ein Paket bekommen!");
    Serial.println("Paket");
  }
}

  /* Nutzt Abstandsensor, um Paket zu erkennen.
   * Sendet eine Nachricht via Blynk, falls ein neues Paket geliefert wurde.
   */
  boolean packageDetected(){
    //Wert den der Abstandssensor ausgibt
    int distance = analogRead(A0);
    //Delay, da auslesen des A0 Pins sonst WLAN Verbindung stört
    delay(100);
    //Wenn ein Paket vorliegt und Nachricht noch nicht gesendet wurde
    if(distance <= MAX_DISTANCE && package == false){
      package = true;
      return true;
    }
    //Wenn Paket entnommen wurde, dann setze alles auf Anfang, um neues Paket erkennen zu können
    if(distance > MAX_DISTANCE){
      package = false;
      return false;
    }

    return false;

}

Dabei wurde „MAX_DISTANCE” auf 1000 gesetzt, da 1024 der Wert ist, den der Abstandssensor ausgibt, wenn sich ein Gegenstand davor befindet. Die Hilfsvariable „package” wird mit „false” initialisiert und dient dazu, dass die Pushnachricht nur einmal gesendet wird. „A0″ ist der Input Pin an dem die Werte des Abstandssensors gelesen werden. Die Methode funktioniert wie folgt: Zuerst wird in „distance” der Wert, den der Abstandssensor ausgibt, gespeichert. Wenn nun ein Paket in den Briefkasten gelegt wird, also der vom Abstandssensor ausgegebene Wert größer als 1000 ist, und noch keine Pushnachricht gesendet wurde, dann wird „true” zurückgegeben und eine Pushnachricht wird gesendet. Außerdem wird noch „package” auf „true” gesetzt, damit die Pushnachricht nur einmal gesendet wird. Wenn das Paket aus dem Briefkasten entnommen wird, also „distance” wieder kleiner als 1000 ist, dann wird „package” auf „false” gesetzt. Dadurch kann beim nächsten Paket wieder eine Pushnachricht gesendet werden. Schließlich wird „false” zurückgegeben.

In der Blynk App muss lediglich ein Notification Element hinzugefügt werden.

Funktionsbeschreibung des Briefkastens

Abb.1: Systemarchitektur und Schnittstellen

Die Abb.1 stellt die Funktion des smarten Briefkastens als Graph dar. Der Graph ist von oben links nach unten rechts zu lesen.

Im Folgenden wird die genauere Funktionsweise des Briefkastens beschrieben:
Der Postbote kann mit seiner RFID Karte den Briefkasten selbstständig öffnen. Wenn der RFID-Sensor den richtigen RFID-Chip oder die richtige RFID-Karte einliest, wird ein entsprechendes Signal an den Mikrocontroller gesendet. Dieser öffnet dann die Türen. Nun kann der Postbote das Paket in den Briefkasten hineinlegen. Durch den Abstandssensor erkennt der Mikrocontroller, dass sich ein Paket im Briefkasten befindet. Anschließend sendet der Mikrocontroller mithilfe der Blynk App eine Pushnachricht an das Handy des Empfängers. Zuletzt kann der Postbote den Briefkasten über einen Tastschalter wieder schließen. Dieser ist an der Außenseite des smarten Briefkastens verbaut. Wenn der Empfänger wieder zu Hause ist, kann er über die Blynk App den Briefkasten öffnen und das Paket herausnehmen.

Blynk

Blynk wird genutzt, um eine Benachrichtigung an das Handy des Nutzers zu senden, sobald der Abstandssensor ein Signal sendet.

Zunächst musste ein neues Projekt in der Blynk App erstellt werden. Hier wurde, wie in Abb.1 zu sehen, das Notification Element hinzugefügt. Die Abb.2 zeigt die vorgenommenen Einstellungen des Elements, die von den Standardeinstellungen nicht abweichen.

Abb.1: Projekt Briefkasten in der Blynk App
Abb.2: Einstellungen des Notification Elementes

Die Verbindung von dem Mikrocontroller zu dem Smartphone des Nutzers wird über den Server von Blynk hergestellt. Um dies umzusetzen, wird zunächst die Blynk Bibliothek als auch die ESP 2866 WiFi Bibliothek eingebunden.
Daraufhin werden Variablen zur Erleichterung der Verbindung zu Blynk festgelegt. Diese beinhalten die WLAN-Verbindungsdaten und der, von Blynk zufällig generierte, Authentifizierungscode. So kann mit „Blynk.begin()” die Verbindung mit den festgelegten Variablen als Parameter aufgestellt werden.
Ein Delay wird eingebaut, um die Verbindungsaufnahme zu erleichtern.

Mit „Blynk.run()” wird Blynk in der loop-Methode gestartet. Ebenfalls wurde eine while-Schleife eingeführt. Diese untersucht mit „Blynk.connected()”, ob die Verbindung abgebrochen wurde und verbindet sie in diesem Fall mit „Blynk.connect()” erneut.

Durch „Blynk.notify(“Du hast ein Paket erhalten!”)” wird eine Benachrichtigung an die Blynk App gesendet. Somit wird der Nutzer benachrichtigt.

Der gesamte Code ist im Folgenden aufgeführt:

//Blynk Libraries
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#define BLYNK_PRINT Serial
//Variablen zur Verbindung mit Blynk
char auth[] = "";
char ssid[] = "";
char pass[] = "";



void setup() {
    Serial.begin(115200);
    //mit Blynk verbinden
    Blynk.begin(auth, ssid, pass);
    delay(500);
}

void loop() {
  while(Blynk.connected() == false){
    Blynk.connect();
    Serial.print(".");
  }
  Blynk.run();
  if(packageDetected()){
    delay(2000);
    Blynk.notify("Du hast ein Paket erhalten!");
    Serial.println("Paket");
  }
}

Abb. 3 zeigt die Blynk App, nachdem eine neue Benachrichtigung eingegangen ist.

Abb. 3: Eingehende Benachrichtung