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");
}
}