[Code check] Nano + 2 Taster + DC Motor + 1-Relais

Moin moin zusammen,

ich habe vor ca. einer Woche angefangen mich mit dem Thema Arduino etc. zu beschäftigen, um ein kleines Privatprojekt realisieren zu können.

Ich habe mir mit einem Nano eine Steuerung für folgender Funktionen gebaut:

  • Öffnen/Schliessen einer Klappe über einen DC Motor (Exup) [L293D]
  • Öffnen/Schliessen eines Stromkreislaufes (Scheinwerfer zuschalten) [1-Relais 5V KY-019]
    Für beide Funktionen verwende ich einen simplen Taster und eine Status-LED, welche mir den aktuellen Stand anzeigt. Die Werte (ob offen oder geschlossen) speichere ich im EEPROM, um diese beim erneuten starten wiederherzustellen.

Der Code steht soweit (beruflich habe ich etwas mit JS/PHP etc. zu tun, was mir hierbei sehr geholfen hat) und es scheint auch alles wie gewünscht zu funktionieren. Testaufbau mit allen Komponenten und verschiedenen Testdurchläufen gemacht und bis jetzt alles top! :slight_smile:

Nun würde ich diesen Code gerne von euch checken lassen, ob ich etwas besser schreiben könnte oder ob es potentielle Fehlerquellen gibt.

#include <EEPROM.h>
#include <OneButton.h>

const int shutterButtonPin    =   10;                                             //  Taster für Klappensteuerung
const int shutterLedPin       =   12;                                             //  Status-LED für Klappensteuerung
const int shutterDuration     =   1000;                                           //  Dauer zum öffnen/schliessen der Klappe
const int shutterState        =   0;                                              //  Klappenstatus : [0 ] Geschlossen [1] Offen
const int headlightButtonPin  =   13;                                             //  Taster für Scheinwerfer
const int headlightLedPin     =   2;                                              //  Status-LED für Scheinwerfer
const int headlightState      =   0;                                              //  Scheinwerferstatus : [0 ] Aus [1] An
const int headlightRelaisPin  =   4;                                              //  Relais für Scheinwerfer

#define shutterOpen             6                                                 //  H-Brücke : Klappe öffnen
#define shutterClose            8                                                 //  H-Brücke : Klappe schliessen

OneButton shutterButton(shutterButtonPin, false);                                 //  OneButton : Klappensteuerung
OneButton headlightButton(headlightButtonPin, false);                             //  OneButton : Scheinwerfer

void setup() {

  pinMode(shutterButtonPin, INPUT);
  pinMode(shutterLedPin, OUTPUT);
  pinMode(shutterButtonPin, INPUT);
  pinMode(headlightLedPin, OUTPUT);
  pinMode(headlightRelaisPin, OUTPUT);

  digitalWrite(shutterOpen, LOW);
  digitalWrite(shutterClose, LOW);
  digitalWrite(headlightsToggle, LOW);

  shutterButton.attachClick(closeShutter);                                        //  Regulärer Taster-Druck : Klappe schliessen
  shutterButton.attachDoubleClick(openShutter);                                   //  Doppelter Taster-Druck : Klappe öffnen
  headlightButton.attachClick(headlightsToggle);                                  //  Regulärer Taster-Druck : Scheinwerfer an/aus

  //  Prüfen ob die Statuswerte im EEPROM vorhanden sind
  
  if ( EEPROM.read(shutterState) != 0 || EEPROM.read(shutterState) != 1 ) {       //  Klappensteuerung : Statuswert im EEPROM vorhanden
    
    EEPROM.write(shutterState, 0);                                                //  Klappensteuerung : Standard-Statuswert im EEPROM anlegen

  }
  
  if ( EEPROM.read(headlightState) != 0 || EEPROM.read(headlightState) != 1 ) {   //  Scheinwerfer : Statuswert im EEPROM vorhanden
    
    EEPROM.write(headlightState, 0);                                              //  Scheinwerfer : Standard-Statuswert im EEPROM anlegen

  }

  //  Klappensteuerung

  if ( EEPROM.read(shutterState) == 1 ) {                                         //  Klappe war offen : 1

    digitalWrite(shutterLedPin, HIGH);                                            //  Status-LED aktivieren

  } else {                                                                        //  Klappe war geschlossen : 0

    digitalWrite(shutterLedPin, LOW);                                             //  Status-LED deaktivieren

  }


  //  Scheinwerfer

  if ( EEPROM.read(headlightState) == 1 ) {                                         //  Scheinwerfer waren an : 1

    digitalWrite(headlightLedPin, HIGH);                                            //  Status-LED aktivieren
    digitalWrite(headlightRelaisPin, HIGH);                                         //  Relais einschalten

  } else {                                                                          //  Scheinwerfer waren aus : 0

    digitalWrite(headlightLedPin, LOW);                                             //  Status-LED deaktivieren
    digitalWrite(headlightRelaisPin, LOW);                                          //  Relais ausschalten

  }

}

void loop() {

  shutterButton.tick();
  headlightButton.tick();
  delay(50);

}

//  Klappensteurung : Schliessen

void closeShutter() {                                                             //  1x Betätigung des Tasters zum schliessen

  if ( EEPROM.read(shutterState) == 1 ) {                                         //  Wenn geöffnet -> Schliessen

    EEPROM.write(shutterState, 0);                                                //  EEPROM : Klappenstatus : Geschlossen
    digitalWrite(shutterLedPin, LOW);                                             //  Status-LED deaktivieren

    digitalWrite(shutterOpen, LOW);                                               //  Exup-Eingang 1 : Stop
    digitalWrite(shutterClose, HIGH);                                             //  Exup-Eingang 2: Start
    delay(shutterDuration);                                                       //  Dauer des Exup-Betriebs
    digitalWrite(shutterClose , LOW);                                             //  Exup-Eingang 2 : Stop
    delay(250);

  }

}

//  Klappensteurung : Öffnen

void openShutter() {                                                              //  1x Betätigung des Tasters zum öffnen

  if ( EEPROM.read(shutterState) == 0 ) {                                         //  Wenn geschlossen -> Öffnen

    EEPROM.write(shutterState, 1);                                                //  EEPROM : Klappenstatus : Offen
    digitalWrite(shutterLedPin, HIGH);                                            //  Status-LED aktivieren

    digitalWrite(shutterOpen, HIGH);                                              //  Exup-Eingang 1 : Start
    digitalWrite(shutterClose, LOW);                                              //  Exup-Eingang 2 : Stop
    delay(shutterDuration);                                                       //  Dauer des Exup-Betriebs
    digitalWrite(shutterOpen, LOW);                                               //  Exup-Eingang 1 : Stop
    delay(250);

  }

}

//  Scheinwerfer : Einschalten / Ausschalten

void headlightsToggle() {                                                         //  Betätigung des Tasters für an/aus

  if ( EEPROM.read(headlightState) == 1 ) {                                       //  Wenn an -> Ausschalten

    EEPROM.write(headlightState, 0);                                              //  EEPROM : Scheinwerfer : Aus
    digitalWrite(headlightLedPin, LOW);                                           //  Status-LED deaktivieren
    digitalWrite(headlightRelaisPin, LOW);                                        //  Ralais : Aus
    delay(250);

  } else {                                                                        //  Wenn aus -> Einschalten

    EEPROM.write(headlightState, 1);                                              //  EEPROM : Scheinwerfer : Ein
    digitalWrite(headlightLedPin, HIGH);                                          //  Status-LED aktivieren
    digitalWrite(headlightRelaisPin, HIGH);                                       //  Ralais : An
    delay(250);

  }

}

Ich hoffe, es ist alles verständlich und freue mich auf Feedback!

Gruß, YF88

Du weißt, das der EEPROM nur 100.000 garantierte Schreibzyklen hat?
Kalkuliere mal, aller welcher Zeit Du da rein schreibst und wie lange der damit garantiert halten wird.

Gruß Tommy

Tommy56:
Du weißt, das der EEPROM nur 100.000 garantierte Schreibzyklen hat?
Kalkuliere mal, aller welcher Zeit Du da rein schreibst und wie lange der damit garantiert halten wird.

Damn, ich glaube da habe ich dann irgendwas verpeilt... :confused: :sweat_smile:

Gibt es dafür noch eine andere bzw. vernünftige Methode?

[Edit] Habe diesen Beitrag gefunden: EEPROM und wie man die Lebensdauer erhöhen kann - Deutsch - Arduino Forum

Bin schon fleissig am lesen, aber trotzdem natürlich für Hilfe und Tipps offen!

Es wäre möglich einen FRAM an I2C oder SPI zu nutzen. Der behält auch die Daten nach dem Ausschalten und hat einige Größenordnungen mehr an Schreibzyklen.

Gruß Tommy

Hi

Naja - da die Klappe vohl nicht im Sekundentakt geöffnet und geschlossen wird und man eh nur bei Änderung im EEprom speichern muß (ohne Änderung steht DAS ja schon da drin) - also diese Zeit x 100.000 -> wird wohl schon eine Woche oder Zwei durchhalten.
FRam ist aber trotzdem ein ziemlich geiles Thema - gibt die FRam in DIP, allerdings fand ich in dieser Bauform nur 512 Byte (4kb = kilo-Bit) - wäre hier aber ebenfalls dicke ausreichend.

const int shutterState = 0; // Klappenstatus : [0 ] Geschlossen [1] Offen

... aaaaahhhh ... DAS soll die Position im EEprom sein, wo der Kram notiert wird ... wieder was gelernt ... ok, dann const (hätte den Kandidaten aber dann etwas anders benannt)

Hier sehe ich Probleme - durch das const ist Das ein FESTWERT - Da ist Nichts mehr mit Ändern!!
Dann - spätestens, wenn der Wert veränderbar sein soll - Datentypen!!
bool 0/1/true/false/HIGH/LOW
byte/uint8_t 0...255
char/int8_t -127...128
... man muß nicht immer INT nehmen (was auf den kleinen Arduino 16 Bit Breite hat, auf den Großen sogar 32).

Auf den ersten Blick - zu viele Leerzeilen in dem Sketch - bitte auf das Notwendigste reduzieren!

Und Kommentare sind recht spärlich - hier noch nicht wirklich notwendig, aber gewöhne Dir an, bei zuschreiben, WARUM die Zeile Das macht, was Sie macht.
Nicht, WAS Sie macht - Das sehen wir schon :wink:

MfG

@postmaster-ino: Die SMD-Versionen kann man anstelle des EEPROM auf das DS3231-Modul auflöten und es gibt "smd to dil" Adapterplatinen

Gruß Tommy

Hi

Ja, Das schon - aber bei Beiden muß man den SMD-Zwerg löten.
Auch, wenn hier glaub noch 1,27mm Pin-Abstand sind - zumindest ich habe hier meine liebe Not.
DIP ist mir hier um Welten lieber ... wenn nur nicht der exorbitant größere Platz in den Käfern stecken würde :wink:

MfG

Edit
Zweg -> Zwerg

Ja, 1,27 mm. Das lötet sich mit gutem Werkzeug unter einer großen Lupe mit Beleuchtung selbst für einen Maulwurf, wie mich, noch problemlos.

SMD-Bahnen verzinnen, Pins verzinnen, Flussmittel drauf und erst mal die Ecken verlöten, dann den Rest.

Gruß Tommy

bei int immer prüfen ob es 2byte signed sein muss oder ob ein byte/bool reicht, oder vieleicht ein unsinged besser wäre.

const int shutterButtonPin    =   10;                                             //  Taster für Klappensteuerung
const int shutterLedPin       =   12;                                             //  Status-LED für Klappensteuerung
const int shutterDuration     =   1000;                                           //  Dauer zum öffnen/schliessen der Klappe
const int shutterState        =   0;                                              //  Klappenstatus : [0 ] Geschlossen [1] Offen
const int headlightButtonPin  =   13;                                             //  Taster für Scheinwerfer
const int headlightLedPin     =   2;                                              //  Status-LED für Scheinwerfer
const int headlightState      =   0;                                              //  Scheinwerferstatus : [0 ] Aus [1] An
const int headlightRelaisPin  =   4;                                              //  Relais für Scheinwerfer

in deinem Fall wird der Compiler das meiste zwar wegoptimieren, aber gewöhn dir das von Anfang an sauber an.

camelCase gefällt mir,
Leerzeilen sind zu viele.
Kommentare brauch ich nicht noch mehr. wenn dann richtige.

wenn das

const int shutterState = 0; // Klappenstatus : [0 ] Geschlossen [1] const int headlightState = 0; // Scheinwerferstatus : [0 ] Aus [1] An

EEprom-Adressen sind ... schauts aus als würdest du dir diese Zelle gegenseitig überschreiben.

Eigentlich machen wir da heute ein struct für die EPROM Daten und arbeiten dann mit offsetof.

statt EEPROM.write/read würde ich put und get empfehlen

die precompiler defines, könntest unter c++ auch eher als const variablen machen

#define shutterOpen             6                                                 //  H-Brücke : Klappe öffnen
#define shutterClose            8                                                 //  H-Brücke : Klappe schliessen

hinter dem Onebutton Include noch ein Wort was das ist und wo du es her hast
dann noch ein Kommentar-Block am Anfang was das Ding macht, wer es geschrieben hat und ein Datum.

sonst aber für eine Woche, schon brav gemacht.
Schulterklopf

Schon einmal danke für das ganze Feedback und die Tipps! :slight_smile:

Bezüglich des Speicherns wäre mein Ziel eine Wartungslose Variante!
Da ich das ganze ohne Breadboard mache und am Ende alles in eine kleine Dose kommen soll, möchte ich mir auch keine Sorgen machen müssen, dass plötzlich nicht mehr gespeichert werden kann oder Fehlerhafte Schaltungen entstehen.
Es wird vermutlich nicht oft geschaltet bzw. in der Regel bleibt beides eigentlich immer auf "1", aber trotzdem möchte ich auf Nummer sicher gehen und es vernünftig machen.

Was wäre denn in meinem Fall die beste Lösung zum Speichern vom Status der Funktionen? (wenn möglich ohne Wartung)

Löten bin ich auch Anfänger, habe lediglich einen günstigen Kolben und war schon stolz wie Bolle, dass ich die ganzen Pins am Arduino hinbekommen habe :smiley:

Zu den oft genannten Leerzeilen: Das kommt aus meinem Beruf, wo ich täglich u. a. mit SCSS/JS etc. zu tun habe und da mache ich dies zur besseren Übersicht. Beim Speichern löscht mir ein Compiler u. a. die Leerzeilen raus, weshalb ich mir da keinen Gedanken darüber machen muss. Werde das hierbei natürlich noch einmal anpassen :wink:

Bei Kommentaren war ich schon immer ein wenig faul, werde aber in Zukunft versuchen, diese deutlicher zu schreiben.

Die variablen Versuche ich auch noch einmal zu optimieren und werde mich über bool, byte, char etc. schlaumachen.

EEPROM.put/get habe ich tatsächlich schon versucht, aber irgendwie bekam ich sofort Fehler und war irgendwann genervt davon^^
Das nehme ich dann auch noch mal in Angriff!

Gruß, YF88

Wenn Du wenig löten willst, musst Du halt fertige Module nehmen (z.B. das oder das)

Gruß Tommy

Tommy56:
Wenn Du wenig löten willst, musst Du halt fertige Module nehmen (z.B. das oder das)

Gruß Tommy

Mit "normalen" Löten habe ich nicht wirklich ein Problem, nur wenn ich da was mit "um die Ecke löten" lese, bin ich komplett raus :smiley:

Auch wenn ich Sachen wie I2C oder SPI google, bin ich dezent überfordert :sweat_smile:

Aus Platzgründen, würde ich nur den kleinen FRAM Chip nehmen un direkt an die Beinchen gehen.
Spricht da etwas gegen?

Und wo kann man sowas günstig und schnell bekommen?
Werde gerade irgendwie nicht wirklich fündig...

Auch da musst Du den mit I2C oder SPI (je nachdem, welchen Chip Du kaufst) ansteuern. Du dast halt noch das Löten im 1,27 mm Abstand dazu und mit Draht direkt an die Beine gehen würde ich Dir nicht empfehlen. Außerdem muss da zumindest noch ein 100 nF C ran und Du musst aufpassen, dass Du Typen für 5V kaufst, wenn Du einen 5V Arduino benutzt.

So einfach wie Du Dir das vorstellst ist es mit Sicherheit nicht.

Gruß Tommy

Ich merke es schon...

So langsam kommt auch Frust auf, da ich ja eigentlich keine Welten bewegen möchte und es an etwas eher simplen scheitert... :confused:

[edit] Code entfernt, da ich dabei vorhin komplett neben mir gestanden haben muss^^

Dann solltest Du Dich wohl wohl mal über die EEPROM-Methoden kundig machen.

Irgendwie habe ich den Eindruck, Du springst munter von einem Thema zum anderen, ohne davon wirklich etwas zu begreifen, in der Hoffnung, dass es zufällig funktionieren könnte. Die Wahrscheinlichkeit dafür ist sehr gering.

Gruß Tommy

Das ich in der kurzen Zeit nicht alles sofort oder zu 100% begreife, steht natürlich nicht zur Debatte.

Ich lese/teste viel und habe so ja auch recht zügig das umsetzen können, was ich mir vorgenommen hatte.
Zu mindestens der Grundaufbau bzw. die reine Funktionalität läuft ja bereits so, wie ich es mir Grunde vorgestellt habe.

Naja, ich ziehe mir das EEPROM Zeugs erneut rein, evtl. checke ich es dann ja mal...

Das lernen/verstehen können wir Dir nicht abnehmen.
Wir können nur bei konkreten Fragen versuchen, mit Erklärungen zu helfen.

Grß Tommy

Tommy56:
Das lernen/verstehen können wir Dir nicht abnehmen.

Habe ich auch nicht erwartet :wink:

So, nun habe ich weitere Erkenntnisse und vermutlich auch einen großen Denkfehler gelöst :smiley:

Ein paar Punkte:

  • EEPROM.put benutzen, da dies gleichzeitig auch EEPROM.update nutz und somit nur im Fall einer Veränderung wirklich Daten schreibt
  • EEPROM.read ist okay, da ich lediglich 1 oder 0 speichere
  • Fehler in den EEPROM Adressen korrigiert (komisch das es vorher trotzdem funktionierte^^)
  • Die Variablen kann ich alle mit const int schreiben, da diese nicht verändert werden

Zum finalen Verständnis möchte ich noch einmal folgendes aufgreifen:

Tommy56:
Du weißt, das der EEPROM nur 100.000 garantierte Schreibzyklen hat?

Jedes mal wenn ein Wert geschrieben/verändert wird, geht somit ein Schreibzyklus verloren.

Da bei mir im Normalfall beide Funktionen auf einem Wert stehen und nur im seltensten Notfall verändert werden, sollte ich damit keinerlei Probleme bekommen. (Vermutlich maximal 20 Änderungen im Jahr)

Sehe ich das richtig?

Anbei einfach noch mal der aktualisierte Code:

/*
  Klappen- & Scheinwerfersteuerung über einen Arduino Nano
  – Taster zum öffnen und schliessen einer Klappe über einen DC Motor mit L293D
  – Taster zum zuschalten eines Scheinwerfers über einen externen Stromkreis mit Relais 5V KY-019
  – Status beider Funktionen wird jeweils über eine LED dargestellt
  – Status beider Funktionen wird gespeichert, um den letzten Zustand bei Neustart wiederherzustellen
  YF88 | 05.03.2020
*/

#include <EEPROM.h>
#include <OneButton.h>                                                                  //  Mehrfachverwendung eines Tasters : https://github.com/mathertel/OneButton

const int shutterButtonPin    =   10;                                                   //  Taster für Klappensteuerung
const int shutterLedPin       =   12;                                                   //  Status-LED für Klappensteuerung
const int shutterDuration     =   1000;                                                 //  Dauer zum öffnen/schliessen der Klappe
const int headlightButtonPin  =   13;                                                   //  Taster für Scheinwerfersteuerung
const int headlightLedPin     =   2;                                                    //  Status-LED für Scheinwerfersteuerung
const int headlightRelaisPin  =   4;                                                    //  Relais für Scheinwerfersteuerung
const int shutterOpen         =   6;                                                    //  Pin der H-Brücke : Klappe öffnen
const int shutterClose        =   8;                                                    //  Pin der H-Brücke : Klappe schliessen
const int shutterState        =   0;                                                    //  Adresse im EEPROM für Klappenstatus
const int headlightState      =   1;                                                    //  Adresse im EEPROM für Scheinwerferstatus

OneButton shutterButton(shutterButtonPin, false);                                       //  OneButton-Funktion für Klappensteuerung
OneButton headlightButton(headlightButtonPin, false);                                   //  OneButton-Funtionn für Scheinwerfersteuerung

void setup() {

  Serial.begin(9600);
  Serial.println("==================================================");

  pinMode(shutterButtonPin, INPUT);
  pinMode(shutterLedPin, OUTPUT);
  pinMode(shutterButtonPin, INPUT);
  pinMode(headlightLedPin, OUTPUT);
  pinMode(headlightRelaisPin, OUTPUT);

  digitalWrite(shutterOpen, LOW);
  digitalWrite(shutterClose, LOW);
  digitalWrite(headlightsToggle, LOW);

  shutterButton.attachClick(closeShutter);                                              //  Regulärer Taster-Druck : Klappe schliessen
  shutterButton.attachDoubleClick(openShutter);                                         //  Doppelter Taster-Druck : Klappe öffnen
  headlightButton.attachClick(headlightsToggle);                                        //  Regulärer Taster-Druck : Scheinwerfer an/aus

  //  Prüfen ob die Statuswerte vorhanden sind und wenn nicht: Standartwerte anlegen
  
  if ( EEPROM.read(shutterState) == 0 || EEPROM.read(shutterState) == 1 ) {
    Serial.print("[ Check ] shutterState : Wert ist vorhanden : ");
    Serial.println(EEPROM.read(shutterState));
  } else {
    Serial.println("[ Check ] shutterState : Kein Wert vorhanden");
    EEPROM.put(shutterState, 0);
    Serial.print("[ Check ] shutterState : Standardwert wurde angelegt : ");
    Serial.println(EEPROM.read(shutterState));
  }
  
  if ( EEPROM.read(headlightState) == 0 || EEPROM.read(headlightState) == 1 ) {
    Serial.print("[ Check ] headlightState : Wert ist vorhanden : ");
    Serial.println(EEPROM.read(headlightState));
  } else {
    Serial.println("[ Check ] headlightState : Kein Wert vorhanden");
    EEPROM.put(headlightState, 0);
    Serial.print("[ Check ] headlightState : Standardwert wurde angelegt : ");
    Serial.println(EEPROM.read(headlightState));
  }

  //  Statuswerte auslesen und letzten Zustand wiederherstellen

  if ( EEPROM.read(shutterState) == 1 ) {
    Serial.print("[ Status ] Klappe ist offen : ");
    Serial.println(EEPROM.read(shutterState));
    digitalWrite(shutterLedPin, HIGH);
  } else {
    Serial.print("[ Status ] Klappe ist geschlossen : ");
    Serial.println(EEPROM.read(shutterState));
    digitalWrite(shutterLedPin, LOW);
  }

  if ( EEPROM.read(headlightState) == 1 ) {
    Serial.print("[ Status ] Licht ist an : ");
    Serial.println(EEPROM.read(headlightState));
    digitalWrite(headlightLedPin, HIGH);
    digitalWrite(headlightRelaisPin, HIGH);
  } else {
    Serial.print("[ Status ] Licht ist aus : ");
    Serial.println(EEPROM.read(headlightState));
    digitalWrite(headlightLedPin, LOW);
    digitalWrite(headlightRelaisPin, LOW);
  }

}

void loop() {
  shutterButton.tick();
  headlightButton.tick();
  delay(50);
}

//  1. Funktion der Klappensteurung : Schliessen wenn Klappe geöffnet ist

void closeShutter() {
  if ( EEPROM.read(shutterState) == 1 ) {
    EEPROM.put(shutterState, 0);
    Serial.print("[ Changed ] Klappe wurde geschlossen : ");
    Serial.println(EEPROM.read(shutterState));
    digitalWrite(shutterLedPin, LOW);
    digitalWrite(shutterOpen, LOW);
    digitalWrite(shutterClose, HIGH);
    delay(shutterDuration);
    digitalWrite(shutterClose , LOW);
    delay(250);
  } else {
    Serial.print("[ Locked ] Klappe ist bereits geschlossen : ");
    Serial.println(EEPROM.read(shutterState));
  }
}

//  2. Funktion der Klappensteurung : Öffnen wenn klappe geschlossen ist

void openShutter() {
  if ( EEPROM.read(shutterState) == 0 ) {
    EEPROM.put(shutterState, 1);
    Serial.print("[ Changed ] Klappe wurde geöffnet : ");
    Serial.println(EEPROM.read(shutterState));
    digitalWrite(shutterLedPin, HIGH);
    digitalWrite(shutterOpen, HIGH);
    digitalWrite(shutterClose, LOW);
    delay(shutterDuration);
    digitalWrite(shutterOpen, LOW);
    delay(250);
  } else {
    Serial.print("[ Locked ] Klappe ist bereits offen : ");
    Serial.println(EEPROM.read(shutterState));
  }
}

//  Funktion der Scheinwerfersteuerung : Einschalten falls aus / Ausschalten falls an

void headlightsToggle() {
  if ( EEPROM.read(headlightState) == 1 ) {
    EEPROM.put(headlightState, 0);
    Serial.print("[ Changed ] Licht wurde ausgeschaltet : ");
    Serial.println(EEPROM.read(headlightState));
    digitalWrite(headlightLedPin, LOW);
    digitalWrite(headlightRelaisPin, LOW);
    delay(250);
  } else {
    EEPROM.put(headlightState, 1);
    Serial.print("[ Changed ] Licht wurde eingeschaltet : ");
    Serial.println(EEPROM.read(headlightState));
    digitalWrite(headlightLedPin, HIGH);
    digitalWrite(headlightRelaisPin, HIGH);
    delay(250);
  }
}

Sollte man die Serial.print's am Ende eigentlich löschen oder sind die egal?

Gruß, YF88

die Serial.print stören nicht, aber du solltest dir angewöhnen, das F-Makro (ganz unten beschrieben) nutzen.