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: 

Selbstgebauter Handsender
Selbstgebauter Handsender

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);
}

 

11 thoughts on “Funksteckdosen und Handsender

  1. Hallo Wolfgang,
    habe versucht Deinen Sketch handsender.ino in der Arduino-Ide zu compilieren, Ohne Erfolg. Es wird folgende Fehlermeldung ausgegeben:
    In function ‚INT1_vect‘:
    C:\Users\mail\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\WInterrupts.c:373:1: warning: ‚INT1_vect‘ appears to be a misspelled ’signal‘ handler, missing ‚__vector‘ prefix [-Wmisspelled-isr]
    IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
    ^
    In function ‚INT1_vect‘:
    C:\Users\mail\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\WInterrupts.c:373:1: warning: ‚INT1_vect‘ appears to be a misspelled ’signal‘ handler, missing ‚__vector‘ prefix [-Wmisspelled-isr]
    IMPLEMENT_ISR(INT1_vect, EXTERNAL_INT_1)
    ^
    Der Sketch verwendet 2334 Bytes (113%) des Programmspeicherplatzes. Das Maximum sind 2048 Bytes.
    Globale Variablen verwenden 208 Bytes (162%) des dynamischen Speichers, -80 Bytes für lokale Variablen verbleiben. Das Maximum sind 128 Bytes.
    Der Sketch ist zu groß; unter https://support.arduino.cc/hc/en-us/articles/360013825179 finden sich Hinweise, um die Größe zu verringern.
    Textbereich überschreitet den verfügbaren Platz auf der Platine

    Compilation error: Textbereich überschreitet den verfügbaren Platz auf der Platine
    Kannst Du mir bitte wieterhelfen ?!
    Vielen Dank
    Lothar

    1. Hallo Lothar,
      den Mitteilungen des Compilers entnehme ich, dass du einen ATtiny25 verwenden willst, richtig? Der hat einen Programmspeicher (Flash) von 2048 Byte und einen dynamischen Speicher (SRAM) von 128 Byte. Auf einem ATtiny45 oder ATtiny85 würde es passen.

      Eigenartig ist, dass ich andere Werte bekomme, die auch das Flashen eines ATtiny25 erlauben:
      Der Sketch verwendet 1394 Bytes (68%) des Programmspeicherplatzes. Das Maximum sind 2048 Bytes.
      Globale Variablen verwenden 72 Bytes (56%) des dynamischen Speichers, 56 Bytes für lokale Variablen verbleiben. Das Maximum sind 128 Bytes.

      Irgendetwas ist also bei dir anders als bei mir.

      Die Bedingungen bei mir sind:
      Boardpaket: ATtinyCore von Spence Konde
      Board: ATtiny25 (ohne Bootloader)
      Bibliothek: rc-switch, Version: 2.6.4
      Sktech: Handsender.ino – ohne jegliche Veränderung.

      Der Link, der helfen soll, die Größe zu verringern, nützt nichts, da das „F“-Makro lediglich Variablen vom SRAM in den Flash auslagert. Da aber beide Speicher nicht ausreichen, funktioniert das nicht. In dem Sketch sind einige Wiederholungen. Ich habe mal versucht, das in for-Schleifen zu packen und ich habe mal die übersendeten Codes als Variable angelegt, also z.B: const char code1[ ] = „010001000001000101010001“; . Das nützt aber nichts. Der Compiler optimiert das so schon.

      Also, zusammengefasst: entweder du nimmst einen größeren ATtiny oder du forschst mal nach, warum der Sketch bei dir mehr Platz benötigt als bei mir.

      VG, Wolfgang

      1. Hallo Wolfgang,
        zunächst vielen Dank für Deine schnelle Antwort.
        Wenn ich Deinen Beitrag Nr.16 gelesen hätte, dann hätte sich meine Frage garnicht erst gestellt :
        ich verwende ein digistump-Modul.
        Nochmals Danke und vG
        Lothar

  2. Hallo,

    der Beitrag scheint optimal für meine Frage zu sein. Ich benutze ein FS1000A-Sender und MX-RM-5V-Empfänger (beliebiges Set von Ebay). An beiden habe ich eine Antenne angelötet. Seit ich die Antenne angelötet habe ist es mir bereits möglich, mit dem Sender zu senden und dies über den Empfänger über geringste Entfernung zu empfangen. Soweit so gut.

    Mein Ziel ist es jedoch, nicht den FS1000A-Sender als Signalquelle zu nutzen, sondern einen externen 4-Kanal-Handsender (ebenfalls beliebig von Ebay, https://www.ebay.de/itm/403798023468?hash=item5e043cdd2c:g:Q7MAAOSw8oJi38RT). Leider empfange ich nichts vom Handsender.
    Daher meine Frage, ob eventuell Handsender und Empfängermodul „nicht kompatibel“ zu einander sein könnten, eventuell gibt es Unterschiede bei den verwendeten Chips und ich habe ein ungünstiges Paar erwischt? Oder ist da alles das „Gleiche“? Leider bin ich mit meinen Recherchen auf keine weiterführenden Informationen gestoßen, möchte aber nicht blind weitere Handsender oder Empfängermodule kaufen.

    Ich würde mich über eine Antwort freuen.

    Viele Grüße
    Martin

    1. Hallo Martin,

      hat denn der Handsender schon ein Signal „gelernt“? So, wie ich das in der Anleitung auf eBay lese, ist das eine Fernbedienung mit der man andere Fernbedienung klont. Ob das Teil ein bestimmtes, vor-eingestelltes Signal funkt, wenn man noch nichts geklont hat, das weiß ich nicht. Wenn du keinen Handsender zum Klonen hast, ist das kein Problem, du kannst die ja ein Signal „ausdenken“ und mit dem FS1000A und dem SendDemo Sketch in Dauerschleife senden. So würdest du dann einen Handsender simulieren.

      VG, Wolfgang

      1. Hallo Wolfgang,

        vielen Dank für die schnelle Antwort. Meine Vermutung ging auch in die Richtung, dass der Schlüssel das Signal eventuell nicht in geeigneter Form sendet. Ich hatte den Schlüssel leider zurückgesetzt, bevor ich das voreingestelltes Signal getestet habe. Ich habe dann in der Tat versucht, ihn über den FS1000A anzulernen (bin aber mit Raspberry Pi unterwegs), und er hatte das zu lernende Signal auch sehr schnell „angenommen“. Meine Vermutung ist nach deiner Antwort nun jedoch, dass das was er gelernt hat nicht mein ursprünglich gewolltes Lernsignal ist, da ich es nur einmal gesendet habe und nicht in Dauerschleife.

        Gibt es für die Dauerschleife für das Signal zum Anlernen eines Handsenders allgemeine Eigenschaften, die man auf jeden Fall erfüllen muss, z.B. ein bestimmte Rate mit der gesendet wird? Das von dir vorgeschlagene SendDemo Sketch scheint jedoch ein guter Anhaltspunkt zu sein, ich werde mich mal damit beschäftigen, es sollte ja etwas Ähnliches auch für den RasPi verfügbar sein.

        Vielen Dank und Viele Grüße
        Martin

        1. Hallo Martin, ob es spezielle Anforderungen hinsichtlich der Anzahl der Signale und Pausen gibt, das weiß ich nicht. Ich würde den Handsendersketch mal als Grundlage nehmen und ein wenig herumprobieren. Ich habe mir übrigens auch so einen Sender bestellt, weil es eine gute Alternative zu meinem Selbstbausender ist. Allerdings bekomme ich das Teil erst Ende August.
          VG, Wolfgang

  3. 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

  4. 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

  5. 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

  6. 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