Automatisches Garagen-Schiebetor mit Arduino Nano
Komponenten und Zubehör
| Komponente | Menge |
|---|---|
| Arduino Nano R3 | 1 |
| OLED-Display 0,96″ 128×64 (SPI) | 1 |
| 4-Kanal-Relais-Modul (3 genutzt) | 1 |
| 5 V Netzteil (230 V → 5 V) | 1 |
| Taster 12 mm (Reset) | 1 |
| Steckbrett & Kabel | 1 |
Hintergrund
Nach einem Kurzschluss durch eine Eidechse im originalen Steuergerät wurde die Steuerung komplett neu entwickelt. Der Arduino Nano übernimmt die Motorsteuerung (Öffnen/Schließen), Lichtsignalisierung, Auswertung von Endschaltern (Tor offen/zu), Lichtschranke (Sicherheit) und Funkempfänger für Fernbedienung.
Warnung
Arbeit an 230 V! Nur für erfahrene Bastler. Vor Inbetriebnahme Simulation durchführen.
Pinbelegung (Auszug)
- Fotocelda (Lichtschranke): Pin 2
- Bombeta (Signallampe): Pin 5 (Relais 1)
- Tancat (Endschalter zu): Pin 7
- Obert (Endschalter auf): Pin 3
- Motor_Obrir (Motor auf): Pin 6 (Relais 2)
- Motor_Tancar (Motor zu): Pin 12 (Relais 3)
- Obrir (Funkempfänger „Öffnen“): Pin 4
- OLED (SPI): MOSI 11, CLK 13, DC 9, CS 10, Reset 8
Funktionslogik (Zustandsautomat)
Der Code nutzt goto-Labels für klare Phasen:
- BUCLE_PRINCIPAL: Wartet auf Öffnen-Befehl, zeigt Sensorstatus auf OLED.
- SEQUENCIA_OBERTURA: Tor öffnen (max. 28 s), Licht blinkt langsam. Bei Abbruch (Taste) → Schließsequenz.
- PORTA_OBERTA: Tor offen, 30 s Wartezeit, spezielles Blinkmuster.
- SEQUENCIA_TANCAMENT: Tor schließen (max. 28 s), Licht blinkt schnell. Lichtschranke unterbricht → sofortiges Wiederöffnen. Endschalter erreicht → Hauptloop.
Fehlererkennung: Überschreitung der maximalen Laufzeit setzt AVARIA-Flag, Lampe blinkt 60 s lang im Hauptloop.
Code (Auszug, englische Kommentare)
/*********************************************************************
* Automatism for sliding motorized door – Arduino Nano
*********************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Pin-Definitionen …
#define OLED_MOSI 11
#define OLED_CLK 13
#define OLED_DC 9
#define OLED_CS 10
#define OLED_RESET 8
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
unsigned long TEMPS_PORTA_OBERTA = 20000;
unsigned long TEMPS_MAXIM_RECORREGUT = 15000;
int interval = 1000;
int TEMPS_DISPLAY = 1;
int DURADA = 300;
unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
unsigned long TEMPS_LLUM = 1000;
boolean LLUM = false;
boolean AVARIA = false;
void setup() {
pinMode(FOTOCELULA, INPUT_PULLUP);
pinMode(TANCAT, INPUT_PULLUP);
pinMode(OBERT, INPUT_PULLUP);
pinMode(OBRIR, INPUT_PULLUP);
pinMode(BOMBETA, OUTPUT);
pinMode(MOTOR_OBRIR, OUTPUT);
pinMode(MOTOR_TANCAR, OUTPUT);
digitalWrite(MOTOR_OBRIR, HIGH); // Relais aus (active low)
digitalWrite(MOTOR_TANCAR, HIGH);
digitalWrite(BOMBETA, HIGH);
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC);
display.display(); delay(1000);
display.clearDisplay();
display.setTextSize(1); display.setTextColor(WHITE);
}
void loop() {
BUCLE_PRINCIPAL:
delay(2000);
previousMillis = millis();
while (digitalRead(OBRIR) == HIGH) {
// OLED anzeigen: Sensorstatus, AVARIA-Blinken
if (AVARIA && (millis() - previousMillis < 60000)) digitalWrite(BOMBETA, LOW);
else digitalWrite(BOMBETA, HIGH);
}
goto SEQUENCIA_OBERTURA;
SEQUENCIA_OBERTURA:
interval = 28000;
previousMillis = millis();
digitalWrite(MOTOR_OBRIR, LOW); digitalWrite(BOMBETA, LOW);
delay(1000);
A:
if (digitalRead(OBERT) == HIGH) goto PORTA_OBERTA;
if (digitalRead(OBRIR) == LOW) { /* Abbruch → Schließen */ goto SEQUENCIA_TANCAMENT; }
// Zeit & OLED aktualisieren
currentMillis = millis();
TEMPS_DISPLAY = (currentMillis - previousMillis) / 1000;
// … OLED Ausgabe …
if ((currentMillis - previousMillis) >= interval) { digitalWrite(MOTOR_OBRIR, HIGH); AVARIA = true; }
// Lampe blinken (1 Hz)
if ((currentMillis - TEMPS_LLUM) >= 1000) { LLUM = !LLUM; digitalWrite(BOMBETA, LLUM); TEMPS_LLUM = currentMillis; }
goto A;
SEQUENCIA_TANCAMENT:
interval = 28000;
previousMillis = millis();
digitalWrite(MOTOR_TANCAR, LOW); digitalWrite(BOMBETA, LOW);
if (digitalRead(TANCAT) == LOW) delay(1000);
B:
if (digitalRead(TANCAT) == HIGH) { digitalWrite(MOTOR_TANCAR, HIGH); digitalWrite(BOMBETA, HIGH); goto BUCLE_PRINCIPAL; }
if (digitalRead(OBRIR) == LOW) { /* Abbruch → Öffnen */ goto SEQUENCIA_OBERTURA; }
if (digitalRead(FOTOCELULA) == HIGH) { digitalWrite(MOTOR_TANCAR, HIGH); delay(1000); goto SEQUENCIA_OBERTURA; }
// Zeit, OLED, schnelles Blinken (300 ms)
// …
goto B;
PORTA_OBERTA:
interval = 30000;
previousMillis = millis();
digitalWrite(MOTOR_OBRIR, HIGH); delay(500);
C:
if (digitalRead(OBRIR) == LOW) goto SEQUENCIA_TANCAMENT;
// Zeit, OLED, spezielles Blinken (kurz/lang)
// …
goto C;
}
Der vollständige Code enthält auch die katalanische Originalversion. Die Logik ist robust, nutzt aber goto – für komplexere Projekte empfiehlt sich eine strukturierte Zustandsmaschine mit switch.
Schaltpläne
Fritzing-Schematics und Pinout-Übersicht sind im Projekt enthalten. Ein Hardware-Addon für alternative Verdrahtung wird ebenfalls gezeigt.
Herstellungsprozess
- Kompakter DHT Temperatur- & Feuchtigkeits-Breakout für Raspberry Pi – ATtiny85 & DHT22/DHT11
- Top-Zubehör, um das volle Potenzial Ihres Raspberry Pi auszuschöpfen
- SIGHT: Smarte Brille für Blinde – Raspberry Pi & TensorFlow
- Unterwasserdrohne mit Raspberry Pi bauen: Design, Entwicklung und Montage
- Präzisions-Schlittenstock-Automation für Schweizer & Produktionsdreherei
- Wachstumstreiber Automatisierung: Wie KMU die Zukunft gestalten
- Ein herzliches Abschiednehmen: Meine 40-jährige Reise im Verlagswesen
- So wählen Sie hochwertige Stoßdämpfer für Ihr Fahrzeug aus
- Handbandsäge: Langlebige, tragbare Schneidlösung für jedes Projekt
- Automatische Exzenterpressen (Power Press): Funktionsweise, Merkmale & Anwendungen im Blechumformen