8er Relais Board

Mein Ziel: Das 8er Relais Board mit einem MCP 23017 ansteuern und die restlichen GPIOs des MCP 23017 als Input für Taster verwenden.

Achtung: i2c muss konfiguriert sein.

Wichtige Parameter

  • Das Relaisboard benötigt 400mA bei 5V wenn alle gleichzeitig eingeschaltet sind
  • Die Eingänge schalten gemäß folgender Charakteristik
    • 0V..0,5V Low (Relais EIN)
    • 2,5V..5V High (Relais AUS)
    • Benötigter Strom im Low-Zustand je nach Spannung: Bei 2,5V: 0,1mA; 3,3V: 0,18mA; 5V: 0,35mA

Die Verkabelung des MCP 23017 erfolgt prinzipiell gemäß folgendem Schaltplan:

Die einzige Abweichung sind die roten Verbindungen zu den Tastern. Ich verwende die oberen 8 GPIOs (GPA0 bis GPA7) als Eingänge für Taster und die unteren 8 GPIO (GPB0 bis GPB7) als Ausgänge für das Relaisboard.

Gemäß Schaltplan verkabele ich das 8er Relais Board, den MCP 23017 und den Pi folgendermaßen:

Pi Pin Pi MCP 23017 8er Relais Board
01 3,3V RESET, VDD
06 GND A0, A1, A2, VSS
03 SDA SDA
05 SCL SCL
38 GPIO20 INTA
02 5V JDVcc
14 GND GND neben JDVcc
06 GND GND neben In1
17 3,3V Vcc
GPB0..GPB7 In1..In8

Das ganze sieht im Betrieb dann in etwa folgendermaßen aus:

I2C

define i2c RPII2C 1
attr i2c alias Onboard I2C Controller 1
attr i2c room ops

MCP 23017

Device einrichten und testen. Weitere Infos sind auf der Seite mcp23017 zu finden.

MCP23017 Device erzeugen:

define i2c20 I2C_MCP23017 0x20
attr i2c20 IODev i2c
attr i2c20 room ops
attr i2c20 Interrupt A0,A1,A2,A3,A4,A5,A6,A7
attr i2c20 InterruptOut separate_active-low
attr i2c20 Pullup A0,A1,A2,A3,A4,A5,A6,A7
attr i2c20 invert_input A0,A1,A2,A3,A4,A5,A6,A7
attr i2c20 OutputPorts B0,B1,B2,B3,B4,B5,B6,B7
set i2c20 PortB0,PortB1,PortB2,PortB3,PortB4,PortB5,PortB6,PortB7 on # zunächst alle Output-Ports auf "on" setzen damit die angeschlossenen Relais ausgeschaltet sind

Interrupt einrichten:

define int RPI_GPIO 20
attr int direction input
attr int active_low yes
attr int interrupt both
attr int pud_resistor up
attr int userReadings get_i2c20 {fhem ("get i2c20")}

Testen

Input testen (jeder angeschlossene Taster sollte bei Betätigung eine inform-Ausgabe liefern):

inform timer i2c20:PortA.*

Output testen (Port „off“ schaltet das Relais ein!):

set i2c20 PortB0,PortB1,PortB2,PortB3,PortB4,PortB5,PortB6,PortB7 off # Alle Relais einschalten
set i2c20 PortB0,PortB1,PortB2,PortB3,PortB4,PortB5,PortB6,PortB7 on # Alle Relais ausschalten
# Jedes zweite ein- bzw. ausschalten
set i2c20 PortB0,PortB2,PortB4,PortB6 off
set i2c20 PortB1,PortB3,PortB5,PortB7 on
# Jedes zweite ein- bzw. ausschalten
set i2c20 PortB0,PortB2,PortB4,PortB6 on
set i2c20 PortB1,PortB3,PortB5,PortB7 off

Relais über Taster schalten

Ein Taster schaltet ein Relais abwechselnd ein und aus.

Relais

setdefaultattr valueFn {($VALUE eq "on")?"off":"on"}
define relais0 readingsProxy i2c20:PortB0
attr relais0 room ops
attr relais0 devStateIcon on:on:off off:off:on
attr relais0 alias Relais 0 (In1)
attr relais0 setList on off
attr relais0 setFn {($CMD eq "on")?"PortB0 off":"PortB0 on"}
setdefaultattr # delete defaultattr

Ich setze valueFn als Default Attribut damit beim ersten Auslesen des Ports die Funktion sofort verwendet wird. Falls man das nicht macht wird beim ersten Auslesen des Ports der falsche (invertierte) Wert angezeigt.

Taster Dummy

define i2c20pA0 readingsProxy i2c20:PortA0
attr i2c20pA0 room ops
attr i2c20pA0 alias Taster A0
attr i2c20pA0 valueFn { if ($VALUE eq "on") { fhem "set relais0 toggle" } }

Für alle Relais Proxies definieren

Mit folgender kleinen bash-Schleife können die Kommandos zum Erstellen der 8 Relais Proxies generiert werden.

for i in {0..7}; do
echo "
setdefaultattr valueFn {(\$VALUE eq 'on')?'off':'on'}
define relais$i readingsProxy i2c20:PortB$i
attr relais$i room ops
attr relais$i devStateIcon on:on:off off:off:on
attr relais$i alias Relais $i (In$((i+1)))
attr relais$i setList on off
attr relais$i setFn {(\$CMD eq 'on')?'PortB$i off':'PortB$i on'}"
done

Alternativ kann man auch mit einer Perl-Schleife arbeiten (direkt an der telnet-Schnittstelle von fhem eingeben):

{ foreach my $i (0..7) { \
  my $j=$i+1;; \
  fhem(" \
    setdefaultattr valueFn {(\$VALUE eq 'on')?'off':'on'};; \
    define relais$i readingsProxy i2c20:PortB$i;; \
    attr relais$i room ops;; \
    attr relais$i devStateIcon on:on:off off:off:on;; \
    attr relais$i alias Relais $i (In$j);; \
    attr relais$i setList on off;; \
    attr relais$i setFn {(\$CMD eq 'on')?'PortB$i off':'PortB$i on'};; \
");; } }

Eine kleine Schleife zum Löschen aller Relais:

{ foreach my $i (0..7) { fhem("delete relais$i");; } }

Taster mit Zusatzfunktionen

Bei folgendem Taster-Proxy werden die Attribute „laston“ und „lastoff“ auf den jeweils aktuellen Unix Timestamp gesetzt.

define taster readingsProxy i2c20:PortA7
attr taster room ops
attr taster alias Taster A7
attr taster userattr laston lastoff
attr taster valueFn { my $time=time();; if ($VALUE eq "on") { fhem "attr taster laston $time;;setreading taster state on" } else { fhem "attr taster lastoff $time;;setreading taster state off" } }