Kommunikationsproblem: RPi - FT232H - MCP23017

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
luemmel76
User
Beiträge: 22
Registriert: Freitag 26. Februar 2016, 17:42
Wohnort: Südhessen

Hallo zusammen,

ich arbeite mich gerade damit ein einen MCP23017 (I2C 16 Kanal Expander) über den FT232H (USB zu I2C/SPI Chip) vom RPi aus anzusteuern. Ich nutze dabei die adafruit GPIO-Libs.

Was geht ist, das er die LEDs an den ersten 8 Kanälen ansteuert und beim beenden alle 8 LEDs ausschaltet.
Was nicht geht, das er die Kanäle 9-16 als Eingänge abfragt und mir den Staus wiedergibt, hier kommt es zur Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "FT232H_MCP23017_inputtest.py", line 32, in <module>
    u = mcp1.input(2)
  File "build/bdist.linux-armv7l/egg/Adafruit_GPIO/MCP230xx.py", line 95, in input
    return self.input_pins([pin])[0]
  File "build/bdist.linux-armv7l/egg/Adafruit_GPIO/MCP230xx.py", line 103, in input_pins
    gpio = self._device.readList(self.GPIO, self.gpio_bytes)
  File "/home/pi/test/FT232H.py", line 726, in readList
    self._verify_acks(response[:-length])
  File "/home/pi/test/FT232H.py", line 646, in _verify_acks
    raise RuntimeError('Failed to find expected I2C ACK!')
RuntimeError: Failed to find expected I2C ACK!
Mein Script nur zum abfragen der Eingänge sieht so aus:

Code: Alles auswählen

#!/usr/bin/python

# using I2C devices with FT232H USB to SPI/I2C breakout
import FT232H as FT232H
from Adafruit_GPIO import MCP230xx as MCP230xx
from time import sleep

# Temporarily disable FTDI serial drivers to use the FT232H device.
FT232H.use_FT232H()

# Create FT232H device instances.
ft232h1 = FT232H.FT232H(serial='FTYSYJZ6')  # I2C device

# Create MCP23017 (I2C 16 Channel Expander) device with FT232H as I2C provider.
#    Like the FT232H guide mentions, when using I2C you'll need to setup
#    your circuit with external pull-up resistors (4k7) connected to the
#    I2C clock (pin D0) and data lines (pin D1+2 together).
#    This is necessary because the FT232H is a general purpose chip which
#    doesn't include built-in pull-up resistors.
mcp1 = MCP230xx.MCP23017(i2c=ft232h1, address=0x21)

# Set pin 1-8 on mcp1 as output
for o in range(0,8):
    mcp1.setup(o, 0)

# Set pin 9-16 on mcp1 as input
for i in range(9,16):
    mcp1.setup(i, 1)
    mcp1.pullup(i, 1)

# read pin 2 on mpc1
u = mcp1.input(2)
print u
Hoffe es kann mir hier geholfen werden

Gruß
Thilo
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Welchen Sinn es hat, einen USB auf I2C-Adapter zu nutzen, wenn der PI schon I2C eingebaut hat muss ich wahrscheinlich nicht verstehen.

Wie dem auch sei, so direkt wird dir hier niemand helfen koennen. Denn dazu braeuchte man die entsprechende Hardware.

Ich wuerde mal anfangen mir auszugeben, was denn da fuer Daten vom i2c-Adapter zurueck kommen, und warum die den verify-check nicht bestehen.

Ausserdem kannst du natuerlich mal bei Adafruit selbst bzw. den entsprechenden Github-Repos Bug-Reports erstellen.
luemmel76
User
Beiträge: 22
Registriert: Freitag 26. Februar 2016, 17:42
Wohnort: Südhessen

Der Grund warum ich den MCP23017 über den FT232H ansteuern muß ist, das in dem Gerät wo der MCP eingebaut wird, kein Platz für den RPi samt Touchdisplay ist. Und da sowohl der I2C- als auch der SPI-Bus empfindlich auf längere Kabel reagieren, nutze ich lieber USB und den FT232H.
Später soll dann auch noch ein LS7366 (23-bit quadratur decoder zähler) mit in das Gerät, dafür nehm ich dann noch einen zweiten FT232H und beide werden im Gerät mit einem 2-Fach USB-Hub zusammengeschaltet. Dann ist der Platz ausgereizt.
Hab die beiden FT232H auch schon reprogrammieren können, sodass diese über die Seriennummer angesprochen werden können.

Wie lese ich denn aus was auf dem I2C-Bus so von sich geht?

Ich bin blutiger Anfänger und arbeite mich nur sehr schwer in Python ein, hab schon ein paar Bücher durch aber es bleibt kaum was hängen...

Bei Adafruit hab ich auch schon im Forum geschrieben, ist aber schwerer alles in englisch zu verfassen und warte da noch auf Antworten.

Gruß
Thilo
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst zB print-statements an die entsprechenden Stellen setzen, und schauen, was da fuer Daten gesendet und empfangen werden. Du kannst stattdessen auch usb-sniffing mit wireshark oder aehnlichen Tools machen.

Eine weitere Debugging-Technik besteht darin, *doch* den eingebauten I2C zu benutzen. Auch wenn du das ultimativ nicht kannst, so bekommst du dadurch doch immerhin eine Komponente eliminiert, und dadurch raus, wo genau das Problem liegt.

Last but not least gibt es auch fuer I2C bus-treiber, mit deren Hilfe du groessere Strecken ueberwinden kannst. Ich hab die mal benutzt, da waren das dann 8-Pol DIPs, das ist klein & gut loetbar. Kleiner als SMD geht natuerlich immer. Waere also eine Loesung, falls du das mit dem Adapter partout nicht hin bekommst, es aber mit dem eingebauten I2C geht.
luemmel76
User
Beiträge: 22
Registriert: Freitag 26. Februar 2016, 17:42
Wohnort: Südhessen

Danke für die Infos

Habe jetzt doch mal wie du vorgeschlagen hast, den MCP über ein misbrauchtes 2,5 Meter langes USB-Kabel und einen Levelshifter an den I2C vom Raspi geklemmt, mein script angepasst und schon bekomme ich auch die Inputs angezeigt :-D
Scheint also bei der kommunikation über den FT232 was schief zu laufen, das schreib ich auch im adafruit forum, die mögen das mal verifizieren.

hier mal mein testscript, es schaltet nach und nach die 8 Outputs auf High, und gibt mir jedesmal den aktuellen Status der 8 Inputs, danach werden nach und nach alle 8 Outputs auf Low gesetzt und wieder die Status aller 8 Inputs angezeigt.
Die Testverdrahtung sieht wiefolgt aus: MPC-Pin A0 -> LED + Optokoppler-LED -> Optokopplertrasistor -> MPC-Pin B0, usw.)

Code: Alles auswählen

#!/usr/bin/python

from Adafruit_GPIO import MCP230xx as MCP230xx
from time import sleep

# Create MCP23017 (I2C 16 Channel Expander) device with FT232H as I2C provider.
#    Like the FT232H guide mentions, when using I2C you'll need to setup
#    your circuit with external pull-up resistors (4k7) connected to the
#    I2C clock (pin D0) and data lines (pin D1+2 together).
#    This is necessary because the FT232H is a general purpose chip which
#    doesn't include built-in pull-up resistors.
mcp1 = MCP230xx.MCP23017(busnum = 1, address=0x21)

# Set pin 1-8 on mcp1 as output
for o in range(0,8):
    mcp1.setup(o, 0)

# Set pin 9-16 on mcp1 as input
for i in range(8,16):
    mcp1.setup(i, 1)
    mcp1.pullup(i, 1)

# Python test on output 0-8 toggling at given speed
st = 1 # sleep time
try:
    while True:
        for x in range(0,8):
            u = {8,9,10,11,12,13,14,15}
            #print mcp1.input_pins(u)
            mcp1.output(x, 1)  # Pin 0-8 High
	    print mcp1.input_pins(u)
            sleep(st)
        for y in range(0,8):
	    #print mcp1.input_pins(u)
            mcp1.output(y, 0)  # Pin 0-8 Low
	    print mcp1.input_pins(u)
            sleep(st)
except KeyboardInterrupt:
    opins = {0:0, 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0}    # set output 0-8 to Low
    mcp1.output_pins(opins)
    quit(0)
Und die Ausgabe für einen kompletten Zyklus:

Code: Alles auswählen

^Croot@AKAI-GX77:/home/pi/test# python MCP23017_inputtest.py
[False, False, False, False, False, False, False, True]
[False, False, False, False, False, False, True, True]
[False, False, False, False, False, True, True, True]
[False, False, False, False, True, True, True, True]
[False, False, False, True, True, True, True, True]
[False, False, True, True, True, True, True, True]
[False, True, True, True, True, True, True, True]
[True, True, True, True, True, True, True, True]
[True, True, True, True, True, True, True, False]
[True, True, True, True, True, True, False, False]
[True, True, True, True, True, False, False, False]
[True, True, True, True, False, False, False, False]
[True, True, True, False, False, False, False, False]
[True, True, False, False, False, False, False, False]
[True, False, False, False, False, False, False, False]
[False, False, False, False, False, False, False, False]
Schön wäre jetzt wenn mir beim Print-Befehl statt TRUE/FALSE 1/0 angezeigt würde, außerdem sieht mir die Pin-Nummerierung etwas schräg aus, aber nur so funktioniert es das er A0-A7 als Output und B0-B7 als Input nutzt...

Gruß
Thilo
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

An sich ist es besser (weil unmissverstaendlicher) mit boolschen Werten zu arbeiten. Wenn das nur fuer die Ausgabe anders sein soll, kannst du sie einfach in ints wandeln:

Code: Alles auswählen

[int(v) for v in liste]
Das mit der Pin-Nummerierung verstehe ich nicht.
luemmel76
User
Beiträge: 22
Registriert: Freitag 26. Februar 2016, 17:42
Wohnort: Südhessen

Danke nochmals, da die kommunikation ja mit dem langen Kabel erstmal läuft kümmere ich mich jetzt um den LS7366R (32-bit Quadratur Decoder Zähler) der auch direkt am Pi an SPI angeschlossen wird, siehe neuer Post ;-)

Gruß
Thilo
Antworten