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-Matrix
Hinweis zu früheren Aussagen: Einige Werte wurden in den Gesprächen bewusst vereinfacht dargestellt. In dieser Zusammenfassung sind die technischen Aussagen präzisiert. Insbesondere ist der PCF8574 kein normaler Push-Pull-Treiber: LOW kann er wesentlich kräftiger treiben als ein dauerhaftes HIGH. Absolute Grenzwerte sind keine empfohlenen Betriebswerte.

1. Ü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.

8I/O-Pins P0–P7
2,5–6 VVersorgungsspannung
100 kHzI²C Standard Mode
0x20–0x27PCF8574-Adressen

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:

Wichtig: Die beiden Gruppen VCC/GND/SDA/SCL sind elektrisch parallel. Es handelt sich nicht um zwei getrennte I²C-Schnittstellen.

3. I²C, Adressen und Signalpegel

3.1 Adressierung

Baustein7-Bit-Adressbereich
PCF85740x20 bis 0x27
PCF8574A0x38 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.

Pull-up nach 3,3 V → SDA/SCL im Ruhezustand etwa 3,3 V Pull-up nach 5,0 V → SDA/SCL im Ruhezustand etwa 5,0 V

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.

ESP32 und ESP8266: Deren GPIOs arbeiten mit 3,3-V-Logik und sind nicht als 5-V-tolerant anzusehen. Wird das Modul mit 5 V versorgt und ziehen seine Widerstände SDA/SCL auf 5 V, ist ein bidirektionaler Pegelwandler oder eine Anpassung der Pull-ups nötig. Die einfache sichere Variante ist der Betrieb des PCF8574-Moduls mit 3,3 V.

3.3 Übliche I²C-Pins

ControllerSDASCL
ESP8266 NodeMCU / D1 miniGPIO4 / D2GPIO5 / D1
ESP32, häufige StandardbelegungGPIO21GPIO22

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 BitVerhalten des Ports
0Der Port zieht aktiv nach GND: kräftiger LOW-Ausgang.
1Der 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.

VCC │ ├── schwache interne Stromquelle │ ●──── P0 … P7 │ └── Schalttransistor nach GND
Merksatz: Zum Lesen zuerst eine 1 schreiben.

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.

BetriebsartPraxisbedeutung
LOW / Strom aufnehmenGeeignet für kleine LED-Ströme und Logikeingänge. Der garantierte LOW-Pegel hängt von Versorgung, Strom und Herstellerdatenblatt ab.
HIGH / Strom liefernIm 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.
Nicht mit dem absoluten Maximum planen. Angaben wie „25 mA pro Pin“ werden häufig als Belastbarkeit missverstanden. Sie sind je nach Datenblatt an bestimmte LOW-Pegel gekoppelt oder absolute Grenzwerte. Für ein robustes Unterrichtsmodell sind wenige Milliampere pro aktivem LOW-Ausgang deutlich sinnvoller. Zusätzlich müssen Gesamtstrom, Verlustleistung und gleichzeitige Belastung aller acht Ports berücksichtigt werden.

Für LEDs ist diese Stromrichtung günstig:

+V ── Vorwiderstand ── LED ── PCF8574-Port │ LOW aktiv

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.

Ein Taster wird daher am einfachsten zwischen Port und GND geschaltet:

PCF8574-Port ── Taster ── GND Taster offen: gelesen wird 1 Taster gedrückt: gelesen wird 0

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)
Wichtig beim gemeinsamen Einsatz von Ein- und Ausgängen: Die Software muss die geschriebenen Zustände in _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:

PCF8574 Nr. 1 → acht Zeilen PCF8574 Nr. 2 → acht Spalten

Für ein didaktisches Modell ist das sehr anschaulich, weil Bitmuster, Zeilen-/Spaltenauswahl, Stromrichtung und Multiplexing offen sichtbar bleiben.

10.1 Sinnvolle Lernschritte

  1. Eine einzelne LED schalten.
  2. Eine vollständige Zeile aktivieren.
  3. Eine vollständige Spalte aktivieren.
  4. Zeilen und Spalten kombinieren.
  5. Einzelne Bildpunkte durch Multiplexing ansteuern.
  6. Treiberstufen ergänzen.
  7. Später mit einem integrierten Matrix-Treiber wie MAX7219 vergleichen.
Didaktischer Kern: Der PCF8574 erzeugt das Bitmuster, die Treiber liefern oder übernehmen den Laststrom, und die Software erzeugt durch schnelles Umschalten das sichtbare Bild.

10.2 Grenzen

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.

Eingang HIGH → Ausgang wird nach GND gezogen Eingang LOW → Ausgang ist hochohmig

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.

Die oft genannten 500 mA pro Kanal sind ein Maximalwert unter Bedingungen. Gesamtstrom und Verlustleistung des Gehäuses begrenzen den tatsächlichen gleichzeitigen Betrieb mehrerer Kanäle.

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.

Merkmal74HC24074HC540
Funktion8 invertierende Puffer8 invertierende Puffer
AusgängeTri-StateTri-State
Enablezwei aktive-LOW-Gruppeneingängezwei aktive-LOW-Gruppeneingänge
Hauptunterschiedandere Pinanordnungandere 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.

Plus-Seite / Anoden: High-Side-Treiber Minus-Seite / Kathoden: ULN2803 oder andere Low-Side-Treiber

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.

ModulBelegung
PCF8574 Nr. 1P0–P3 Motor 1, P4–P7 Motor 2
PCF8574 Nr. 2P0–P3 Motor 3

Die Motorversorgung muss extern erfolgen. ESP, PCF8574, ULN2003-Platinen und Netzteil benötigen eine gemeinsame Masse.

Geschwindigkeit: Ein Schrittmuster über einzelne 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.

EigenschaftPCF8574PCF8575
Portanzahl816
Datenbreite je Übertragung1 Byte2 Byte
Richtungsregisterneinnein
Konfigurierbare Pull-ups/-downsneinnein
Portprinzipquasi-bidirektionalquasi-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

FehlerbildWahrscheinliche UrsacheAbhilfe
i2c.scan() liefert nichtsVerdrahtung, Versorgung, SDA/SCL vertauscht oder falsche PinsVCC/GND prüfen, Busleitungen messen, korrekte Controllerpins verwenden
Falsche AdresseA0–A2 anders gesetzt oder PCF8574A statt PCF8574Adresse scannen; Bereiche 0x20–0x27 bzw. 0x38–0x3F prüfen
ESP wird mit 5 V belastetModul-Pull-ups liegen an 5 VModul mit 3,3 V betreiben, Pull-ups ändern oder Pegelwandler einsetzen
Eingang bleibt LOWVor dem Lesen wurde eine 0 geschriebenBit zuerst auf 1 setzen
LED an HIGH-Ausgang bleibt dunkelPCF8574 kann HIGH nur schwach haltenLED gegen VCC schalten und Strom nach LOW aufnehmen oder Puffer einsetzen
Binärausgabe verursacht FehlerFormat-Unterstützung der MicroPython-Version eingeschränkt"0b" + bin(wert)[2:].rjust(8, "0") verwenden
Stepper läuft ruckeligZu viele einzelne I²C-Schreibvorgänge oder zu hohe SchrittfrequenzPortbyte gesammelt schreiben, Verzögerung erhöhen, Versorgung prüfen

15. Verifizierte Datenblattquellen

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.