I2C Expander PCF8574

Hardware

Beschreibung

Der PCF8574 ist ein 8-Bit Expander mit I2C-Bus. Übersetzt heißt das, über den I2C-Bus kann ich 8 Pins setzen oder lesen. Die 8 Pins sind Open-Collektor, die wahlweise als Ein- oder Ausgang geschalten werden können. Sollte der Pin als Eingang genutzt werden, muss ein sogenannter Pull-Up-Widerstand gegen UCC (Betriebsspannung) geschalten werden, damit dieser einen logischen (High) Pegel hat.

Die 8 Pins können nur gleichzeitig als ein Byte gelesen bzw. geschrieben werden. Gegebenenfalls muss man erst den Ist-Stand lesen und dann das eine Bit dazu addieren oder wegnehmen um wirklich nur das eine Bit zu modizifieren.

Adressierung des Expanders

Jumper A0-A2 dienen zur Adressierung des Expanders. Es gilt

0x40 + A[2:0]*2 + R(ead)\W(rite)-Bit.

Tools lassen das R\W-Bit bei der Adressierung weg. Es gilt dann bitweise
0 1 0 0 A2 A1 A0, somit als Basisadresse in Hexidezimal 0x20
D.h. je nach Jumper sollten die I2C im Adressraum 0x20-0x27 ansprechbar sein.

Mit 3 Jumper lassen sich also maximal 2^3 = 8 Expander an einem I2C-Bus einsetzen. Aber es gibt ähnliche Expander, wo nur der Adressraum anders liegt.

So gilt z.B. für den PCF8574A gilt folgende Adressierung


Peripherie am Expander

Ich bin kein Elektroniker. Daher sind die Einstellungen nur Erfahrungswerte, wie die Hardware bei mir funktionierte. Es gibt sicher tolle Formeln, allerdings liegen mir ja nicht mal alle Datenblätter zu den einzelnen Modulen vor.

Ich nutzte bisher folgende Pull-Up-Widerstände als Eingang von folgenden Sensoren

Bei der Nutzung als Ausgang fand ich folgendes im Internet Typ Open Collector sind und nur bei LOW große Ströme schalten können. D.h. ein Ausgang zur LED sollte mit Vorwiderstand (bei mir 220 Ohm) gegen die Betriebspannung geschalten werden. Dadurch ist der Pegel negiert zu betrachten. Sprich geschaltenes "On" schaltet die LED aus und umgekehrt.

Anschluss an den Raspberry Pi


PIN 3 = SDA1 (Daten)
PIN 5 = SCL1 (Clock)

Einfach an den Expander anschließen. UCC des Expanders zum 5Volt UCC vom Raspberry Pi

Aktivieren unter dem Raspberry

Die Module i2c-bcm2708 und spi-bcm2708 müssen aus der Ausschluss-Liste entfernt werden.

Dazu muss man in der Datei /etc/modprobe.d/raspi-blacklist.conf die entsprechenden Einträge auskommentieren.

in der Kommandozeile unter Linux als Root angemeldet.

  1. modprobe i2c-bcm2708
  2. modprobe i2c-dev
  3. apt-get install i2c-tools

optional kann die Baudrate angegeben werden. Der I2C läuft maximal bis 400kHz, bei 30 Metern Kabellänge sollte man aber eher runtertakten. Hier im Beispiel auf 20 KHz

  1. modprobe i2c-bcm2708 baudrate=20000

Wenn alle Jumper default gelassen wurden, dann sollte das hier die Belegung der Ein/Ausgänge zeigen.
Die 1 beim Aufruf von i2cdetect -y 1 ist in dem Fall der Adressbus.
(Bei anderen Versionen des Raspberry PI kann es durchaus ein anderer sein.)
Im Ergebniss sieht man, dass ein I2C-Expander unter Port 0x20 gefunden wurde.

Einbindung in Hausautomatisierungs-Software "Fhem"

Der Expander hat einen Interrupt-Pin. Dieser wird geschalten, sofern sich an einen der 8 Pins etwas tut. Wenn man das Interrupt-Signal auf eine GPIO-Pin des Raspberry Pi legt, könnte man also direkt auf eine Änderung reagieren.

Theoretisch habe ich 8 Kanäle im Kabel, allerdings nutze ich diese als 4x2, um den Kabelwiderstand so gering wie möglich zu halten. Außerdem benötige ich ohnehin schon sehr viele GPIOs vom Raspberry für die weitere Haus-Steuerung, so dass jeder GPIO wertvoll ist.

So habe ich mich auf die weniger elegante Methode des Pollings entschieden. Sprich das Signal wird aller Sekunden abgefragt. Bei 20.000 KHz Takt dürfte das zu verkraften sein.

# setze Bus auf 1 define raspBerryBus RPII2C 1 # setze den entsprechenden (in dem Beispiel den Expander in der Küche) PCF8574 auf Adresse 0x20 define kuecheExpander I2C_PCF8574 0x20 # teile dem PCF8574 den Bus mit attr kuecheExpander IODev raspBerryBus # Eingabe-Ports definieren, dadurch erscheinen Änderungen am Port auch im Logfile attr kuecheExpander InputPorts 7 6 5 # setze Polling auf 0.02 Minuten (ca. aller 1,2 Sekunden), attr kuecheExpander poll_interval 0.02 # nur Event wenn sich auch der Status, Port7, Port6, Port5 sich wirklich ändern
# sonst hätten wir durch das Polling alle Sekunden einen neuen Eintrag attr kuecheExpander event-on-change-reading state,Port7,Port6,Port5 # hier Beispiele wie Logfiles aussehen könnten define FileLog_kuecheExpander FileLog ./log/kuecheExpander-%Y.log kuecheExpander
define FileLog_LichtKueche FileLog ./log/LichtKueche-%Y.log kuecheExpander.*:Port7.*
# hier wie ich die LED am Port0 anschalte set KuecheExpander Port0 off # hier wie ich die LED am Port0 abschalte set KuecheExpander Port0 on # prüfe ob der Lichtsensor angeschalten ist ReadingsVal("KuecheExpander","Port6","") eq "off"
Artikel von Karsten Grüttner, letzte Änderung 6.10.2015