Nachdem Handy und TV vom Namen her schon smart sind (meiner Ansicht nach aber doch eher ziemlich dumm), wollen einem die Elektronik-Hersteller nun das "Smart Home" verkaufen.
Philips verkauft seine "LightBulbs" für 20€ je Birne, Samsung steigt auch in den Markt ein; jeder hat dafür eine passende Äpp am Start, über die man das Licht ein- und ausschalten, dimmen und eine andere Farbe geben kann.

Meine Meinung dazu: Teures Spielzeug. Die Philips-Lampen kann ich mit der Philips-Äpp steuern, die Samsung-Lampen mit der Samsung-Äpp, wenn Apple auch noch auf den Markt kommt, gibt's noch ne weitere. Entweder muss ich mir immer alle Lampen neu kaufen, wenn ich lieber auf den Mitbewerber umsteigen will, oder ich muss ja nach Lampe eine andere Äpp benutzen – sie mal ordinär mit dem Lichtschalter zu bedienen kann man sowieso vergessen.
Das Handy in die Hand nehmen, entriegeln, passende Äpp suchen und öffnen...das kann doch nicht das "smart home" sein?!

Die Zukunft sieht meiner Ansicht nach so aus, wie die Seite digitalstrom.de es bewirbt. Die dazugehörige Technik ist allerdings leider noch zu teuer (man rechne mal mit 100€ für jedes Elektrogerät, das ich steuern möchte).

Da ich einige Steh- und Sideboardlampen sowieso schon an einer billigen Baumarkt-Funksteckdose hängen hatte (zum Beispiel rechts abgebildet. Gibt's im Toom Baumarkt im Viererpack für 11€), dachte ich mir "Kann ich diese statt mit der Funk-Fernbedienung nicht auch vom Computer aus steuern?".
Wenn ich etwas von meinem Computer aus steuern kann, ist sowieso alles möglich: Automatisierung, Zeitschaltung, Schaltung in Abhängigkeit bestimmter Gegebenheiten, Bedienung per Browser/Hotkey/Butler/Handy,...

So kam mein erstes Arduino-Projekt in's Rollen...

 

Inspiration fand' ich auf der Seite homecontrol4me, die ein ähnliches Projekt beschreibt, bei dem der Arduino autark arbeitet (stellt selbst einen Webserver dar, ist per Ethernet mit dem Netzwerk vebunden).

Mein Abwandlung dieses Projektes ist, dass der Arduino nur Funksignale an die Steckdosen sendet, dabei via USB an einen Mac angeschlossen ist, der den Arduino steuert.
Der Mac läuft sowieso im Serverbetrieb, so spare ich mir den Ethernet-Shield für den Arduino und der Arduino kann seinen Strom via USB vom Mac beziehen (statt ihn separat mit einem Netzteil zu betreiben; spart etwas Strom).

Meine Einkaufsliste

  • Arduino Uno (oder Mikro oder Nano...spielt eigentlich keine Rolle)
  • 433MHz Sender hatte ich bei eBay gefunden.
  • Läuft bei mir auch nach einem Jahr noch alles auf einem Breadboard und Stecker-Kabeln... auf Lötkolben hatte ich noch keine Lust.
  • USB-Kabel zum Anschließen des Arduino an den Mac
  • Damit sich alles gut verstauen lässt ggf noch ein passendes Gehäuse für Arduino und Board
  • Im Falle des Arduino Uno brauchte ich noch einen 10µF-Kondensator, da sich der Arduino Uno beim Anschließen via USB an den Computer immer wieder resettet und den aufgespielten Sketch löscht. Kann man mit dem Kondensator überbrücken (siehe dieser Artikel)

Die Steckdose

Die erwähnten Steckdosen haben auf der Rückseite DIP-Schalter. Möglicherweise muss man zuerst eine Schraube lösen, um an diese Schalter ranzukommen.

Die ersten 5 Schalter geben die Steckdosen-Gruppe an (die Gruppe muss auch bei der mitgelieferten Fernbedienung eingestellt sein, damit die Steckdosen reagieren), die letzten 5 Schalter geben die Steckdosennummer an (und somit auf die die Taste 1, 2, 3 oder 4 der Fernbedienung reagieren).

Im Beispiel Rechts haben wir eine Steckdose Nummer 10000 der Gruppe 10010.

Diese wollen wir im folgenden per Arduino ein- und ausschalten.


Die Hardware (nachgebau mit einem Nano)

...in Bild...
 
...und Schaltplan.
  • GND des 433MHz-Senders mit GND des Arduinos verbinden
  • VCC des 433MHz-Senders mit 5V des Arduinos verbinden
  • DATA des 433MHz-Senders mit beliebigem digitalen Ausgang des Arduinos verbinden (in meinem Beispiel D3)
  • Je nach Baustein einen möglichen Antennen-Port noch mit einem 17 cm langen Draht verbinden
 

Software auf Arduino

Obligatorisch zum Erstellen des Sketches ist natürlich die gratis erhältliche Arduino-Software.

Außerdem benötigen wir die RCSwitch-Bibliothek, die im Sketch mittels

include
 eingebunden wird.
Die RCSwitch-Library einfach von der GitHub-Seite (Ordner libraries) herunterladen und in der Arduino-Software einbinden (in den Arduino-Library-Ordner kopieren, der sich unter ~/Dokumente/Arduino/ befinden sollte).

Mit ihr erstellen wir einen Beispiels-Sketch

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
int test = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("Moment...");
  mySwitch.enableTransmit(3); # <-- Nummer des digitalen Arduino-Ausgangs
  }

void loop() {
  // Kurze Gedenk-Pause
  delay(5000);
 
  if (test == 0) {
    steckdoseSchalten("1-10010-10000");
    test = 1;
    }
   
   // Kurze Pause
   delay(100);
  }

void steckdoseSchalten(String id) { // Akzeptiert eine id nach dem Schema anAus-Gruppe-Dose, z.B. 1-10010-10000
  char gruppe[6];
  char dose[6];
  int stat;

  stat   = id.substring(0, 1).toInt();
  id.substring(2, 7).toCharArray(gruppe, 6);
  id.substring(8, 13).toCharArray(dose, 6);
  if (stat == 0) {
      mySwitch.switchOff(gruppe, dose);
      Serial.print("SWITCHOK:");
      Serial.println(id);
      }
  if (stat == 1) {
      mySwitch.switchOn(gruppe, dose);
      Serial.print("SWITCHOK:");
      Serial.println(id);
      }
  }

Fügt man diesen Sketch in ein neues leeres Dokument ein und ladet ihn auf den Arduino hoch, sollte sich nach 5 Sekunden die Steckdose einschalten.

Mit geändertem Befehl
steckdoseSchalten("0-10010-10000");
kann man sie wieder ausschalten.

Soweit der erste Test.

Vom Mac aus steuern

Etwas abgewandelter Code, der auf seriellen Input wartet und bei passender Eingabe die Steckdose wie gehabt schaltet:

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();
String  input  = "";

void setup() {
  Serial.begin(9600);
  Serial.println("Moment...");
  mySwitch.enableTransmit(3);
  }

void loop() {

  // Serial-Port abfragen
  int chr = Serial.read();
  if (chr > 0) {
    input += (char)chr;
  } else if (chr == -1 && input != "") {
    if (input.substring(0, 5) == "STKD:") {
      steckdoseSchalten(input.substring(5,18));
      }
    input = "";
    }

  // Kurze Pause
  delay(100);
  }

void steckdoseSchalten(String id) {
  char gruppe[6];
  char dose[6];
  int stat;

  stat = id.substring(0, 1).toInt();
  id.substring(2, 7).toCharArray(gruppe, 6);
  id.substring(8, 13).toCharArray(dose, 6);
  if (stat == 0) {
    mySwitch.switchOff(gruppe, dose);
    Serial.print("SWITCHOK:0-");
    Serial.print(gruppe);
    Serial.print("-");
    Serial.println(dose);
    }
  if (stat == 1) {
    mySwitch.switchOn(gruppe, dose);
    Serial.print("SWITCHOK:1-");
    Serial.print(gruppe);
    Serial.print("-");
    Serial.println(dose);
    }
  }

Wenn wir diesen Code zum Arduino hochladen und den SerialMonitor der Arduino IDE öffnen, können wir mit der Eingabe STKD:1-10010-10000 gefolgt von Enter dieselbe Steckdose wie im ersten Beispiel einschalten.
Das Prefix STKD: verlange ich, weil ich den Arduino und die Arduino/Mac-Schnittstelle noch für weitere Zwecke nutzen möchte und hiermit mitgeben will: "Bitte folgende Steckdose schalten, nichts anderes tun."

Nun – die Eingabe von STKD:1-10010-10000 kann ich entweder im SerialMonitor der Arduino-IDE machen oder auch von einem Perl-Skript an den Arduino übergeben, was zum Zwecke der Automatisierung praktischer ist.
Wir beenden die Arduino IDE und stecken den Arduino aus.

Zur Kommunikation zwischen Arduino und Perl benötigen wir die CPAN-Bibliothek Device::SerialPort::Arduino und müssen wissen, als welche serielle Schnittstelle der Arduino am Mac auftaucht.

Dazu lassen wir uns im Terminal alle seriellen Schnittstellen anzeigen:

ls /dev/tty.*
stöpseln den Arduino wieder ein und schauen nochmals nach:
ls /dev/tty.*

Im Falle eines Arduino Nano wäre bei mir nun die Schnittstelle /dev/tty.usbserial dazu gekommen.

Im Falle eines Arduino Uno wäre bei mir eine Schnittstelle /dev/tty.usbmodemfd123 mit irgend einer Zahlenfolge hinzugekommen, die nach jedem Neustart anders sein kann. Dies müssen wir im Skript beachten.
Außerdem muss man beim Arduino Uno beachten, dass das Programm, das wir vorher über die Arduino IDE auf ihn geladen haben, gelöscht wird, wenn wir ihn erneut per USB an den Mac anschließen. Ein unliebsames Auto-Reset, das man wie hier beschrieben unterbinden kann.

Was im Falle eines Arduino Nano noch zu beachten wäre ist, dass bei der Kommunikation vom Mac zum Arduino wie hier beschrieben das Steuerzeichen \0 mitgegeben werden muss.

Hier mein Perl-Skript arduino-set.pl

#!/usr/bin/perl

use Device::SerialPort::Arduino;
use strict;

my $PORT = "/dev/tty.usbserial";      # Im Falle des Nanos

#my $PORT = `ls /dev/tty.usbmodem*`;  # Im Falle des Unos irgendeine Schnittstelle
#$PORT =~ s/[\n\r]//;                 # verwenden, in der 'tty.usbmodem' vorkommt

my $arduino = Device::SerialPort::Arduino->new(
     port     => $PORT,
     baudrate => 9600, # Selbe Baudrate wie im Arduino-Code in setup()-Funktion!
     databits => 8,
     parity   => 'none'
     );

my $gruppe = $ARGV[0];
# Falls eine Textbezeichnung der Gruppe verwendet wurde...
if ($gruppe eq "wz") { $gruppe = "11111"; } # Als Beispiel die Steckdosen im Wohnzimmer
if ($gruppe eq "k")  { $gruppe = "10001"; } # Als Beispiel die Steckdosen in der Küche

my $dose = $ARGV[1];
# Falls die Steckdosennummer im Dezimalsystem angegeben wurde...
if ($dose eq "1") { $dose = "10000";}
if ($dose eq "2") { $dose = "01000";}
if ($dose eq "3") { $dose = "00100";}
if ($dose eq "4") { $dose = "00010";}
if ($dose eq "5") { $dose = "00001";}

$arduino->communicate("\0STKD:".$ARGV[2].'-'.$gruppe.'-'.$dose."\0"); # Im Falle des Nanos
#$arduino->communicate("STKD:".$ARGV[2].'-'.$gruppe.'-'.$dose);       # Im Falle des Unos

Verwendung, um zum Beispiel die Steckdose 1 der Gruppe 11111 einzuschalten:

arduino-set.pl 11111 10000 1

Um die Verwendung etwas zu vereinfachen, habe ich meine verwendeten Gruppen mit Kürzeln versehen, die ebenfalls im Skript vorkommen und durch ihr binäres Pendant ersetzt werden.
Ebenso lassen sich die einzelnen Steckdosen als Dezimal-Zahl statt binär angeben:

arduino-set.pl wz 1 1