433MHZ Steckdosen Arduino ECMD

Begonnen von mcbain2k, 23 Januar 2014, 00:40:25

Vorheriges Thema - Nächstes Thema

mcbain2k

Hi Leute

nach SmasungTV und Onkyo hier wieder mal wieder was gestricktes. ::)

Es geht um die billig 433MHz Steckdosen z.B. von Pollin 3st für 10€

zum Binärcode:

die 10 ersten Stellen enstsprechen den DIP-Schalter der Steckdose

die 2 letzten stellen sagen an oder aus
1off  b001011000001
1on  b001011000010

das b dient der besseren Unterscheidung der Packete für den Arduino.

Hier hab ich den Arduino Sketch her und es gibt noch weitere Infos:
http://www.dserv01.de/howtos/funksteckdose-fernsteuern-mit-arduino/

Die ersten 5 Stellen sind die Gruppenadresse die nächsten 5 die Geräteadresse.
pro Gruppe also 5 Steckdosen möglich, da ich mehr  habe
übergebe ich auch eine Stelle des Gerätecodes in der Varibale.

define ARDUINOserial ECMD serial /dev/arduino1@9600
attr ARDUINOserial classdefs FSD=/usr/share/fhem/FHEM/fsd.classdef
attr ARDUINOserial room Arduino_serial

define FunkSteck1 ECMDDevice FSD 110000
attr FunkSteck1 devStateIcon on.*:FS20.on off.*:FS20.off
attr FunkSteck1 room Arduino_serial
attr FunkSteck1 webCmd on:off


fsd.classdef   
(postproc ist bei mir nur platzhalter)
params NUM
set on cmd {"b0010%NUM10"}
set on postproc {"" eq "" ? "" : ""; }
set off cmd {"b0010%NUM01"}
set off postproc {"" eq "" ? "" : ""; }


funksteck.ino

short rc_pin=7;
char code[12]; //neu: hier wird der Code gespeichert

void setup() {
  pinMode(rc_pin, OUTPUT);
  Serial.begin(9600); //neu: hier stellen wir die Baudrate fuer die serielle USB Verbindung ein
}
void loop() {
  while(Serial.available() <= 0){ delay(10);}
  while(Serial.read() != 'b'){ delay(10);}
  for(short i=0; i<12; i++){
    while(Serial.available() <= 0){ delay(10);}
    code[i] = Serial.read();
  }
  Serial.println(code);
  sendCode(code);
}

boolean sendCode(char code[]){
  for(short z = 0; z<7; z++){
    for(short i = 0; i<12; i++){
      sendByte(code[i]);
    }
  sendByte('x');
  }
  return true;
}

void sendByte(char i) {
  switch(i){
  case '0':{
    digitalWrite(rc_pin,HIGH);
    wait(1);
    digitalWrite(rc_pin,LOW);
    wait(3);
    digitalWrite(rc_pin,HIGH);
    wait(3);
    digitalWrite(rc_pin,LOW);
    wait(1);
    return;
  }
  case '1':{ //Der Code fuer '1'
    digitalWrite(rc_pin,HIGH);
    wait(1);
    digitalWrite(rc_pin,LOW);
    wait(3);
    digitalWrite(rc_pin,HIGH);
    wait(1);
    digitalWrite(rc_pin,LOW);
    wait(3);
    return;
  }
  case 'x':{ //Der Code fuer x(sync)
    digitalWrite(rc_pin,HIGH);
    wait(1);
    digitalWrite(rc_pin,LOW);
    wait(31);
  }

}
}

void wait(int x) {
  delayMicroseconds(x*350);
}


Viel Spass beim nachbauen.

McBain

linusd

#1
Hi McBain,

super Beitrag der mir sehr geholfen hat!
Zur Kommunikation zwischen den Arduino's setzte ich allerdings die Lib VirtualWire ein. 8)

Deine Classdef habe ich übernommen.

params NUM
set on cmd {"b0010%NUM10"}
set on postproc {"" eq "" ? "" : ""; }
set off cmd {"b0010%NUM01"}
set off postproc {"" eq "" ? "" : ""; }


Die Konfiguration im FHEM ist letztlich schön übersichtlich! :)

define ARDUINOserial ECMD serial /dev/ttyACM0@9600
attr ARDUINOserial classdefs FSD=/opt/fhem/FHEM/ECMD_Arduino.classdef
attr ARDUINOserial group Arduino_serial
attr ARDUINOserial verbose 5

define FunkSteck1 ECMDDevice FSD 110000
attr FunkSteck1 IODev ARDUINOserial
attr FunkSteck1 group Arduino_serial
attr FunkSteck1 room Labor
attr FunkSteck1 webCmd on:off
set FunkSteck1 off

define FunkSteck2 ECMDDevice FSD 111000
attr FunkSteck2 IODev ARDUINOserial
attr FunkSteck2 group Arduino_serial
attr FunkSteck2 room Labor
attr FunkSteck2 webCmd on:off
set FunkSteck2 off

define Relay1 ECMDDevice FSD 120000
attr Relay1 IODev ARDUINOserial
attr Relay1 group Arduino_serial
attr Relay1 room Labor
attr Relay1 webCmd on:off
set Relay1 off

define Relay2 ECMDDevice FSD 121000
attr Relay2 IODev ARDUINOserial
attr Relay2 group Arduino_serial
attr Relay2 room Labor
attr Relay2 webCmd on:off
set Relay2 off



Sketch für den ArduinoSerielVirtualWireServer (2 Relais werden lokal und 2 Relais remote geschaltet)

#include <VirtualWire.h>

byte analogPin;
int reservedPin = 5; //  Incoming Firmata data on this pin is handled specially.
int SESNOR_PIN = 10;
String deviceCode, swCode;
char code[12]; //neu: hier wird der Code gespeichert

void sendByte(String deviceCode, String swCode) {
   //In Abhängigkeit vom GeräteCode und dem Schaltbefehl wird die entsprechende Aktion ausgeführt
   if(deviceCode == "120000") {   
      if(swCode == "on") {   
        digitalWrite(8, HIGH);
      }
      if(swCode == "off") {   
        digitalWrite(8, LOW);
      }
    }

   if(deviceCode == "121000") {   
      if(swCode == "on") {   
        digitalWrite(9, HIGH);
      }
      if(swCode == "off") {   
        digitalWrite(9, LOW);
      }
    }

    if(deviceCode == "110000") {   
      if(swCode == "on") {   
        const char *msg = "relay1_on";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx(); // Wait until the whole message is gone
        digitalWrite(13, false);
        delay(10);     
      }
      if(swCode == "off") {   
        const char *msg = "relay1_off";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx(); // Wait until the whole message is gone
        digitalWrite(13, false);
        delay(10);     
      }
    }

    if(deviceCode == "111000") {   
      if(swCode == "on") {   
        const char *msg = "relay2_on";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx(); // Wait until the whole message is gone
        digitalWrite(13, false);
        delay(10);     
      }
      if(swCode == "off") {   
        const char *msg = "relay2_off";
        vw_send((uint8_t *)msg, strlen(msg));
        vw_wait_tx(); // Wait until the whole message is gone
        digitalWrite(13, false);
        delay(10);     
      }
    }
}

boolean sendCode(char code[]){
  //Der GeräteCode und Schaltbefehl wird extrahiert
  for(short i = 4; i<11; i++){
    if( i < 10){
      deviceCode += code[i];
    } else {
      if (code[i] == '0'){
        swCode = "on";
      } else {
        swCode = "off";
      }
    }
  }
  //Die extrahierten Infrmationen werden an die Ausführung übergeben
  sendByte(deviceCode, swCode);
  deviceCode="";
  swCode="";
  return true;
}

void setup() {

  Serial.begin(9600);   // Debugging only
  // Initialise the IO and ISR
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_set_tx_pin(18); //transmitter
  vw_set_rx_pin(19); //receiver
//  vw_set_ptt_pin(8); //push to talk
  vw_setup(2000); // Bits per sec
  vw_rx_start();       // Start the receiver PLL running
   // initialize the LED pins:
  for (int thisPin = 8; thisPin < 10; thisPin++) {
    pinMode(thisPin, OUTPUT);
  }
}

void loop() {

  //Das Empfangene Kommando wird analysert unf ohen Start-b in einen Char-Array geschrieben
  while(Serial.available() <= 0){ delay(10);}
  while(Serial.read() != 'b'){ delay(10);}
  for(short i=0; i<12; i++){
    while(Serial.available() <= 0){ delay(10);}
    code[i] = Serial.read();
  }
//Analyserter und Empfangener Code wird zur weiteren Aufbereitung übergeben
  sendCode(code);
}


Sketch für den ArduinoVirtualWireClient (Es werden durch Befehle des ArduinoSerielVirtualWireServer 2 lokale Relais geschaltet)

#include <VirtualWire.h>
int RELAIS_1 = 7;
int RELAIS_2 = 8;
String msg;
char buf[4];

void switchRelais() {
  //Empfangen und Ausführen der Schaltbefehle
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;

  if (vw_get_message(buf, &buflen)) { // Non-blocking
    int i;
    digitalWrite(13, true); // Flash a light to show received good message
    // Message with a good checksum received, dump it.
    Serial.print("Got: ");

    for (i = 0; i < buflen; i++) {
      Serial.print(char(buf[i]));
      msg += char(buf[i]);
    }
    Serial.println("");
    digitalWrite(13, false);

    if (msg.indexOf("relay1") >=0) {
      if (msg.indexOf("on") >=0) {
        digitalWrite(RELAIS_1, HIGH); // RELAIS anschalten
        Serial.println( "Relais 1 wurde angeschaltet." );
      } else {
        digitalWrite(RELAIS_1, LOW); // RELAIS ausschalten
        Serial.println( "Relais 1 wurde ausgeschaltet." );
      }
    }

    if (msg.indexOf("relay2") >=0) {
      if (msg.indexOf("on") >=0) {
        digitalWrite(RELAIS_2, HIGH); // RELAIS anschalten
        Serial.println( "Relais 2 wurde angeschaltet." );
      } else {
        digitalWrite(RELAIS_2, LOW); // RELAIS ausschalten
        Serial.println( "Relais 2 wurde ausgeschaltet." );
      }
    }
    msg = "";
  }
}

void setup() {
  Serial.begin(9600); // Debugging only
  Serial.println("setup");

  // Initialise the IO and ISR
  vw_set_ptt_inverted(true); // Required for DR3100
  vw_set_tx_pin(4); //transmitter
  vw_set_rx_pin(2); //receiver
  vw_setup(2000); // Bits per sec
  vw_rx_start();       // Start the receiver PLL running

  for (int thisPin = 7; thisPin < 9; thisPin++) {
    pinMode(thisPin, OUTPUT);
  }
//  analogReference(DEFAULT); // nicht relevant
}

void loop() {
  //Empfangen und Ausführen der Schaltbefehle
  switchRelais();
}



Wenn ich den nächsten Schritt (Analoge Signale vom Arduino(Client) an den Arduino(Server) senden und im FHEM anzeigen) umgesetzt hab, werde ich auch diese Erkenntnisse hier preisgeben! 
Es wundert mich ein wenig, dass das Interesse an so einer Lösung so gering zu sein scheint.

Ich hab mal einen eigenen Thread aufgemacht und werde dort weiter dokumentieren!
Einbinden von Arduino's in FHEM als Sateliten via USB und 433MHz

Gruß
Christian