Kontrolle von Garagentor und Briefkasten          

von Günther Zöppel                       
 
                      Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller                        



Download: Garagentor_Briefkasten_Kontrolle.ino

Schon immer störte mich, dass ich nochmals vors Haus gehen muß, um nachzusehen, ob meine beiden Garagentore wirklich geschlossen sind und ob nicht eventuell Post im Briefkasten liegt. Das brachte mich auf die Idee, eine gerade vorhandene Hardware  Arduino Uno mit TFT-LCD Shield 2.4“ dafür zu nutzen, um die Anzeige im Haus an einer günstigen Stelle zu platzieren. Von der Garage bis ins Haus wurde dazu ein 4-adriges Kabel durch bereits vorhandene Leerrohre gezogen, welche die Sensorsignale der beiden Tore und des Briefkastens an den Arduino Uno übertragen. Diese Signale könnten auch per WLAN übertragen werden, aber da das Leerrohr bereits lag, habe ich die konventionelle Methode gewählt und diese ist damit auch relativ störfest. Die Sensoren an den beiden Garagentoren sind durch Reedkontakte realisiert, welche mittels an der Torkante befestigten Permanentmagneten geschaltet werden und die Endlage „Tor geschlossen“ detektieren. Der Briefkasten hat einen Deckel zum Einwurf  der Post, den der Zusteller anheben muß, um die Post einzuwerfen. Dabei wird ein nachträglich montierter Mikrotaster betätigt. Da die Nachbau-Gegebenheiten sicher bei jedem potentiellen Nachnutzer anders sind, möchte ich hier keine näheren Ausführungen zum mechanischen Aufbau machen. Nur soviel : Alle Kontakte schalten ihre zugeordnete Signalleitung nach GND. Die Länge der 4-adrigen Leitung beträgt bei mir ca. 6m , es konnte kein Störeinfluß trotz benachbarter 230V~ beobachtet werden. Damit ergab sich folgende Schaltung :



Für den Arduino Uno mit dem zugehörigen aufsteckbaren 2.4“- Touchdisplay wurde ein Sketch geschrieben, der die relevanten Daten auf dem Display darstellt und alle Infos, ohne das Haus verlassen zu müssen, beinhaltet. Für den Briefkasten wurde noch eine Besonderheit vorgesehen : Wenn der Deckel desselben erstmalig geöffnet wird, wird der Zustand gespeichert und der Hinweis „POST DA“ erscheint.  Diesen Hinweis kann man durch Berühren des Touchdisplays zurücksetzen, sinnvollerweise nach Entnahme der Post. Danach ist der Briefkasten wieder „empfangsbereit“. Die hier etwas eigenartig gewählte Beschaltung der Pins des Arduino ( GPIO10, Rx und A5 ) ist der Tatsache geschuldet, daß die meisten  der Digitalpins durch das aufgesteckte Shield bereits genutzt  werden und diese daher nicht mehr frei zugänglich sind. Im Sketch wurden daher die hier verwendeten noch freien Pins benutzt.



Der gesamte Hardware wird über ein gerade vorhandenes USB-5V Netzteil versorgt und verbraucht im Betrieb ca. 0,2 A. Nach Realisierung aller Funktionen und Platzierung des Displays im Hausinneren ist auch der WAF (Wife Acceptance Faktor) merklich gestiegen, da die beste aller Ehefrauen nicht mehr im Dunklen das Haus zur Kontrolle von Garagentoren und Briefkasten verlassen muss ;-)



Günther Zöppel
Pockau, Juni 2026


#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
#include <TouchScreen.h>

MCUFRIEND_kbv tft;

// ==========================================
//  FUNKTIONIERENDE TOUCH-PIN-BELEGUNG
// ==========================================
const int XP = 6; const int XM = A2; const int YP = A1; const int YM = 7;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Standard-Kalibrierungswerte für funktionierende Touch-Pin-Belegung
const int TS_LEFT = 920; const int TS_RT  = 120;
const int TS_TOP  = 900; const int TS_BOT  = 140;

// Farbdefinitionen im 16-Bit RGB565-Format
#define BLACK   0x0000
#define WHITE   0xFFFF
#define GREEN   0x07E0
#define RED     0xF800
#define GREY    0x5AEB
#define YELLOW  0xFFE0

// Pin-Belegung am Arduino Uno
const int pinTor1       = 10;
const int pinTor2       = A5;
const int pinBriefkasten = 0;  // Rx-Pin

// Status-Variablen
int letzterStatusTor1 = -1;
int letzterStatusTor2 = -1;
bool postVorhanden    = false;
bool alterPostStatus  = true;

// Funktions-Prototypen
void drawStaticUI();
void updateTorAnzeige(int torNummer, bool isOpen, int xPos, int yPos);
void updateBriefkastenAnzeige();
bool checkTouchQuittung();

void setup() {
    pinMode(pinTor1, INPUT_PULLUP);
    pinMode(pinTor2, INPUT_PULLUP);
    pinMode(pinBriefkasten, INPUT_PULLUP);

    uint16_t ID = tft.readID();
    tft.begin(ID);
    tft.setRotation(1); // Querformat (320x240 Pixel)
    tft.fillScreen(BLACK);
   
    drawStaticUI();
   
    letzterStatusTor1 = digitalRead(pinTor1);
    letzterStatusTor2 = digitalRead(pinTor2);
    updateTorAnzeige(1, letzterStatusTor1, 15, 75);
    updateTorAnzeige(2, letzterStatusTor2, 120, 75);
    updateBriefkastenAnzeige();
}

void loop() {
    bool statusTor1 = digitalRead(pinTor1);
    bool statusTor2 = digitalRead(pinTor2);
    bool statusKlappe = digitalRead(pinBriefkasten);

    if (statusTor1 != letzterStatusTor1) {
        updateTorAnzeige(1, statusTor1, 15, 75);
        letzterStatusTor1 = statusTor1;
    }
    if (statusTor2 != letzterStatusTor2) {
        updateTorAnzeige(2, statusTor2, 120, 75);
        letzterStatusTor2 = statusTor2;
    }

    if (statusKlappe == LOW && !postVorhanden) {
        postVorhanden = true;
    }

    if (postVorhanden != alterPostStatus) {
        updateBriefkastenAnzeige();
        alterPostStatus = postVorhanden;
    }

    // Präzise Bereichsprüfung beim Tippen
    if (postVorhanden && checkTouchQuittung()) {
        postVorhanden = false;
    }

    delay(50);
}

bool checkTouchQuittung() {
    TSPoint p = ts.getPoint();
   
    // Geteilte Pins zwingend wieder auf Output für das TFT-Shield schalten
    pinMode(XM, OUTPUT);
    pinMode(YP, OUTPUT);
   
    if (p.z > 150 && p.z < 1000) {
        int pixel_x = map(p.x, TS_LEFT, TS_RT, 0, 320);
        int pixel_y = map(p.y, TS_TOP, TS_BOT, 0, 240);
       
        // Bereichsfilter: Untere rechte Ecke
        if (pixel_x > 140 && pixel_y > 140) {
            return true;
        }
    }
    return false;
}

void drawStaticUI() {
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.drawFastVLine(110, 0, 140, GREY);  
    tft.drawFastHLine(0, 140, 320, GREY);  
    tft.setCursor(10, 20);   tft.print("TOR 1");
    tft.setCursor(120, 20);  tft.print("TOR 2");
    tft.setCursor(10, 155);  tft.print("BRIEFKASTEN:");
}

void updateTorAnzeige(int torNummer, bool isOpen, int xPos, int yPos) {
    tft.fillRect(xPos, yPos, 85, 40, BLACK);
    tft.setCursor(xPos, yPos);
    tft.setTextSize(3);
    if (isOpen) { tft.setTextColor(RED); tft.print("OFFEN"); }
    else { tft.setTextColor(GREEN); tft.print("ZU"); }
}

void updateBriefkastenAnzeige() {
    // Bereich säubern (X leicht nach links erweitert für den langen Text)
    tft.fillRect(145, 145, 175, 60, BLACK);
   
    if (postVorhanden) {
        tft.setCursor(165, 155);
        tft.setTextSize(3);
        tft.setTextColor(YELLOW); 
        tft.print("POST DA");
       
        // Quittierungshinweis in WEISS, weiter links platziert
        tft.setTextSize(1);
        tft.setTextColor(WHITE);
        tft.setCursor(145, 195);
        tft.print("[Hier tippen zum Leeren]");
    } else {
        tft.setCursor(165, 155);
        tft.setTextSize(3);
        tft.setTextColor(GREEN);
        tft.print("LEER");
    }
}



Elektronik-Labor  Bastelecke  Projekte  Mikrocontoller