Einbinden von Arduino's in FHEM als Satelliten via USB, Ethernet und 433MHz

Begonnen von linusd, 14 November 2014, 12:54:35

Vorheriges Thema - Nächstes Thema

linusd

Hallo zusammen,

wer wie ich auch auf der Suche nach einer kostengünstige und hochflexiblen Lösung für die Hausautomation ist, sollte weiter lesen! 8)
Bei kostengünstigen Sensoren und Aktoren bin ich unweigerlich bei kabel-gebundenen Komponenten für den Arduino (aus Fernost) gelandet.
Nun wollte ich nicht einen Kabelbaum durchs ganze Haus zur Zentrale (raspberry pi mit , wie sollte es auch anders sein, FHEM) legen.

Da ich Netzwerk "fast" in jeden Raum (aber leider nicht immer an der richtigen Stelle) zur Verfügung habe,
dachte zunächst ich mit einem Bus z.B. I²C und einer selbst gebauten Platine mit dem IC MCP23017 sowie dem FHEM-Modul vom Klaus ans Ziel zu kommen.
Wie ich jedoch hier festgehalten habe, bin ich dann aus Kosten-/Nutzen-gründen zu der Möglichkeit tendiert mit dem Rasperry Pi und dem Modul FHEM2FHEM Satelliten zu verteilen.

Als ich jedoch auf die Lösung mit Arduino's als Satelliten aufmerksam geworden bin, der zugleich ein AD-Wandler darstellt, habe ich meine Ausrichtung erneut geändert.  8) (Ein Arduino-Nano derivat kostet ca. 5€ in der Bucht)

Neben dem RPI können sich selbstverständlich auch die Arduino's, mit Funk-Sender und Funk-Empfänger ausgestattet, unterhalten.
Damit aber der RPI nicht in Vollast gehen muss um nix zu verpassen, werde ich einen Arduino(als Funk-Server) via USB oder Ethernet am RPI(mit FHEM) anschliessen.
Dieser informiert den RPI dann über Neuigkeiten von den Satelliten-Arduino's(Client) wenn diese eintreffen und übermittelt Befehle an die Satelliten-Arduino's(Funk-Client).
Eine direkte Kopplung des Client am RPI via Ethernet ist natürlich möglich und wird von mir bzgl. Einsatzmöglichkeit in meinem Projekt überprüft.

In so einer Lösung können die Sensorwerte auf den Satelliten-Arduino's(Client) bereits aufbereitet, vor Ort (dezentrale Teil-Logik) verwendet und nur das wesentliche an die Zetrale gesendet werden.
Je nachdem wie man es aufbaut, kann dann selbstverständlich die dezentrale Teil-Logik durch Kommandos aus dem FHEM beeinflusst werden.

Für die "Grundlagenforschung" eingesetzte Hardware:

  • Raspberry Pi
  • Arduino MEGA (geht aber auch mit einem NANO)
  • Arduino NANO
  • MiNi ENC28J60 Ethernet Modul
  • W5100 Ethernet-Shield
  • 2x 433MHz Receiver & Transmitter
  • 2x 2 Kanal 5V Relais
  • 2x Lichtsensoren

Als ich dieses Thema mit Erreichen der Phase 1erstellt habe, dachte ich das ich den Weg mit ECMD gehen würde.
Nachdem ich jedoch bereits am selben Abend  :D die Phase 2 mit ConfigurableFirmate erreicht hatte, war klar das es nur mit Firmata weiter gehen wird!
(Im Zuge dessen habe ich meine Planung bzgl. der Ausbaustufen den Text und Titel am 19.11.2014 überarbeitet)
 
An die Lösung werde ich mich in folgenden Schritten herantasten: ;)

Phase 1: (Lösung mit ECMD in Beitrag 1)
Aufbau einer Kommunikationsstecke zum Schalten von Aktoren am Satelliten via USB und 433MHz:
RPI(FHEM) =USB=> Arduino(Server) -433MHz-> Arduino(Client)
                                               |                                                  |
                                               ->Aktoren(Relais)                    ->Aktoren(Relais)

Phase 2: (Lösung mit Firmata! - Nach einer Aufbereitung folgt die Doku)
Ausbau der Kommunikationsstecke zum übermitteln von Sensorwerten an das FHEM und zum Schalten von Aktoren via USB und 433MHz:
RPI(FHEM) <=USB=> Arduino(Server) <-433MHz-> Arduino(Client)
                                               |                                                  |
                                                <-Sensor(Lichtsensor)           <-Sensor(Lichsensor)
                                               ->Aktoren(Relais)                    ->Aktoren(Relais)

Phase 3:
Ausbau der Kommunikationsstecke zum übermitteln von Sensorwerten an das FHEM und zum Schalten von Aktoren via Ethernet und 433MHz:
RPI(FHEM) <=Ethernet=> Arduino(Server) <-433MHz-> Arduino(Client)
                                                      |                                                  |
                                                      <-Sensor(Lichtsensor)           <-Sensor(Lichsensor)
                                                      ->Aktoren(Relais)                    ->Aktoren(Relais)

Phase 4:
Ausbau der Kommunikationsstecke zum übermitteln von Sensorwerten an das FHEM und zum Schalten von Aktoren via Ethernet und 433MHz:
RPI(FHEM) <=Ethernet=> Arduino(Server) <-433MHz-> Arduino(Client)
                                ||                    |                                                  |
                                ||                    <-Sensor(Lichtsensor)           <-Sensor(Lichsensor)
                                ||                    ->Aktoren(Relais)                    ->Aktoren(Relais)
                                ||
                                ======>Arduino(Client)
                                                      |
                                                      <-Sensor(Lichtsensor)
                                                      ->Aktoren(Relais)

Phase 5:
Produktiver Einsatz!!!!!!! :D :D :D :D

Über einen Gedanken- und Erfahrungsaustausch freue ich mich natürlich immer! 

Gruß
Christian

linusd

Phase 1
Aufbau einer Kommunikationsstecke zum Schalten von Aktoren am Sateliten:
RPI(FHEM) -USB-> Arduino(Server) -433MHz-> Arduino(Client)
                                      |                                                            |
                                     ->Aktoren(Relais)                             ->Aktoren(Relais)


Zur Kommunikation zwischen den FHEM und dem Arduino(Sever) wird ECMD und zwischen den Arduino's die Library VirtualWire eingesetzt.

In meinem Besipiel habe ich folgende Classdef (/opt/fhem/FHEM/ECMD_Arduino.classdef) für das ECMD-Device angelegt.

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 Relay1Remote ECMDDevice FSD 110000
attr Relay1Remote IODev ARDUINOserial
attr Relay1Remote group Arduino_serial
attr Relay1Remote room Labor
attr Relay1Remote webCmd on:off
set Relay1Remote off

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

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

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


An den Arduino werden Kommandos mit folgendem Aufbau gesendet.

Einschalten vom Relay2Lokal
b001012100010
Ausschalten vom Relay2Lokal
b001012100001

Diese Kommandos werden in der Verarbeitung wie folgt aufgeschlüsselt
k.a.  ::) | ECMDDevice (hier Relay2Lokal) | Befehl wobei von mir zunächst nur die erste Zahl verwendet wird  ;) 
b0010  | 121000                                               | 01


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



Gruß
Christian

NietGiftig

Sehr interessant, haben ähnliche Pläne.
Müssen nur herausfinden, wie FHEM über die serielle Verbindung mit einem Arduino (jeenode) kommunizieren können in beiden Richtungen.
Aber Ihre Beispiele helfen dabei
Ich benutze Jeenodes mit benutzerdefinierte Kommandos, nicht die ich sehe in FHEM (PCA301, Lacrosse uzw)
Die Tutorials sind überwiegend deutsch, und das ist nicht meine Sprache (Hollands)
Plane auch eine eigene Kommandostruktur erstellen
Übersetzt mit Google;)

linusd

Hallo NietGiftig,

das Modul sieht interessant aus.
Wieviel Speicher steht auf dem Gerät zur Verfügung?
Jenachdem wieviel Platz auf dem jeenode zur Verfügung steht,
könnte eine Verbindung aus FIRMATA und VirtualWire auch für Dich hilfreich sein.
Im ersten Ansatz habe ich diese in Phase2 beschriebene Kommunikation realisiert.

Sobald meine Prototypen einen stabilen Status erreichen, werde ich sie hier bereitstellen.
Gerne kannst Du auch Deine Ansätze/Realisierungen hier posten.

Gruß
Christian

psch

Hallo Christian,

wie hast Du die Lösung mit Firmata realisiert? Insbesondere würde mich interessieren, wie Du die gewünschten Befehle an den Client weiterleitest. Schaltest Du mit "nur" Pins am Server ein und aus (FRM_OUT), oder überträgst Du eine Befehlsfolge?

Gruß,
Peter

linusd

Hallo Peter,

leider sind mir ein paar andere Projekt und die liebe Arbeit dazwischen gekommen, so dass ich mich erst wieder einarbeiten muss. ::)
Da ich dass aber eh vor hatte werde ich hier in ein paar Tagen/Wochen eine konkrete Beschreibung posten.

Gruß
Chtistian

pula

Hallo,

das wäre im Prinzip auch genau das, was ich suche:

Arduino (server mit ether-shield) <---> x-arduino-clients (mit 1wire, relais, diversen sensoren)....

Hat sich hier wieder was getan? Meine Kenntnisse sind leider _noch_ eher bescheiden, aber ich werde mal versuchen, mich einzulesen.

Cheers,

Pula
fhem (debian auf proxmox), HM-LAN und wired, MySensors, FritzBoxes, Kodi, vdr, Onkyo, squeezeplayers, nanoCUL, wifilight (Ethernet-Bridge), Heizungssteuerung (python/vncdotool), doorpi, ESP/Arduinos/MQTT, Alexa, HomeConnect, Sonoff/Tasmota, espRGBWW, esphome, Telegram

Nepumuk4321

Hallo,

ich habe die Lösung so ähnlich umgesetzt. Sie funktioniert auch, so dass ich an beliebigen Clients Schaltaktionen aufgrund der Befehle ausführen kann. Damit bin ich auch schon "halb glücklich".
Was aber mein größtes Problem ist (auch und besonders weil ich perl nicht wirklich beherrsche), ist der Weg zurück in Fhem.
Das bedeutet, ich würde gerne den Status der Relais an Fhem senden und dort als reading anzeigen.
Außerdem möchte ich auch an den Clients Eingänge einlesen und an fhem schicken.
Auf der Arduino Seite ist das kein Problem. Aber:

1. Wie muss die classdef und ggf. die Fhem.cfg aussehen um den Zustand der Relais (reading) auszuwerten?
2. Welchen String muss ich über die serielle Schnittstelle schicken, dass Fhem es als reading auswertet.
3. Wie muss die classdef und Fhem.cfg für einen Eingang aussehen und welcher String wird dann von Fhem erwartet.

Ich wäre  sehr froh, wenn jemand das halbwegs verständlich beantworten könnte.
Ich will mich zwar noch in perl einarbeiten, aber um die Module zu verstehen, wird's wohl noch einige Zeit dauern. Ich wäre froh, wenn ich an dieser Stelle schneller weiter kommen würde.

Gruß
Frank
FHEM@RPI2, HMUSB; Keymatic;Thermostate (HM-CC-RT-DN); Rolladenaktoren(HM-LC-BI1PBU-FM); 2xConfig-Firmata@ArduinoUno mit Relaisausgängen und DS18B20;Schaltaktor(HM-LC-SW1-BA-PCB); Rauchmelder(HM-SEC-SD); ArduinoNano+ nRF24L01 MySensors;   FHEM@RPI1 als Teststation mit RF1101se@ArduinoNano.....

Kuzl

Hallo,

ich bin mir nicht ganz sicher, aber ist das ganze nicht genau das gleiche wie mysensors, nur mit anderen Funkmodulen?

Gruß
Kuzl

Nepumuk4321

Das sagt mir jetzt nicht viel.
Ich hab auf der Suche nach einer Lösung viele Posts gelesen und den Eindruck, dass genau das, also wie rein in oder raus aus FHEM für die meisten das größte Problem ist.
Durch das einfache Beispiel oben in diesem Thread ist raus aus FHEM hier kein Problem. Bräuchte wie gesagt jetzt noch ein Beispiel, wie ich hinein komme.


Gruß
Frank
FHEM@RPI2, HMUSB; Keymatic;Thermostate (HM-CC-RT-DN); Rolladenaktoren(HM-LC-BI1PBU-FM); 2xConfig-Firmata@ArduinoUno mit Relaisausgängen und DS18B20;Schaltaktor(HM-LC-SW1-BA-PCB); Rauchmelder(HM-SEC-SD); ArduinoNano+ nRF24L01 MySensors;   FHEM@RPI1 als Teststation mit RF1101se@ArduinoNano.....

Kuzl

Wenn dus nicht kennst, schaus dir an: mysensors.org
Da kannst du alles mögliche an Sensoren einbinden, ist extrem sparsam und schon fertig in FHEM eingebunden (bidirektional).
Das Gateway für FHEM kannst du entweder per LAN/USB oder auch direkt auf einem ESP8266 über Wifi laufen lassen.

Gruß
Kuzl

Nepumuk4321

Habe es mir angeschaut. Sieht echt sehr vielversprechend aus. Ich hab mir gleich mal 3 Stück NRF24L01 zum Testen bestellt. Arduinos, Ethernetshield und Esp's hab ich eh noch genügend hier rumliegen.
Wenn das so klappt, wie es aussieht, wäre es genau das, was ich suche.
Danke für den Tip!


Gruß
Frank
FHEM@RPI2, HMUSB; Keymatic;Thermostate (HM-CC-RT-DN); Rolladenaktoren(HM-LC-BI1PBU-FM); 2xConfig-Firmata@ArduinoUno mit Relaisausgängen und DS18B20;Schaltaktor(HM-LC-SW1-BA-PCB); Rauchmelder(HM-SEC-SD); ArduinoNano+ nRF24L01 MySensors;   FHEM@RPI1 als Teststation mit RF1101se@ArduinoNano.....

linusd

Ein riesen Dank an Kuzl für den Tipp mit  mysensor!

Damit sind die von mir angepeilten Funktionen und weit darüber hinaus perfekt umgesetzt worden!
Erste Tests mit Sensoren (Licht, Bewegung, Gyroscope) und Aktoren (2 fach Relay) an einem Nano (als Node) sind extrem vielersprechend! :)

Da ich mittlerweile wieder Zeit hierfür habe und vor allen Dingen, dank c keine "Grundlagenforschung" betreiben muss kann es an die Realisierung gehen! 8)

Sobald die bestellen Komponenten eintreffen, kann ich endlich die schon fast eingestaubten Komponenten (Reed-Kontakte, Relays, Gyroscope, Lichtsensoren, ...) ihrem Einsatz zuführen.   :D :D :D :D

Die Umsetzung werde ich dann hier einstellen.
(Wird aber sich er erst Ende Q2, Anfang Q3 2016 - also diesen Jahres   8) - bis repräsentable Ergebnisse da sind)

Ich kann es nicht oft genug sagen!
DANKE Kunzl und den Jungs von  mysensor! :D

Nepumuk4321

Ich war anfangs auch begeistert, bis ich feststellen musste , dass die Verschlüsselung in MySensors  noch  in den Kinderschuhen steckt. Ohne Verschlüsselung kann halt jeder mitlesen oder Aktoren steuern. Zudem ist es nicht Übertragungs-sicher. Es werden auch schon mal Telegramme verschluckt. Ich mache deshalb mit Esp8266 und Httpmod weiter.

Gruß
Frank



Gesendet von iPad mit Tapatalk
FHEM@RPI2, HMUSB; Keymatic;Thermostate (HM-CC-RT-DN); Rolladenaktoren(HM-LC-BI1PBU-FM); 2xConfig-Firmata@ArduinoUno mit Relaisausgängen und DS18B20;Schaltaktor(HM-LC-SW1-BA-PCB); Rauchmelder(HM-SEC-SD); ArduinoNano+ nRF24L01 MySensors;   FHEM@RPI1 als Teststation mit RF1101se@ArduinoNano.....