Funksteckdosen und Handsender

Worum geht’s?

Viele funkgesteuerte Geräte wie z.B. Garagentore, Fenstersensoren, Funksteckdosen und Handsender basieren auf 433 MHz Technik. In meinem letzten Beitrag habe ich gezeigt, wie man mit Transmitter- und Receivermodulen Daten von einem Arduino zum anderen sendet. In diesem Beitrag zeige ich wie ein Arduino mit den oben genannten Geräten kommunizieren kann. Am Beispiel von Funksteckdosen und der RCSwitch Bibliothek erkläre ich das Prinzip und stelle am Ende noch einen selbstgebauten Handsender vor. 

Funksteckdosensets

Funksteckdosen werden meistens als Set, bestehend aus einem Sender und mehreren Steckdosen, angeboten. Solche Sets sind für 10 bis 30 Euro in Elektronikgeschäften oder Onlineshops erhältlich. Dabei gibt es lernende Steckdosen, die man auf An-/Aussignale trainieren kann und andere, bei denen man die Kanäle über Dipschalter („Mäuseklavier“) einstellen kann. Beide Versionen lassen sich mit dem Arduino koppeln, aber ich rate zu denen mit Dipschaltern, da man mit ihnen flexibler ist.

Einstellung ohne Arduino (Handsender zu Steckdose)

Am Sender stellt man die Kodierung mit den Dipschaltern 1 bis 5 ein. Diese muss mit der Kodierung an der Steckdose übereinstimmen. Die Dipschalter A bis E legen fest, auf welche Sendertaste die Steckdose „hört“, in diesem Fall also B. Die hier abgebildete Einstellung wird in allen weiteren Erklärungen und Beispielen verwendet. 

Dipschalter am Sender (li.) und an der Dose (re.)

Die RCSwitch Bibliothek

Wir wollen ja nun nicht das Set als solches benutzen, sondern entweder mit dem Sender einen Arduino steuern oder mit einem Arduino eine Funksteckdose steuern. Wer nicht in die Tiefen der Signalübertragung einsteigen möchte, braucht dafür zunächst eine Bibliothek. Für diesen Beitrag habe ich die RCSwitch Bibliothek gewählt. Zur Installation einfach dem Link folgen, als Zipdatei herunterladen und im Verzeichnis Arduino\libraries entpacken.  

Die Hardware

Ich verwende die in meinem letzten Beitrag vorgestellten und unten noch einmal abgebildeten Module. Für Details einfach noch einmal in den Beitrag gehen. Einfacher geht es aber auch nicht: für die Verbindung von Transmitter und Receiver zum Arduino wird GND mit GND, VCC mit 5 V und der Datenpin je nach Vorschrift aus den Beispielsketchen verbunden. Denkt an die Antennen, die ggf. noch an die Module gelötet werden müssen.

Diese Module werden in diesem Beitrag verwendet

Jetzt geht es los

Verwendung von Dipschaltersystemen

Um die Funksteckdose mittels Transmittermodul zu schalten, passt man einfach den Beispielsketch „TypeA_WithDIPSwitches.ino“ aus der RCSwitch Bibliothek entsprechend der Dipschaltereinstellung  an. Der Sketch ist selbsterklärend. Und das war’s schon! Wenn alles richtig eingerichtet wurde, sollte die Funksteckdose mit diesem Beispiel im Einsekundentakt ein- und ausgeschaltet werden. 

/*
  Example for outlets which are configured with a 10 pole DIP switch.
  
  https://github.com/sui77/rc-switch/
*/

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {

  // Transmitter is connected to Arduino Pin #10  
  mySwitch.enableTransmit(10);

  // Optional set pulse length.
  // mySwitch.setPulseLength(320);
  
}

void loop() {

  // Switch on:
  // The first parameter represents the setting of the first 5 DIP switches. 
  // In this example it's OFF-ON-OFF-ON-ON.
  // 
  // The second parameter represents the setting of the last 5 DIP switches. 
  // In this example the last 5 DIP switches are OFF-ON-OFF-OFF-OFF.  
  mySwitch.switchOn("01011", "01000");

  // Wait a second
  delay(1000);
  
  // Switch off
  mySwitch.switchOff("01011", "01000");
  
  // Wait another second
  delay(1000);
  
}

 

Verwendung anderer Systeme ohne Dipschalter

Auslesen des Funkcodes

Für andere Systeme (also solche ohne Dipschalter) muss man zunächst den Funkcode herausbekommen. Dazu verwendet man das Receivermodul, den Sender aus dem Set und am besten den Beispielsketch „ReceiveDemo_Advanced.ino“. Achtet darauf, dass hier der Datenpin des Receivermoduls mit Pin 2 des Arduino verbunden wird.  

/*
  Example for receiving
  
  https://github.com/sui77/rc-switch/
  
  If you want to visualize a telegram copy the raw data and 
  paste it into http://test.sui.li/oszi/
*/

#include <RCSwitch.h>
static const char* bin2tristate(const char* bin);
static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength);

RCSwitch mySwitch = RCSwitch();

void setup() {
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
}

void loop() {
  if (mySwitch.available()) {
    output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol());
    mySwitch.resetAvailable();
  }
}

void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) {

  const char* b = dec2binWzerofill(decimal, length);
  Serial.print("Decimal: ");
  Serial.print(decimal);
  Serial.print(" (");
  Serial.print( length );
  Serial.print("Bit) Binary: ");
  Serial.print( b );
  Serial.print(" Tri-State: ");
  Serial.print( bin2tristate( b) );
  Serial.print(" PulseLength: ");
  Serial.print(delay);
  Serial.print(" microseconds");
  Serial.print(" Protocol: ");
  Serial.println(protocol);
  
  Serial.print("Raw data: ");
  for (unsigned int i=0; i<= length*2; i++) {
    Serial.print(raw[i]);
    Serial.print(",");
  }
  Serial.println();
  Serial.println();
}

static const char* bin2tristate(const char* bin) {
  static char returnValue[50];
  int pos = 0;
  int pos2 = 0;
  while (bin[pos]!='\0' && bin[pos+1]!='\0') {
    if (bin[pos]=='0' && bin[pos+1]=='0') {
      returnValue[pos2] = '0';
    } else if (bin[pos]=='1' && bin[pos+1]=='1') {
      returnValue[pos2] = '1';
    } else if (bin[pos]=='0' && bin[pos+1]=='1') {
      returnValue[pos2] = 'F';
    } else {
      return "not applicable";
    }
    pos = pos+2;
    pos2++;
  }
  returnValue[pos2] = '\0';
  return returnValue;
}

static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) {
  static char bin[64]; 
  unsigned int i=0;

  while (Dec > 0) {
    bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0';
    Dec = Dec >> 1;
  }

  for (unsigned int j = 0; j< bitLength; j++) {
    if (j >= bitLength - i) {
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    } else {
      bin[j] = '0';
    }
  }
  bin[bitLength] = '\0';
  
  return bin;
}

 

Nach dem Start des Sketches und dem Drücken der ausgewählten Sendetaste erhält man auf dem seriellen Monitor die folgende Meldung für „ON“ und „OFF“ (bei Einstellung des Senders wie oben abgebildet und Kanal B):

Oben: „On“ Signal, unten: „Off“ Signal

Das ist der jeweilige Funkcode im Dezimal-, Binär- oder Tristateformat. Im Tristateformat erkennt man die Dipschaltereinstellung wieder, wenn man „F“ durch „OFF“ ersetzt und „0“ durch „ON“. Das letzte „0F“ bzw. „F0“ steht für An- und Ausschalten. Im Binärcode stehen „01“ und „00“ für „OFF“ bzw. „ON“ (nicht so wirklich wichtig, aber vielleicht ja interessant).

Dann notiert man sich den Code für Anschalten und Ausschalten in einem der Formate.  

Senden des Funkcodes

Für das Senden dieses Funkcodes mittels Transmittermodul schauen wir uns den Beispielsketch „SendDemo.ino“ an, den ich hier schon für unseren Beispielsender angepasst habe: 

/*
  Example for different sending methods
  
  https://github.com/sui77/rc-switch/
  
*/

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {

  Serial.begin(9600);
  
  // Transmitter is connected to Arduino Pin #10  
  mySwitch.enableTransmit(10);
  
  // Optional set protocol (default is 1, will work for most outlets)
  // mySwitch.setProtocol(2);

  // Optional set pulse length.
  // mySwitch.setPulseLength(320);
  
  // Optional set number of transmission repetitions.
  // mySwitch.setRepeatTransmit(15);
  
}

void loop() {

  /* See Example: TypeA_WithDIPSwitches */
  mySwitch.switchOn("01011", "01000");
  delay(1000);
  mySwitch.switchOff("01011", "01000");
  delay(1000);

  /* Same switch as above, but using decimal code */
  mySwitch.send(4460881, 24);
  delay(1000);  
  mySwitch.send(4460884, 24);
  delay(1000);  

  /* Same switch as above, but using binary code */
  mySwitch.send("010001000001000101010001");
  delay(1000);  
  mySwitch.send("010001000001000101010100");
  delay(1000);

  /* Same switch as above, but tri-state code */ 
  mySwitch.sendTriState("F0F00F0FFF0F");
  delay(1000);  
  mySwitch.sendTriState("F0F00F0FFFF0");
  delay(1000);

  delay(5000);
}

 

Zur Anschauung werden in dem obigen Beispiel alle Sendemethoden verwendet. Man braucht natürlich nur eine. 

Handsender

Handsender

Meistens wird man mit einem Transmittermodul eine Funksteckdose steuern wollen. Wer umgekehrt mit der Sendeeinheit Signale an seinen Arduino senden will, kann sich auch nur einen Handsender (also ohne Set) zulegen wie den oben abgebildeten. Einen richtig coolen „Hardwarehack“ mit genau diesem Sender habe ich hier entdeckt. Dort wird beschrieben, wie man den Handsender mit einem Bewegungsmelder zu einem kabellosen Bewegungsmelder umfunktioniert, der auf der Sendeseite keinen weiteren Arduino oder Microcontroller braucht. Ich habe es nachgebaut und es funktioniert. 

Ein selbstgebauter Handsender

Dann wollte ich noch einen Handsender selbst bauen. Mein Ziel war es ihn so minimalistisch wie möglich zu konstruieren. Vor allem wollte ich außer der Sendetaste keinen extra An-/Ausschalter für den Microcontroller, denn das haben Handsender, die man kaufen kann ja auch nicht. Herausgekommen ist folgendes: 

Als elektrische Bauteile wurden lediglich ein Taster, ein ATtiny 85, ein einfaches Transmittermodul und zur Stromversorgung ein 3.7 V Li-Akku aus dem Drohnenbau verwendet. Vielleicht fällt Euch auf, dass keine Antenne verwendet wurde. Je nachdem wie gut die Empfängerseite ist und wie weit man funken möchte, ist das auch nicht immer notwendig. 

Wie kann man nun mit nur einem Taster auskommen? Recht einfach: über Zeitsteuerung. Mit dem Betätigen des Tasters wird die Stromversorgung und damit der Sketch gestartet. Nach wenigen Sekundenbruchteilen wird das „An“-Signal gesendet. Ich sende es zur Sicherheit dreimal kurz hintereinander, falls etwas „im Äther“ verloren geht. Will ich ein „Aus“-Signal senden, bleibe ich einfach für eine weitere Sekunde auf dem Taster, sonst lasse ich einfach los. Hier der einfache Sketch dazu:  

#include <RCSwitch.h>

RCSwitch mySwitch = RCSwitch();

void setup() {
  mySwitch.enableTransmit(4);
  mySwitch.setPulseLength(311);
  delay(10);
}

void loop() {
  mySwitch.send("010001000001000101010001");
  delay(5);
  mySwitch.send("010001000001000101010001");
  delay(5);
  mySwitch.send("010001000001000101010001");
  delay(1000);
  mySwitch.send("010001000001000101010100");
  delay(5);
  mySwitch.send("010001000001000101010100");
  delay(5);
  mySwitch.send("010001000001000101010100");
  delay(5);
  delay(5000);
}

 

4 thoughts on “Funksteckdosen und Handsender

  1. Hallo Wolfgang!

    Das Problem ist gelöst und die Funksteckdose FUNKtionniert!
    Es war wohl wirklich der Sender defekt. Nun ging es recht schnell.

    Vielen Dank, dass Du mich hier unterstützt hast!

    Grüße!

    Klaus

  2. Hallo Wolfgang,

    vielen lieben Dank für die Tips und die schnelle Antwort!

    Leider hat nichts geklappt, was Du mir empfohlen hast. Habe sehr genau auf die Pin Belegung geachtet und auch nochmal Nano und Uno durch getauscht – wieder ohne Erfolg.

    Ich glaube ich bestelle mir jetzt einfach mal ein neues Set der Funkmodule – der Preis mit ca 3€ ist ja überschaubar und die Zeit, die ich mittlerweile investiert habe steht in keiner Relation mehr.

    Wenn ich die neuen Module bekommen und getestet habe, gebe ich Dir gerne Bescheid.

    Vielen Dank!!!!

    Klaus

  3. Hallo Klaus,

    also du verwendest SendDemo am Sender und ReceiveDemo_Advanced am Empfänger, richtig? Hast du sie in irgendeiner Form abgeändert? Wenn ja, kannst du sie mir vielleicht an wolfgang.ewald@wolles-elektronikkiste.de senden? Dann schaue ich mal, ob ich irgendetwas entdecke.

    Du könntest mal prüfen, ob die Übertragung wie im vorherigen Beitrag beschrieben funktioniert:

    https://wolles-elektronikkiste.de/433-mhz-funk-mit-dem-arduino

    Es kann natürlich auch mal ein Teil kaputt sein, aber die Erfahrung zeigt, dass in den meisten Fällen der Fehler irgendwo anders liegt. Ob etwas gesendet wird ist schwer zu prüfen. Aber du könntest am Empfänger schauen, ob überhaupt etwas ankommt (und vielleicht nur nicht richtig „verstanden“ wird), indem du den Daten Pin des receivers an einen I/O Pin hängst und mit digitalRead prüfst. Also sowas wie:
    if(digitalRead(dataPin)){
    Serial.println(„Signal erhalten!“);
    }
    Wenn du die Dinge probiert hast, melde dich nochmal. Das wird schon!

    VG, Wolfgang

  4. Hallo Wolle!
    Ich finde dein Seite echt klasse. Habe erst vor kurzem begonnen mich mit dem Arduino zu beschäftigen. Deine Artikel sind für mich super zum lernen und verstehen. Alles ist sehr gut erklärt! Vielen Dank dafür!

    Ich habe eine Frage zu den Funk Modulen. Ich will eine Steckdose mit Anlernfunktion ansteuern. Komme aber nicht weiter.
    Um zu überprüfen ob überhaupt Signale gesendet werden, habe ich mir zu meinem UNO, mit dem ich begonnen habe, noch einen NANO gekauft. Nun hängt der Sender am UNO und der Empfänger am NANO. Habe deine Sketche von oben hochgeladen aber es kommt am Empfänger nichts an (Die Signale von meiner Fernbedienung für die Steckdose empfange ich einwandfrei – Empfänger funktioniert also). Habe auch die Module an NANO und UNO vertauscht. Aber es klappt immer noch nicht.
    Habe auch schon eine Antenne am Sender angelötet – leider ohne Erfolg.

    Hast Du eine Idee an was es liegen könnte? Ist evtl das Sendemodul defekt? Oder gibt es noch eine Möglichkeit zu testen ob der Sender überhaupt sendet (LED oder Nachricht am Seriellen Monitor oder so etwas)?

    Vielen Dank für Deine Hilfe!

    Grüße!

    Klaus

Schreibe einen Kommentar

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