Vorbereiten des Raspberry Pi auf I2C

In meinem letzten Artikel habe ich beschrieben, wie herkömmliche Funksteckdosen mit einem Raspberry PI angesteuert werden können. Damit die beschriebene Schaltung auch angesteuert werden kann, sind auf Seite des Raspberry Pi noch ein paar kleine Anpassungen nötig:

Laden der Kernelmodule

Das Kernelmodul, das die I2C Funktionalität des Raspberry Pi zur Verfügung stell, ist standardmäßig deaktiviert. Um I2C nutzen zu können, müssen wir es zunächst aktivieren. Hierzu muss die Datei /etc/modprobe.d/raspi-blacklist.conf bearbeitet werden:

#sudo nano /etc/modprobe.d/raspi-blacklist.conf

Die Zeile

blacklist i2c-bcm2708

wird auskommentiert:

#blacklist i2c-bcm2708

Mit Strg+O wird die Datei danach gespeichert und mit Strg+X der Editor verlassen.

Nur kann das Modul geladen werden:

#modprobe i2c-bcm2708

Zusätzlich benötigen wir das Modul i2c_dev. Auch dieses Modul wird geladen:

#modprobe i2c_dev

Mit dem Befehl lsmod wird nun überprüft, ob beide Module geladen wurden:

#lsmod
Module                  Size  Used by
nfsd                  236425  11
i2c_dev                 5587  20
i2c_bcm2708             3542  0
snd_bcm2835            19889  0
snd_pcm                74834  1 snd_bcm2835
snd_seq                52536  0
snd_timer              19698  2 snd_seq,snd_pcm
snd_seq_device          6300  1 snd_seq
snd                    52489  5 snd_seq_device,snd_timer,snd_seq,snd_pcm,snd_bcm2835
snd_page_alloc          4951  1 snd_pcm

Tauchen beide Module in der Liste auf, hat alles funktioniert. Damit die Module zukünftig bei jedem Systemstart automatisch geladen werden, müssen sie noch in der Datei /etc/modules eingetragen werden.

#sudo nano /etc/modules

snd-bcm2835
i2c-dev

Herstellen der nötigen Verbindungen

Nun kann -falls noch nicht geschehen- die Verbindung des I2C IO-Expanders zum Raspberry Pi hergestellt werden. Verwendet werden hierfür die Pins 2 (+5 Volt), 3 (I2C SDA), 5 (I2C SCL) und 6 (Masse).

MCO23017 und Raspberry Pi

 

Testen der Schaltung mit I2C-Tools

Um die Verbindung testen zu können, wird die Tool-Sammlung i2c-tools benötigt, die mit folgendem Befehl installiert wird:

#sudo apt-get update && apt-get install i2c-tools

Mit dem Befehl

#i2cdetect -y 0

wird der I2C-Bus 0 nach angeschlossenen Geräten durchsucht. Wurde die Schaltung so aufgebaut, wie im letzten Artikel beschrieben, wird genau ein IC mit der Adresse 0x20 angezeigt:

    0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Nun testen wir, ob die einzelnen Register des Chips lesbar sind:

#i2cdump -y 0 0x20

Die folgende Liste zeigt die Register des MCP23017:

00h IODIRA
01h IODIRB
02h IPOLA
03h IPOLB
04h GPINTENA
05h GPINTENB
06h DEFVALA
07h DEFVALB
08h INTCONA
09h INTCONB
0Ah IOCON
0Bh IOCON
0Ch GPPUA
0Dh GPPUB
0Eh INTFA
0Fh INTFB
10h INTCAPA
11h INTCAPB
12h GPIOA
13h GPIOB
14h OLATA
15h OLATB

Wichtig für die Ansteuerung des HX2262 sind die folgenden Register:

  • IODIRA und B: Konfiguration der Pins von GPIOA/B als Input oder Output
  • GPPUA und B: Konfiguration der integrierten Pullup-Widerstände (Auf VCC) von GPIOA/B (im Input-Modus)
  •  GPIOA und B: Schaltung der GPIO-Pins auf 0 oder 1 im Output-Modus

Die Register können mit den I2C-Tools auch direkt geschrieben werden. Um z.B. alle Pins von Register A (GPA0-7) als Input zu konfigurieren, muss der folgende Befehl ausgeführt werden:

#i2cset -y 0 0x20 0x00 0xff

Die Parameter einzeln bedeuten:

  • -y: Keine weitere Bestätigung vor Ausführung nötig
  • 0: Gearbeitet wird mit I2C-Bus 0
  • 0x20: Der IC hat die Adresse 0x20
  • 0x00: Geschrieben wird Register 0x00 (IODIRA)
  • 0xff: Alle 8 Bits werden auf 1 gesetzt. (0xFF entspricht dezimal 255 und binär 11111111)

Entsprechend werden mit dem folgenden Befehl alle 8 Pins als Output konfiguriert:

#i2cset -y 0 0x20 0x00 0x00

Um die Ports jetzt von 0 auf 1 zu schalten, wird der folgende Befehl verwendet:

#i2cset -y 0 0x20 0x12 0xff

LEDs, die an einem der Pins von GPIOA angeschlossen sind leuchten jetzt. (Vorwiderstand verwenden!)

 Im nächsten Artikel zeige ich bespielhaft, wie der MCP23017 per Python angesteuert werden kann.

4.83 avg. rating (95% score) - 6 votes

29 Gedanken zu “Vorbereiten des Raspberry Pi auf I2C

  1. Pingback: Funksteckdosen mit Raspberry Pi steuern | G-SURF

  2. Pingback: Raspberry Pi: MCP23017 I2C mit Python steuern | G-SURFG-SURF

  3. Hi, ich habe heute meinen MCP23017 bekommen und mich sofort an die Verkabelung gemacht. Zuvor habe ich die i2c Unterstützung mit einem rtc(pvf8583) ausprobiert. Und wunderbar, keine Probleme.

    Aber mit diesem MCP23017…. der stürzt andauernd ab.
    Direkte Verkabelung 20 cm. Nach manuellem reset über Pin 18 ist er wieder da. Dann funktioniert es eine weile und nach 3 – 4 leseversuchen ist er weg.

    irgend eine Ahnung?

    pi@raspberrypi ~ $ i2cdetect -y 1
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: — — — — — — — — — — — — —
    10: — — — — — — — — — — — — — — — —
    20: 20 — — — — — — — — — — — — — — —
    30: — — — — — — — — — — — — — — — —
    40: — — — — — — — — — — — — — — — —
    50: — — — — — — — — — — — — — — — —
    60: — — — — — — — — — — — — — — — —
    70: — — — — — — — —
    pi@raspberrypi ~ $ i2cget -y 1 0x20 0x12
    0x00
    pi@raspberrypi ~ $ i2cget -y 1 0x20 0x12
    0x00
    pi@raspberrypi ~ $ i2cget -y 1 0x20 0x12
    Error: Read failed
    pi@raspberrypi ~ $ i2cget -y 1 0x20 0x12
    Error: Read failed
    pi@raspberrypi ~ $ i2cget -y 1 0x20 0x12
    Error: Read failed

    • Das kann mehrere Ursachen haben. Hast du den Reset-Pin mit einen 1k Widerstand auf VCC geschaltet? Der Zustand des Pins ist sonst nicht sauber definiert. Zusätzlich würde ich den Pin mit einem 100 nF Kondensator auf Masse legen. Der Kondensator leitet beim Einschalten so lange, bis er geladen ist. Das reicht, um einen sauberen Reset durchzuführen. Falls das nicht fruchtet, liegt es wahrscheinlich an der Stromversorgung. Hast du einen 100 nF Abblockkondensator zwischen GND und VCC des MCP23017 angebracht? Der Chip reagiert relativ empfindlich auf Störungen.

      • Ok, da habe ich wohl noch etwas nachzuholen. Ich hatte es so wie auf dem Bild oben verbunden. wie Müsste das Schaltbild denn genau aussehen um alles „richtig“ miteinander zu verbinden?
        Müssen die Adresspins 17-15 des MCP auf masse gelegt werden?
        Danke für deine schnelle Antwort
        Es gibt nichts schlimmeres als an einem samstag Abend vor dem Rechner zu sitzen und es funktioniert nicht so wie es soll. 🙂
        mfg matze

        • Den Widerstand siehst du auf dem Schaltbild im vorherigen Artikel. Der Kondensator ist da noch nicht eingezeichnet. Die Adresspins kannst du auf Masse legen. Wenn du mehrere MCP23017 an einem I2C-Bus betreiben möchtest, musst du mindestens einen Pin auf Plus legen, um eine andere Adress zu erhalten. In jedem Fall sollten die Pins entweder mit Plus oder Masse verbunden werden, weil ihr Zustand sonst wieder nicht sauber definiert ist.

        • Hallo, es hat funktioniert.
          1 Wiederstand 1K zwischen vcc und reset (pin18)
          1 100nF Kondensator zwischen vcc und vss
          3 * vss an pin 15 – 17 (A0-A2)
          und er läuft stabil.
          THX
          matze

  4. Pingback: MPD RaspberryPi LCD Interface « Random IT Stuff

  5. Hallo, ich verwende ein HD44780 20×4 LCD via I2C mit LCDproc.

    Mein I2C wird via i2cdetect -y 0 nicht erkannt, sondern via i2cdetect -y 1 unter der Adresse 0x20

    In LCDproc habe ich als Treiber i2c eingetragen, allerdings zeigt mein LCD nur Blöcke an.

    Kann mir jemand helfen?

    • Ich vermute mal, dass du einen relativ alten Raspberry Pi besitzt. Der RPi verfügt grundsätzlich über zwei I2C Schnittstellen. Diese wurden ab der zweiten Revision gedreht. Seitdem liegt Bus 0 auf dem Header P1. Ich kenne LCDproc nicht, aber ich könnte mir vorstellen, dass man dem auch irgendwie sagen muss, welchen Bus es verwenden soll.

        • Das stimmt. Hätte ich wissen müssen, ich habe selber noch die alte Revision im Einsatz. 😀 Fakt ist jedenfalls, dass es sowohl Versionen mit I2C-0 als auch mit 1 auf dem P1-Header gibt.

  6. Hi,
    ich habe gerade deinen Artikel gelesen, da ich versuche ein paar Taster auszulesen. Aber irgendwie werde ich nicht ganz schlau.

    Ich habe 5 Taster, diese sind an GPA0-4 angeschlossen.
    Ich möchte nun also GPA0-5 als Eingang deklarieren und die Pullupwiderstände aktivieren.

    GPA4 setzte ich so als Eingang
    i2cset -y 1 0x20 0x00 0x04?

    Hier hörts bei mir schon auf. Wie mach ich das nun?

    Gruß und danke schon mal,
    Daniel

    • Das ist so nicht korrekt. Du musst das Byte (bei dir jetzt 0x4) in Bits bzw. seine Binärform umwandeln. Wenn du die ersten 5 Pins als Eingang schalten willst, muss der Wert also 00011111 sein. Hexadezimal ist das dann 1F. Also i2cset -y 1 0×20 0×00 0×1F. Dann die Pullups an mit i2cset -y 1 0×20 0×0C 0×1F. Dadurch liegen alle 5 Pins hochohmig auf + (logisch 1). Um zu schalten, kannst du jetzt einen Taster zwischen dem Pin und Masse anschließen. Durch Drücken des Tasters ändert sich der Wert des Pins dann auf 0. Auslesen kannst du das mit i2cget 0x20 0x12. i2cget und -set sind aber nur für Diagnosezwecke da. Wenn du das sinnvoll nutzen willst, musst du dich mit eine Programmiersprache wie z.B. Python (sehr einfach) auseinandersetzen. Code-Beispiele habe ich einige in den anderen Artikeln.

  7. Bedenken

    der IC Portextender wird mit 5 V betrieben, liegt dann an SCA und SCL daher nicht ebenfalls 5V? Der PI verträgt aber nur 3V?
    Gibt es da keine Problme?

    • Die Frage muss lauten, mit welcher Spannung der Bus betrieben wird. Der Bus wird nie aktiv auf Volt gelegt, sondern per Pullup-Widerstand am RPi mit 3,3 Volt versorgt. Die Kommunikationspartner ziehen den Bus bei der Datenübertragung dann wechselseitig auf 0 Volt herunter. Am IO-Expander darf der Bus natürlich nicht per Pullup auf 5 Volt gezogen werden. Das ist aber auch nicht nötig.

  8. Hallo,
    kann mir jemand helfen, den I2C-Clock auf 10kHz beim Modulaufruf zu konfigurieren, da ich über längere Kabelstrecken damit senden/empfangen möchte. Standard ist ja 100kHz, was bei größern Kabellängen Probleme wegen der Lastkapazitäten macht.
    Durch Eigenprogrammierung von I/o-Pins als Master ist es kein Problem, die Clockfrequenz beliebig zu wählen. Ich möchte aber das I2C-modul des Pi verwenden.

  9. JG vielen Dank für den Hinweis. Leider hilft er nicht weiter, da die Clockänderung wahrscheinlich nicht vorgesehen ist.
    Also werde ich einen i/o-port als Master programmieren und kann so den Clock beliebig durch waits einstellen.

  10. Hi,

    ich hätte auch mal ne Frage zum Thema „mehrere Devices an einem I2C Anschluss“… verstehe ich nicht ganz…oder stelle mich zu doof 🙂

    Nehmen wir an ich möchte 2 MCPs 230xx an einem Raspberry PI RevB anschließen. Wenn ich das hier und das Netz richtig verstehe würde ich beide MCPs an denselben SCL/SDA Anschlüssen des des Rasperrys anschließen. Masse und GND dann aber unterschiedliche. Sprich bei RevB 1x MCP auf GPIO1 3,3 und GPIO 10 GND, den anderen dann auf GPIO17 3,3 und GPIO25 GND? Richtig kapiert? Dann kann ich ihn über i2cdetect abfragen und kriege einen zweiten angezeigt?

    Richtig kapiert oder noch Ideen?

    • Nein, das ist so nicht korrekt. Man nimmt auch die gleichen Anschlüsse für VDD und GND. Damit zwei Chips an einem I2C-Bus funktionieren, müssen sie unterschiedliche Adressen haben. Die Adresse wird jeweils über die Pins A0,A1 und A2 eingestellt. Ich habe in meinem Beispiel alle drei auf Masse gelegt. Das entspricht dann der Adresse 0x20. Wenn man nur A1 und A2 auf Masse legt und A0 auf VDD (über einen Widerstand mit mindestens 1k Ohm), dann ändert sich die Adresse auf 0x21. Du solltest bei so etwas nicht raten, sondern einfach einen Blick ins Datenblatt werfen. Auf Seite 8 wird die Adressierung beschrieben. Es gibt 7 Bits für die Adresse. 4 Stehen fest und die anderen drei werden über die PINs A0-A2 definiert.

      • Ist eine Frage nicht genau dafür da, eine Antwort zu geben auf dessen jemand versucht hat zu verstehen/interpretieren oder von mir aus auch zu raten? Wobei man raten als abwertend bezeichnet, sprich jemand tippt ins blaue hinein. Dennoch, danke für die Antwort, ich werde hier niemand weiter behelligen.

        • Ich glaube, das ist abwertender rübergekommen, als es gemeint war. Die Ergebnisse deiner Netzrecherche sahen nur eher nach Raten als nach Lesen aus. 🙂 Du kannst hier gerne weiter Fragen stellen und ich werde mich immer bemühen, sie zu beantworten. Das nächste Mal auch gerne ohne kleinen Seitenhieb. 😉

          • Ich glaube das geht iO 🙂

            A0+A1+A2 -> GND = 20
            A0 -> 1kΩ -> VDD; A1+A2 -> GND = 21
            A1 -> 1kΩ -> VDD; A0+A2 -> GND = 22
            A0+A1 -> 1kΩ -> VDD; A2 -> GND = 23
            A2 -> 1kΩ -> VDD; A0+A1 -> GND = 24
            A0+A2 -> 1kΩ -> VDD; A1 -> GND =25
            A1+A2 -> 1kΩ -> VDD; A0 -> GND = 26
            A0+A1+A2 -> 1kΩ -> VDD = 27

            Getestet funktioniert und damit auch geteilt, evtl. nutzt das jemanden.
            War zwar Operation am offenen Herzen, aber als absoluter Elektronikneuling ist für mich wirklich alles neu…war aber auch so geplant vom Projekt her.

  11. Hallo ,
    ich hab da mal eine Frage. Ich möchte am I2C-Bus eine Echtzeituhr DS1307 sowie den Potexpander MCP23017 betreiben. Gibt es da Probleme wegen der 3,3 V die der Raspi verträgt und den 5 V der Betriebsspannungen der beiden Schaltkreise. Im Raspi-Forum sind die Beispielschaltungen der Uhr mit 5V betrieben der MCP23017 jedoch mit 3,3V. Was ist richtig? In Deiner Schaltung betreibst Du den MCP23017 auch mit 5 V.
    Gruß Mathias

    • Der Bus wird an irgendeiner stelle über Pullup-Widerstände auf eine bestimmte Spannung gezogen. Beim Raspberry ist diese Funktion standardmäßig an, kann aber deaktiviert werden. Während der Übertragung der Daten zieht keine der Stationen den Bus auf ihre jeweilige Spannung hoch, sondern betreibt lediglich ein Pulldown auf 0. Dadurch ist es eigentlich kein Problem, wenn man Geräte mit unterschiedlichen Versorgungsspannungen an einem Bus betreibt. Man muss nur darauf achten, dass keine der angeschlossenen Komponenten ein Pullup auf 5 Volt oder mehr macht. (Datenblatt konsultieren!) Der Raspberry Pi könnte sonst Schaden nehmen. Komponenten, die als I2C Slave arbeiten, machen das aber in der Regel nicht.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Spamschutz * Time limit is exhausted. Please reload the CAPTCHA.