AVR: Elro Funksteckdosen mit ATTINY 2313 schalten

Wie ich bereits in den letzten Artikeln beschrieben habe, lassen sich Funksteckdosen, die auf dem HX2262 Chip basieren, problemlos mit dem Raspberry Pi steuern. Die Kodierung der Daten habe ich dabei weiterhin dem HX2262 überlassen. Will man auf den Einsatz des ICs verzichte, muss man das Protokoll verstehen, das er zur Kommunikation mit der Gegenseite nutzt. Die Arbeit, das Protokoll zu analysieren hat sich zum Glück bereits jemand gemacht. Auf dieser Seite wird die Funktionsweise der Funksteckdosen ausführlich beschrieben. Basierend auf diesen Erkenntnissen existieren bereits diverse Implementierungen für unterschiedliche Plattformen.

Verwendete Hardware

Den Raspberry Pi halte ich persönlich für ungeeignet, die benötigten Signale zu generieren. Der RPi ist ein Multitasking-System. Lastspitzen einzelner Prozesse können demnach andere, parallel laufende Prozesse beeinflussen. Ein auf die erforderlichen 400 µs genaues Echtzeitverhalten ist also nicht zu erwarten. Statt des RPis habe ich stattdessen auf einen Mikrocontroller der Firma Amtel, einen ATTINY 2313, gesetzt. Für diesen AVR konnte ich Netz keine fertige Implementierung finden. Es gab jedoch mehrere Lösungen für die Arduino Plattform. Da beide Systeme mit C programmiert werden, war eine Anpassung des Codes nicht schwierig.

ATTINY 2313

Beim Einstieg in den Umgang mit dem ATTINY fand ich diese Seite sehr hilfreich. Dort erfährt man eigentlich alles, was man für den Start wissen muss. Ich verzichte daher darauf, näher auf die Basics einzugehen.

Die verwendete Schaltung besteht neben dem ATTINY 2313 aus einer LED, einem Knopf und dem hier beschriebenen Funkmodul.

ATTINY2313 433,92 Mhz  ATTINY2313_Pinout

Der Programmcode

Das folgende Programm implementiert das Funkprotokoll des HX2262 mit Hilfe der Funktion codeSenden(). Mit Hilfe des an PB0 angeschlossenen Knopfes wird die an PA1 angeschlossene LED geschaltet und entsprechend ein Ein- bzw. Ausschaltsignal an die Funksteckdose mit der Kodierung 10111/C gesendet. Das Programm implementiert eine HX2262 kompatible Fernbedienung für eine Funksteckdose auf Basis eines ATTINY 2313. Eine Erweiterung auf mehrere Geräte ist nach dem gleichen Schema problemlos möglich.

[c language=“++“]
// —————————————–
// Schalten von Elro Funksteckdosen
// ATTINY 2313
// —————————————–
#define F_CPU 1000000 // 1 MHz
#define funkpin PB1
#define ledpin PA1
#define HIGH 1
#define LOW 0
#include <avr/io.h>
#include <util/delay.h>
#include <stdbool.h>
#include <string.h>

//Wiederholungen der Funkübertragung
int repeat = 8;
char switchcon[12]="0F000FF0FF0F";
char switchcoff[12]="0F000FF0FFF0";

void SetupFunkPin(){
 // FunkPin als Ausgang schalten
 DDRB = (1 << funkpin);
}

void setpin(int pin, int state){
 if (state==HIGH){
  PORTB |= (1 << pin);
 }
 if (state==LOW){
  PORTB &= ~(1 << pin);
 }
}

void delayoneclk(int clks){
 for(int i=0; i<=clks; i++){
  _delay_us(342);
 }
}

void codeSenden(char *c){
 char ch;
 
 for(int i=0; i<=repeat; i++){
  for(int j=0; j<=11; j++){
   ch = c[j];
   if (ch==’0′){
    setpin(funkpin, HIGH);
    delayoneclk(1);
    setpin(funkpin, LOW);
    delayoneclk(3);
    setpin(funkpin, HIGH);
    delayoneclk(1);
    setpin(funkpin, LOW);
    delayoneclk(3);
   }
   if (ch==’F‘){
    setpin(funkpin, HIGH);
    delayoneclk(1);
    setpin(funkpin, LOW);
    delayoneclk(3);
    setpin(funkpin, HIGH);
    delayoneclk(3);
    setpin(funkpin, LOW);
    delayoneclk(1);
   }
   if (ch==’1′){
    setpin(funkpin, HIGH);
    delayoneclk(3);
    setpin(funkpin, LOW);
    delayoneclk(1);
    setpin(funkpin, HIGH);
    delayoneclk(3);
    setpin(funkpin, LOW);
    delayoneclk(1);
   }
   
  }
  //Sende Sync 32 Takte
  setpin(funkpin, HIGH);
  delayoneclk(1);
  setpin(funkpin, LOW);
  delayoneclk(31);
  
 }
}
int main (void)
{
 
 PORTB = _BV(PB0);
 //Pin PB0 als Eingang definieren
 DDRB|=(1<<PB0);
 
 // Pin 1 von Port A (PA1) als Ausgang schalten
 DDRA = (1 << PA1);
 
 bool buttonpressed=false;
 bool ison=false;
 bool buttonreleased=true;
 SetupFunkPin();
 
 
 // Endlosschleife
 for (;;) {
  //Prüfen, ob der Knopf gedrückt wurde
  if (bit_is_clear(PINB,0) && buttonreleased){
   buttonreleased=false;
   buttonpressed=true;
  }
  if (!bit_is_clear(PINB,0)){
   buttonreleased=true;
  }
  //Wenn der Knopf gedrückt und wieder losgelassen wurde…
  if (buttonpressed && buttonreleased){
   buttonpressed=false;
   //Wenn der bisherige Zustand nicht "on" war, einschalten
   if (!ison){
    PORTA |= (1 << ledpin);  // bit im Portregister auf 1 setzen => LED leuchtet
    codeSenden(switchcon);
    ison=true;
   }
   //Ansonsten ausschalten
   else{
    PORTA &= ~(1 << ledpin); // bit im Portregister auf 0 setzen => LED aus
    codeSenden(switchcoff);
    ison=false;
   }
  }
 }
}
[/c]

Download elro_attiny.zip

Der Code ist natürlich noch verbesserungsfähig. Für mich war das Ganze jedoch eher ein Spielprojekt, um mich mit dem ATTINY vertraut zu machen. Vielleicht findet ja jemand den Ansatz trotzdem nützlich.

4.60 avg. rating (91% score) - 5 votes

8 Gedanken zu “AVR: Elro Funksteckdosen mit ATTINY 2313 schalten

  1. Hallo Jan,

    vielen Dank für das bereitstellen des Programms für den ATTINY. Hab noch zwei Fragen, wie bist du auf die delaytime von 342us gekommen? Irgendwie erschließt sich mir das noch nicht.
    Scheinbar ist beim Kopieren des Programms etwas schiefgegangen. delay und codeSenden funktionieren so nicht. Außerdem sind oben noch leere #includes und int button1; wird auch nicht benutzt.

    Gruß Yannick

    • Danke für die Hinweise, ich werde den Code bei Gelegenheit bereinigen. Was genau geht bei den beiden Funktionen nicht? Gibt es einen Fehler vom Compiler? Welche IDE verwendest du? Ich habe Atmel Studio 6 verwendet.
      Auf das Delay bin ich nach Studie der im Artikel verlnkten Seite gekommen. Dazu kam dann auch etwas Ausprobieren. Ich denke, der Takt des Attiny ist auch nicht wirklich genau genug, um mit dem exakten theoretischen Wert hinzukommen. Mit einem externen Quarz sollte das besser klappen. Grundsätzlich sind die Funksteckdosen aber auch relativ tolerant.

      Gruß

      Jan

      • Bei den beiden Funktionen fehlt einfach was bei den for-Schleifenköpfen. for(int i=0; i _delay_us(342);
        } macht ja keinen Sinn. Müsste wahrscheinlich eher for(int i=0; i<clks;i++) heißen.

        Ach ich hab noch eine Frage. Ich möchte das ganze gerne auf einem Atmega8 mit externem 8MHz Quarz laufen lassen. Da ich gelesen habe, dass die _delay_us(); Prozessortakt abhängig ist und man eigentlich F_CPU definieren muss, wollte ich nachfragen mit wecher Frequenz der ATTINY bei dir läuft? 4 oder 8 MHz?

        Gruß Yannick

        • Die Schleifen sind beim Einfügen wohl abgeschnitten worden. Der Attiny2313 wird von Haus aus mit 8 Mhz getaktet, hat aber einen 8er Teiler aktiviert. Damit die Delays passen, muss F_CPU auf die korrekte Frequenz des AVRs gesetzt werden, das ist korrekt. Mit ein paar Tagen und einigen Programmierstunden Abstand wirkt mein Code echt verbesserungsbedürftig. Ich denke, das hat bei mir nur funktioniert, weil der AVR zusällig mit dem Standardtakt lief. 🙂

  2. Hallo,

    vielen Dank für die tolle Umsetzung. Funktionierte bei mir auf Anhieb. Für die Schaltung mehrerer Funksteckdosen mit mehreren Tasten muss ich als Noob noch ein bisschen den Gehirnschmalz anstrengen, aber ich bin zuversichtlich, dass das irgendwann funktionieren wird.
    Geh ich richtig in der Annahme, dass die rote LED nur zu Dekorationszwecken aufgesteckt ist?

    Gruß Franz

    • Die LEDs sind beide für die Funktion nicht erforderlich. Ich glaube, ich hatte die damals für die Fehlersuche angeschlossen. Sag Bescheid, wenn du bei der Lösung mit mehreren Tasten noch Unterstützung brauchst.

      • Ok, die LED ist für die Statusanzeige, wie ich festgestellt habe (nachdem ich mir den Quelltext genauer angesehen habe). Diese steckt nur auf dem Bild in der verkehrten Reihe, muss zwischen – und PA1, dann zeigt sie an, ob die Funksteckdose an ist oder nicht (zumindest, wenn sie beim einstecken aus war).

        Für die Schaltung mehrerer Steckdosen mit mehreren Schaltern bräuchte ich tatsächlich Hilfe. Aber ich möchte Deine Zeit nicht allzusehr in Anspruch nehmen. Dankbar für einen Hinweis oder einen Code wäre ich aber auf jeden Fall.

        Gruß Franz

Schreibe einen Kommentar

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

Spamschutz * Time limit is exhausted. Please reload the CAPTCHA.