PCF8574 – Gesamtdokumentation
Technische Grundlagen, Modulanschluss, MicroPython, Belastbarkeit, Eingänge, LED-Matrix, Treiber und Vergleich zum PCF8575
8-Bit-I/O-Erweiterung I²C MicroPython ESP32 / ESP8266 LED-Matrix1. Überblick
Der PCF8574 erweitert einen Mikrocontroller über den I²C-Bus um acht digitale Ein-/Ausgänge P0 bis P7. Für die Kommunikation werden nur die beiden Busleitungen SDA und SCL benötigt.
Typische Anwendungen sind Taster, Statussignale, LEDs mit geeigneter Beschaltung, Relais- oder Transistortreiber, LCD-Adapter und einfache Unterrichtsmodelle.
2. Das verwendete PCF8574-Modul
Das gezeigte blaue Breakout-Modul besitzt gewöhnlich:
- zwei parallele Anschlussgruppen mit VCC, GND, SDA und SCL zum einfachen Durchschleifen des I²C-Busses,
- eine Stiftleiste für P0 bis P7,
- drei Adressbrücken oder Jumper A0, A1 und A2,
- teilweise einen herausgeführten INT-Anschluss.
3. I²C, Adressen und Signalpegel
3.1 Adressierung
| Baustein | 7-Bit-Adressbereich |
|---|---|
| PCF8574 | 0x20 bis 0x27 |
| PCF8574A | 0x38 bis 0x3F |
Die unteren drei Adressbits werden über A0, A1 und A2 eingestellt. Die tatsächliche Adresse sollte immer mit i2c.scan() geprüft werden.
3.2 SDA- und SCL-Pegel
SDA und SCL sind Open-Drain-Leitungen. Die Teilnehmer ziehen die Leitungen nur aktiv auf LOW. Der HIGH-Pegel entsteht durch Pull-up-Widerstände.
Auf vielen Modulen liegen die I²C-Pull-ups an der Modulversorgung VCC. Dann hängt der HIGH-Pegel tatsächlich von der Versorgungsspannung des Moduls ab.
3.3 Übliche I²C-Pins
| Controller | SDA | SCL |
|---|---|---|
| ESP8266 NodeMCU / D1 mini | GPIO4 / D2 | GPIO5 / D1 |
| ESP32, häufige Standardbelegung | GPIO21 | GPIO22 |
4. Quasi-bidirektionale Ein-/Ausgänge
Der PCF8574 besitzt kein Richtungsregister. Ein Pin wird nicht mit INPUT oder OUTPUT konfiguriert. Stattdessen bestimmt das geschriebene Bit das Verhalten:
| Geschriebenes Bit | Verhalten des Ports |
|---|---|
0 | Der Port zieht aktiv nach GND: kräftiger LOW-Ausgang. |
1 | Der LOW-Transistor wird abgeschaltet; eine schwache interne Stromquelle hält den Pin HIGH. Der Pin kann nun als Eingang gelesen oder extern auf LOW gezogen werden. |
Nach dem Einschalten stehen alle Ports auf HIGH und sind damit grundsätzlich als Eingänge nutzbar.
5. Belastbarkeit der Ausgänge
Der PCF8574 kann Strom wesentlich besser nach GND aufnehmen als nach VCC liefern. Das macht ihn für aktive-LOW-Schaltungen besonders geeignet.
| Betriebsart | Praxisbedeutung |
|---|---|
| LOW / Strom aufnehmen | Geeignet für kleine LED-Ströme und Logikeingänge. Der garantierte LOW-Pegel hängt von Versorgung, Strom und Herstellerdatenblatt ab. |
| HIGH / Strom liefern | Im statischen Zustand nur über eine schwache interne Stromquelle, typischerweise in der Größenordnung von etwa 100 µA. Nicht als kräftige Versorgung einer Last verwenden. |
Für LEDs ist diese Stromrichtung günstig:
Ungünstig ist dagegen, eine LED vom PCF8574-Ausgang nach GND zu speisen, weil der Port dabei den HIGH-Strom liefern müsste.
6. Interne Pull-ups und Pull-downs
Der PCF8574 besitzt keine frei konfigurierbaren Pull-up- oder Pull-down-Widerstände wie ein ESP32.
- Kein
Pin.PULL_UP. - Kein
Pin.PULL_DOWN. - Kein einstellbarer Widerstandswert.
- Bei einer geschriebenen 1 wirkt die schwache interne Stromquelle nach VCC.
Ein Taster wird daher am einfachsten zwischen Port und GND geschaltet:
Bei langen Leitungen oder störbehafteter Umgebung kann ein externer Pull-up, beispielsweise 4,7 kΩ bis 10 kΩ, sinnvoll sein.
7. MicroPython-Grundlagen
7.1 I²C-Scan
from machine import Pin, I2C
# ESP32
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)
print([hex(adresse) for adresse in i2c.scan()])
7.2 Ein Byte schreiben
PCF_ADDR = 0x20
i2c.writeto(PCF_ADDR, bytes([0b1010_0101]))
7.3 Ein Byte lesen: Unterschied mit und ohne [0]
daten = i2c.readfrom(PCF_ADDR, 1)
# Ergebnis: bytes-Objekt, zum Beispiel b'\xff'
wert = i2c.readfrom(PCF_ADDR, 1)[0]
# Ergebnis: Ganzzahl, zum Beispiel 255
Das [0] wählt das erste Byte des zurückgegebenen bytes-Objekts aus. Dadurch lässt sich direkt mit Bitoperationen arbeiten.
7.4 Binärzahlen in Python
wert = 0b0101_1010
print(wert) # 90
print(bin(wert)) # 0b1011010
Für eine immer achtstellige Ausgabe, auch auf MicroPython-Versionen mit eingeschränkter Formatunterstützung:
print("OUT = 0b" + bin(wert)[2:].rjust(8, "0"))
8. Kleines MicroPython-Treibermodul pcf8574.py
class PCF8574:
def __init__(self, i2c, addr=0x20):
self.i2c = i2c
self.addr = addr
self._state = 0xFF
self._write_byte(self._state)
def _check_pin(self, pin):
if pin < 0 or pin > 7:
raise ValueError("pin muss zwischen 0 und 7 liegen")
def _write_byte(self, value):
self._state = value & 0xFF
self.i2c.writeto(self.addr, bytes([self._state]))
def _read_byte(self):
return self.i2c.readfrom(self.addr, 1)[0]
def write(self, value):
self._write_byte(value)
def read(self):
return self._read_byte()
def pin_write(self, pin, value):
self._check_pin(pin)
if value:
self._state |= 1 << pin
else:
self._state &= ~(1 << pin)
self._write_byte(self._state)
def pin_read(self, pin):
self._check_pin(pin)
return 1 if self._read_byte() & (1 << pin) else 0
def pin_input(self, pin):
self.pin_write(pin, 1)
def pin_low(self, pin):
self.pin_write(pin, 0)
def pin_high(self, pin):
self.pin_write(pin, 1)
def toggle(self, pin):
self._check_pin(pin)
self._state ^= 1 << pin
self._write_byte(self._state)
_state behalten. Bits, die als Eingang dienen, müssen in diesem Schattenregister auf 1 bleiben.9. Testprogramme
9.1 Lauflicht an den acht Ports
from machine import Pin, I2C
from pcf8574 import PCF8574
import time
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)
adressen = i2c.scan()
if not adressen:
raise RuntimeError("Kein I2C-Gerät gefunden")
pcf = PCF8574(i2c, adressen[0])
while True:
for pin in range(8):
wert = 1 << pin
pcf.write(wert)
print("OUT = 0b" + bin(wert)[2:].rjust(8, "0"))
time.sleep_ms(250)
9.2 Taster an P0
from machine import Pin, I2C
from pcf8574 import PCF8574
import time
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=100000)
pcf = PCF8574(i2c, 0x20)
pcf.pin_input(0)
while True:
if pcf.pin_read(0) == 0:
print("Taster gedrückt")
else:
print("Taster offen")
time.sleep_ms(100)
10. Zwei PCF8574 an einer 8×8-LED-Matrix
Eine naheliegende Aufteilung ist:
Für ein didaktisches Modell ist das sehr anschaulich, weil Bitmuster, Zeilen-/Spaltenauswahl, Stromrichtung und Multiplexing offen sichtbar bleiben.
10.1 Sinnvolle Lernschritte
- Eine einzelne LED schalten.
- Eine vollständige Zeile aktivieren.
- Eine vollständige Spalte aktivieren.
- Zeilen und Spalten kombinieren.
- Einzelne Bildpunkte durch Multiplexing ansteuern.
- Treiberstufen ergänzen.
- Später mit einem integrierten Matrix-Treiber wie MAX7219 vergleichen.
10.2 Grenzen
- I²C-Übertragungen begrenzen die maximale Multiplexrate.
- Die HIGH-Ausgänge des PCF8574 sind sehr schwach.
- Bei mehreren gleichzeitig aktiven LEDs müssen Einzel- und Gesamtstrom beachtet werden.
- Für höhere Helligkeit oder Dauerbetrieb sind externe Treiber sinnvoll.
11. Treiber- und Pufferbausteine
11.1 ULN2803A
Der ULN2803A enthält acht Darlington-Treiber mit Open-Collector-Ausgängen. Er kann Lasten nur nach GND ziehen.
Er liefert keinen aktiven HIGH-Pegel. Für Kathoden oder die Low-Side einer Matrix ist er gut geeignet. Der COM-Pin gehört bei induktiven Lasten an die positive Lastversorgung, damit die integrierten Freilaufdioden wirken; bei reinen LEDs kann COM offen bleiben.
11.2 74HC240 und 74HC540
Beide Bausteine sind achtfach invertierende Puffer mit Tri-State-Ausgängen. Sie können aktiv HIGH und LOW ausgeben und sind daher für kleine LED-Ströme und zur Pegelinvertierung geeignet.
| Merkmal | 74HC240 | 74HC540 |
|---|---|---|
| Funktion | 8 invertierende Puffer | 8 invertierende Puffer |
| Ausgänge | Tri-State | Tri-State |
| Enable | zwei aktive-LOW-Gruppeneingänge | zwei aktive-LOW-Gruppeneingänge |
| Hauptunterschied | andere Pinanordnung | andere Pinanordnung |
Für dauerhaft aktive Ausgänge werden die beiden /OE-Eingänge auf GND gelegt.
Bei etwa 5 mA pro Kanal kann ein HC-Puffer in einem kleinen Unterrichtsmodell grundsätzlich funktionieren. Trotzdem müssen Datenblatt, Gesamtstrom und zulässiger Spannungsabfall geprüft werden. Acht Kanäle mit je 5 mA bedeuten bereits 40 mA Gesamtlast.
11.3 High-Side-Treiber
Wer deutlich mehr Strom aktiv nach VCC liefern möchte, benötigt eine High-Side-Stufe, beispielsweise PNP-Transistoren, P-Kanal-MOSFETs oder einen Source-Treiber wie TBD62783/UDN2981.
12. Mehrere 28BYJ-48 über ULN2003
Jeder 28BYJ-48 benötigt über seine ULN2003-Platine vier Steuersignale. Drei Motoren benötigen daher zwölf Ausgänge. Ein einzelner PCF8574 reicht nicht; mindestens zwei Module oder ein PCF8575 sind nötig.
| Modul | Belegung |
|---|---|
| PCF8574 Nr. 1 | P0–P3 Motor 1, P4–P7 Motor 2 |
| PCF8574 Nr. 2 | P0–P3 Motor 3 |
Die Motorversorgung muss extern erfolgen. ESP, PCF8574, ULN2003-Platinen und Netzteil benötigen eine gemeinsame Masse.
pin_write()-Aufrufe erzeugt mehrere I²C-Übertragungen pro Halbschritt und ist unnötig langsam. Besser ist es, das vollständige Portbyte zu berechnen und mit genau einer I²C-Übertragung zu schreiben.12.1 Positionsverwaltung
Der 28BYJ-48 besitzt in der üblichen Ausführung keine Positionsrückmeldung. Das Programm kann lediglich die ausgegebenen Schritte zählen:
self.position = 0
def step(self, richtung=1):
self.position += richtung
# anschließend neues Spulenmuster ausgeben
Dieser Softwarezähler ist nur dann korrekt, wenn der Motor keine Schritte verliert. Nach Neustart, Blockieren oder manuellem Verdrehen stimmt die angenommene Position nicht mehr. Eine zuverlässige Maschine benötigt eine Referenzfahrt mit Endschalter oder Sensor; alternativ einen Encoder.
13. Vergleich mit dem PCF8575
Der PCF8575 arbeitet nach demselben Grundprinzip, bietet aber 16 statt 8 quasi-bidirektionale Ports.
| Eigenschaft | PCF8574 | PCF8575 |
|---|---|---|
| Portanzahl | 8 | 16 |
| Datenbreite je Übertragung | 1 Byte | 2 Byte |
| Richtungsregister | nein | nein |
| Konfigurierbare Pull-ups/-downs | nein | nein |
| Portprinzip | quasi-bidirektional | quasi-bidirektional |
13.1 16 Bit schreiben und lesen
# Schreiben, Low-Byte zuerst
i2c.writeto(PCF_ADDR, bytes([
wert & 0xFF,
(wert >> 8) & 0xFF
]))
# Lesen
daten = i2c.readfrom(PCF_ADDR, 2)
wert = daten[0] | (daten[1] << 8)
Auch beim PCF8575 gilt: Zum Lesen eines Pins muss das zugehörige Ausgangsbit vorher auf 1 gesetzt werden.
14. Typische Fehler und Missverständnisse
| Fehlerbild | Wahrscheinliche Ursache | Abhilfe |
|---|---|---|
i2c.scan() liefert nichts | Verdrahtung, Versorgung, SDA/SCL vertauscht oder falsche Pins | VCC/GND prüfen, Busleitungen messen, korrekte Controllerpins verwenden |
| Falsche Adresse | A0–A2 anders gesetzt oder PCF8574A statt PCF8574 | Adresse scannen; Bereiche 0x20–0x27 bzw. 0x38–0x3F prüfen |
| ESP wird mit 5 V belastet | Modul-Pull-ups liegen an 5 V | Modul mit 3,3 V betreiben, Pull-ups ändern oder Pegelwandler einsetzen |
| Eingang bleibt LOW | Vor dem Lesen wurde eine 0 geschrieben | Bit zuerst auf 1 setzen |
| LED an HIGH-Ausgang bleibt dunkel | PCF8574 kann HIGH nur schwach halten | LED gegen VCC schalten und Strom nach LOW aufnehmen oder Puffer einsetzen |
| Binärausgabe verursacht Fehler | Format-Unterstützung der MicroPython-Version eingeschränkt | "0b" + bin(wert)[2:].rjust(8, "0") verwenden |
| Stepper läuft ruckelig | Zu viele einzelne I²C-Schreibvorgänge oder zu hohe Schrittfrequenz | Portbyte gesammelt schreiben, Verzögerung erhöhen, Versorgung prüfen |
15. Verifizierte Datenblattquellen
- Texas Instruments: PCF8574 – Remote 8-Bit I/O Expander for I²C Bus
- NXP: PCF8574 / PCF8574A – Remote 8-bit I/O expander for I²C-bus
- Texas Instruments: PCF8575 – Remote 16-Bit I²C and SMBus I/O Expander
Diese Datei fasst die bisherigen Gespräche zusammen und ordnet sie technisch. Für endgültige Grenzwerte eines konkreten Aufbaus ist immer das Datenblatt des tatsächlich verbauten Herstellers und Bauteiltyps maßgeblich.