DIY Schließ- und Alarmanlage – 3/4 Programmieren

Nachdem wir im ersten Teil alle benötigten Geräte zusammengesammelt und im zweiten Teil alles angeschlossen haben, kommen wir nun endlich zur Programmierung des Systems. In diesem Teil bringen wir dir die Grundlagen der Programmierung bei und zeigen, wie man die Programme / Sketches auf den Arduino überspielt.

Die Programmiersprache

Die Programmiersprache des Arduinos ist C++. Sie ist schnell zu erlernen und einmal grob verstanden kann man die kompliziertesten Programme mit simplen Codezeilen schreiben. Auf der Arduino Seite wird die Sprache einfach und verständlich mit Beispielen erklärt.

Sketch auf den Arduino laden

Um die Codezeilen auf den Arduino zu laden, benötigst du lediglich ein USB-Kabel und das Arduino eigene Programm. Hier kannst du den Code schreiben, Fehler beheben, ihn kompilieren und auf den Arduino laden. Zum Einstieg empfehlen wir die Beispielbibliothek etwas zu durchstöbern, um mit der Programmiersprache mit einfachen kleinen Programmen vertrauter zu werden.

Ein Sketch auf den Arduino zu laden ist glücklicherweise kein Hexenwerk, sondern recht simpel gestrickt. Schließ den Arduino mit dem Kabel an den Computer an, öffne die Arduino Software, mit der du den Code auch geschrieben hast und klicke oben links auf den Hochladen-Pfeil.

Automatisch wird der geschriebene Code auf Fehler und Korrektheit überprüft, das gesamte Sketchfile wird für den Arduino vorbereitet (kompiliert) und anschließend auf den Arduino geladen. Sollten Fehler bei der Übertragung oder im Code auftreten, werden diese unterhalb des Code-Fensters aufgelistet und ggf. auch bereits mit einer Problemlösung bestückt.

Struktur eines Sketches

Zuallererst werden im setup die Pinmodi, Bibliotheken, erste Variablen usw. initialisiert. Alles, was hier steht, wird beim Starten des Arduino und bei einem Reset einmal aufgerufen.

Das loop ist – wie der Name schon verrät – eine Dauerschleife des Codes. Hier werden Befehle ausgeführt, Variablen überschrieben und verändert, Eingänge ausgelesen und Ausgänge gesteuert. Wenn das Programm am Ende angekommen ist, beginnt es wieder von vorne und dass endlos lang.

void setup()
{
  //Hier werden die Pins verteilt und erste Variablen erstellt. 
}
void loop()
{
  //Hier steht der ganze Code der ausgeführt wird drin.
}

PinModi und erste Variablen

Zu Beginn des Sketches definieren wir sämtliche Variablen, die wir im Sketch benötigen. Es gibt unterschiedliche Variablen-Typen, für unterschiedliche Anwendungsgebiete. Wir nutzen dabei am meisten word für Textinhalte, int (Integer) für Zahlen, long int für längere Zahlen und bool für ein einfaches Ja (TRUE) und Nein (FALSE). Die Variablennamen sind frei wählbar, dürfen aber nur aus einem Wort bestehen und keine Zahlen und Umlaute beinhalten.

Da keiner bei den vielen Pinnummern durchblickt, empfehlen wir die Nummern durch Namen vorab zu definieren. Mit dem Befehl #define kann die Pinnummer mit einem Wort verknüpft werden, das fortan anstelle der Nummer verwendet werden kann.

Kommen wir zum setup, in dem wir die PinModes den Pins zuweisen. Zur Mode Auswahl steht für Ausgänge OUTPUT und für die Eingänge INPUT oder INPUT_PULLUP zur Auswahl. Auf der Arduino-Seite findest du eine ausführliche Beschreibung der Modi.

//DEFINE VARIABLES
word ledcolor = "white";
int redValue; int greenValue; int blueValue;
long int lockcount;
bool outdoorlight;

//DEFINE PINS
#define OUTDOORTASTER 5
#define OUTDOORLIGHT 6

void setup()
{
  pinMode(OUTDOORTASTER, INPUT_PULLUP);
  pinMode(OUTDOORLIGHT, OUTPUT);
}
...

Pins schreiben und auslesen

Mit den Befehlen digitalRead(), digitalWrite(), analogRead() und analogWrite() können die digitalen und analogen Pins gelesen und geschrieben werden. In unserem Beispiel wird die bool Variable outdoorlight erstellt und anschließend mit dem aktuellen Wert vom Pin OUTDOORTASTER beschrieben. Danach wird der Pin OUTDOORLIGHT auf HIGH (+5V) gesetzt und das Sketch beginnt wieder von vorne.

//DEFINE VARIABLES
bool outdoorlight;

//DEFINE PINS
#define OUTDOORTASTER 5
#define OUTDOORLIGHT 6

void setup()
{
  pinMode(OUTDOORTASTER, INPUT_PULLUP);
  pinMode(OUTDOORLIGHT, OUTPUT);
}

void loop()
{
  outdoorlight = digitalRead(OUTDOORTASTER);

  digitalWrite(OUTDOORLIGHT, HIGH);
}

IF – ELSE Abfragen

Mit einer if-Abfrage wird eine Bedingung abgefragt. Wenn die Bedingung erfüllt (TRUE) ist, wird der umklammerte Code ausgeführt. Anderenfalls wird der Teil übersprungen. Bei einer IF-ELSE Abfrage wird bei nichterfüllten der Bedingung der ELSE Code ausgeführt.

In unserem Beispiel wird abgefragt, ob der Taster an Pin OUTDOORTASTER gedrückt (also HIGH) ist und schaltet dann den Pin OUTDOORLIGHT (also das Relais zum Außenlicht) auf HIGH, also an. Wenn der Taster nicht gedrückt ist, also ein LOW am Pin OUTDOORTASTER gelesen wird, schaltet der Arduino den Pin OUTDOORLIGHT auf LOW.

//DEFINE VARIABLES
bool outdoorlight;

//DEFINE PINS
#define OUTDOORTASTER 5
#define OUTDOORLIGHT 6

void setup()
{
  pinMode(OUTDOORTASTER, INPUT_PULLUP);
  pinMode(OUTDOORLIGHT, OUTPUT);
}

void loop()
{
  outdoorlight = digitalRead(OUTDOORTASTER);

  if (outdoorlight == HIGH)
  { digitalWrite(OUTDOORLIGHT, HIGH); }
  else
  { digitalWrite(OUTDOORLIGHT, LOW); }
}

Klicken und Speichern

Okay, jetzt kommt viel Neues, aber auf der Basis und dem Wissensstand haben wir so ziemlich das ganze System aufgebaut. Bisher geht die Außenbeleuchtung beim Loslassen des Tasters immer wieder aus und leuchtet nur, wenn der Taster gedrückt ist. Wir müssen also den Code so verändern, dass der Wert auch gespeichert wird und die Lampe erst wieder aus geht, wenn wir den Taster erneut drücken.

Um die teils komplexen Codezeilen schnell zu verstehen, schreiben wir uns kurze Überschriften als Kommentar dazu. So bekommen wir einen Einblick, wo wir sind und was der Codeblock macht.

In diesem Beispiel wird die Variable outdoorlight als Resultat für die Relais genommen. Eine weitere Variable outdoorlighttasterbefore wird benutzt, um den vorherigen Wert des Tasters zu speichern. Die if-Abfrage vergleicht ständig den aktuellen Wert des Tasters mit dem gespeicherten. Wenn der Wert sich ändert, also der Taster gedrückt oder losgelassen wird, wird der Code in der Abfrage ausgeführt.

Ein Mikrocontroller ist so schnell, dass er beim Drücken des Tasters, diesen bereits erfasst hat, noch bevor der Taster vollkommen gedrückt ist. Manchmal entsteht dabei ein Flimmern, wenn der Taster halb gedrückt ist und das System so ein loslassen und erneutes drücken erkennt. Um dieses Tasterflimmern zu verhindern, haben wir eine kleine Pause von 10 ms eingesetzt, bevor die zweite if-Abfrage ausgeführt wird.

Jetzt wo der Taster gedrückt ist und die kurze Pause abgelaufen ist, wird die aktuelle Schalterstellung des Tasters abgefragt. Ist der Taster gedrückt (also HIGH), wird der Wert der Variable outdoorlight mit dem umgekehrten Wert (!) gefüllt. Anschließend wird der neue Wert des Tasters in der Variable outdoorlighttasterbefore gespeichert. Wenn der Taster losgelassen wird, wird das Script in der ersten if-Abfrage erneut ausgeführt, wobei lediglich der neue Tasterwert gespeichert wird und das Licht nicht wieder abgeschaltet wird.

Am Endes des Codes haben wir, mit einer kleinen if-Abfrage das Relais auf Basis der Variable outdoorlight geschrieben. Die Relais sind komischerweise bei LOW ein- und bei HIGH ausgeschaltet. Etwas verwirrend – I know.

//DEFINE VARIABLES
bool outdoorlight;
bool outdoorlighttasterbefore;

//DEFINE PINS
#define OUTDOORTASTER 5
#define OUTDOORLIGHT 6

void setup()
{
  pinMode(OUTDOORTASTER, INPUT_PULLUP);
  pinMode(OUTDOORLIGHT, OUTPUT);
}

void loop()
{
  //Toggle AußenlichtRelay-Value (outdoorlight) on Button-Push
  if (digitalRead(OUTDOORTASTER) != outdoorlighttasterbefore)
  {
    delay(10);
    if (digitalRead(OUTDOORTASTER) == HIGH)
    {
      outdoorlight = !outdoorlight;
    }
    outdoorlighttasterbefore = digitalRead(OUTDOORTASTER);
  }

  //Write Outdoorlight Relay
  if (outdoorlight == true) {digitalWrite(OUTDOORLIGHT, LOW);}
  else {digitalWrite(OUTDOORLIGHT, HIGH);}
}

Ein Eingang schaltet mehrere Ausgänge

Wir sind sehr vergesslich und obendrein auch noch etwas Faul. Immer wieder sind wir losgefahren und hörten gleich nach der ersten Kurve eine polternde Schublade oder fuhren mit offenen Fenstern durch die Gegend. Das war eigentlich der Grund, weshalb wir uns für die Automation entschieden und mit dem folgenden Codeschnipsel schalten wir automatisch ein paar Ausgänge am Arduino, wenn der Motor gestartet und abgestellt wird.

Zuerst wird gefragt, ob sich das Relais des Motorsignals geändert hat. So passiert auch erst etwas, wenn der Motor auch wirklich eingeschaltet oder abgestellt wird. Nach der kurzen anti Flackern Pause wird gefragt, ob der Motor eingeschaltet ist. Das Relais gibt dafür missverständlicherweise wieder ein LOW aus. Wenn der Motor abgestellt ist, werden die Variablen der zu schaltenden Geräte mit vordefinierten Werten überschrieben.

In unserem Fall sollen sich die Schubladen abschließen, die Wasserpumpe und der Warmwasserboiler vom Strom genommen werden und die Außenbeleuchtung abgeschaltet werden. Wenn der Motor abgestellt wird, sollen sich lediglich die Schubladen entriegeln.

Dadurch, dass wir nur zum Zeitpunkt des ein- und abschalten des Motors nur ein mal und lediglich die Variablen überschreiben, können diese zu jedem anderen Zeitpunkt wieder mit den Tastern verändert werden. Das geht aber nur, wenn die Pin-Ausgänge erst am Ende des Sketches mit den Inhalten der Variablen geschrieben werden.

...
//Engine Start with D+ Relay
if (digitalRead(MOTORDPLUS) != motordplusbefore)
{
  delay(10);
  if (digitalRead(MOTORDPLUS) == LOW)
  {
    lock = true;
    pump = false;
    boiler = false;
    outdoorlight = false;
  }
  if (digitalRead(MOTORDPLUS) == HIGH)
  {
    lock = false;
  }
  motordplusbefore = digitalRead(MOTORDPLUS);
}
...

Schließen und Öffnen der Schubladen

Wie schon im zweiten Teil beschrieben, schalten wir die Schubladenmotoren mit zwei Relais. Wenn beide Relais ausgeschaltet (also HIGH) sind, liegt an beiden Polen der Motoren Minus an. Wenn eines der Relais eingeschaltet (also LOW) wird, fließt von hier der Strom und der Motor bewegt sich in eine Richtung.

Eine weitere Schwierigkeit ist es, dass die Motoren sehr viel Strom verbrauchen, wenn sie an der Endposition angekommen sind. Aus dem Grund schalten wir die Relais nach einer sehr kurzen Zeit auch wieder ab. Solang, dass die Motoren auch schließen und so kurz, dass die Sicherung nicht ständig herausfliegt.

Gelöst haben wir das Ganze mit einem ähnlichen Code wie bei den Tastern. Wenn sich der Inhalt der Variable geändert hat, wird ein Zähler auf NULL gesetzt und anschließend das richtige Relais eingeschaltet. Während das Programm immer wieder von oben herunterläuft, wird der Zähler immer wieder um eins erhöht (++). Sobald das Programm so oft durchgelaufen ist, bis der Zähler den Wert der locktime überschreitet, bleibt das Relais eingeschaltet. Danach schaltet es sich wieder aus und die Motoren bekommen keinen Strom mehr. Der Wert 120 hört sich zwar sehr lang an, wiederum muss man bedenken, dass ein Mikrocontroller unglaublich schnell ist und es nur ein Bruchteil einer Sekunde entspricht. Aber auch nur solange keine Delays im Script enthalten sind, die den Ablauf verzögern könnten!

...

bool lock;             //Soll auf- oder abgeschlossen werden
bool lockcurrent;      //Gespeicherter vorheriger Wert
int lockcount;         //Timer der Stromzufuhr
int locktime = 120;    //Zeit der Stromzufuhr

...

//Write lock (Schließanlage) mit automatischer Abschaltung
if (lock != lockcurrent) {
  lockcurrent = lock;
  lockcount = 0;
}
if (lock == true && lockcount < locktime) {
  lockcount++;
  digitalWrite(RELAY3, LOW);
  digitalWrite(RELAY4, HIGH);
}
else if (lock == false && lockcount < locktime) {
  lockcount++;
  digitalWrite(RELAY3, HIGH);
  digitalWrite(RELAY4, LOW);
}
else {
  digitalWrite(RELAY3, HIGH);
  digitalWrite(RELAY4, HIGH);
}
...

Wie geht es weiter?

Mit dem ersten groben Wissen der Programmiersprache und der Nutzung des Arduinos, solltest du in der Lage sein erste eigene Codezeilen zu schreiben um dich nach und nach in das System einzuarbeiten. Auf der Arduino-Webseite kannst du dich detailliert in die einzelnen Befehle einlesen. Im Internet findest du viele kleine Beispielprojekte mit Codes, mit denen du erste kleine simple Projekte umsetzen kannst, bevor du dich an ein ganzes Alarmsystem setzt.

Im nächsten und vorerst letzten Teil werden wir dir unseren eigenen Code präsentieren, grob erklären und abschließend kostenlos zur Verfügung stellen.

Liege Grüße,
Hanna & Dorian

Werbung:

Bleib auf dem Laufenden

Dir gefällt, was du siehst? Dann abonniere doch meinen Newsletter und ich schreibe dir, wenn ich etwas Neues veröffentlicht habe.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Translate