Forum: Mikrocontroller und Digitale Elektronik Sensor Array ansprechen mit I2C - Unterschiede zu Mega2560 und Seeed RP2040


von Dat L. (datley)



Lesenswert?

Hallo zusammen.

ich bin ein absoluter Anfänger in der Welt des Raspberry Pis und bin auf 
ein Problem gestoßen und suche daher nach eurem Rat und Wissen.

In meinem Projekt habe ich eine Platine entworfen, auf der insgesamt 16 
Magnetsensoren (MMC5633NJL) in einem Sensor Array zusammengefasst sind. 
Die Sensoren werden über I2C angesprochen, da aber jeder Sensor die 
gleiche I2C Adresse hat, müssen diese mit einem I2C Multiplexer 
(TCA9548) zwischengeschaltet werden. Dieser ist ein 1- 8 Kanal 
Multiplexer und hat pro Kanal 2 Anschlüsse für jeweils SDA und SCL.

Dazu habe ich jeweils PullUp Widerstände (2,7 kOhm oder 10 kOhm) 
zwischen Sensor und Multiplexer Kanal gesetzt. Da der Raspberry Pi 5 
bereits integrierte PullUp Widerstände hat, habe ich keine zusätzlichen 
zwischen Multiplexer und Microcontroller platziert (beim RP2040 habe ich 
10kOhm Widerstände auf einem Breadboard dazwischen platziert).

Letztendlich sind also die 2 Multiplexer mit den Adressen 0x70 und 0x71 
direkt mit dem Raspberry Pi 5 verbunden, während die Sensoren mit den 
Multiplexern verbunden sind, um Adressenkonflikte zu vermeiden.



Mittlerweile habe ich es geschafft, die Sensoren über I2C mit dem Seeed 
RP2040 bzw. auch dem Arduino Mega 2560 zu erkennen und zu 
initialisieren. Diese geben auch Messwerte aus.

Der Code für den RP2040 sieht folgendermaßen aus:
1
import time
2
import board
3
import busio
4
from adafruit_mmc56x3 import MMC5603
5
from adafruit_bus_device.i2c_device import I2CDevice
6
7
'# Adressen der Multiplexer
8
TCAADDR1 = 0x70
9
TCAADDR2 = 0x71
10
'# Initialisiere I2C
11
i2c = busio.I2C(board.SCL, board.SDA)
12
'# Funktion zur Auswahl des Kanals am Multiplexer
13
def tcaselect(mux_address, channel):
14
15
if channel > 7:
16
return
17
18
with I2CDevice(i2c, mux_address) as mux:
19
mux.write(bytes([1 << channel]))
20
'# Überprüfen, ob die Multiplexer ansprechbar sind
21
print("Überprüfe Multiplexer...")
22
try:
23
with I2CDevice(i2c, TCAADDR1) as mux:
24
print("Multiplexer 1 (0x70) gefunden.")
25
except:
26
print("Multiplexer 1 (0x70) nicht gefunden.")
27
try:
28
with I2CDevice(i2c, TCAADDR2) as mux:
29
print("Multiplexer 2 (0x71) gefunden.")
30
except:
31
print("Multiplexer 2 (0x71) nicht gefunden.")
32
'# Initialisiere jeden Sensor an den entsprechenden Kanälen der Multiplexer
33
sensors = []
34
sensor_found = []
35
for i in range(16):
36
mux_address = TCAADDR1 if i < 8 else TCAADDR2
37
channel = i % 8
38
tcaselect(mux_address, channel)
39
print(f"Initialisiere Sensor auf MUX {1 if i < 8 else 2}, channel {channel}")
40
41
try:
42
sensor = MMC5603(i2c)
43
sensors.append(sensor)
44
sensor_found.append(True)
45
print(f"Sensor gefunden auf MUX {1 if i < 8 else 2}, channel {channel}")
46
47
except ValueError:
48
sensors.append(None)
49
sensor_found.append(False)
50
print(f"Keinen Sensor gefunden auf MUX {1 if i < 8 else 2}, channel {channel}")
51
52
'# Zeige Details für jeden gefundenen Sensor
53
for i in range(16):
54
if sensor_found[i]:
55
print(f"Sensor {i + 1}:")
56
print(sensors[i])
57
while True:
58
for i in range(16):
59
mux_address = TCAADDR1 if i < 8 else TCAADDR2
60
channel = i % 8
61
tcaselect(mux_address, channel)
62
print(f"Abfrage Sensor auf MUX {1 if i < 8 else 2}, channel {channel}")
63
64
if sensor_found[i]:
65
sensor = sensors[i]
66
67
mag_x, mag_y, mag_z = sensor.magnetic
68
temp_c = sensor.temperature
69
70
print(f"Sensor {i + 1}: X={mag_x} uT, Y={mag_y} uT, Z={mag_z} uT, Temp: {temp_c} *C")
71
72
else:
73
print(f"Sensor {i + 1}: X=0 uT, Y=0 uT, Z=0 uT, Temp: 0 *C")
74
75
print("****************************")
76
time.sleep(10)


Kurzfassung des Codes:

Zuerst prüft es, ob die Multiplexer erkannt werden und initialisiert 
diese. Danach prüft es pro Kanal, ob ein Sensor erkannt wird und 
initialisiert diese. Im letzten Schritt holt er sich die Messwerte der 
Sensoren durch Eventabfragen.



Nun zu meinem Problem:

Der Arduino Mega 2560 erkennt und initialisiert alle I2C Teilnehmer (den 
Code kann ich bei Bedarf gerne hochladen). Der Seeed Rp2040 läuft mit 
CircuitPython und erkennt auch alle I2C Teilnehmer. Beide holen sich 
auch Messwerte ab. Nur der Raspberry Pi 5, der genau den gleichen Code 
wie der RP2040 verwendet, erkennt nur die Multiplexer, aber nicht die 
Sensoren.
Das Board hat sich nicht geändert und wurde auf allen 3 Mikrocontrollern 
verwendet.



Ich möchte den Raspberry Pi 5 verwenden, da ich mit ihm das Sensorarray 
initialisieren, messen, visualisieren und in einem gemeinsamen, 
kompakten Programm auswerten möchte.



Habt ihr Ideen, weshalb der Pi im Vergleich zum RP2040 nicht die 
Sensoren erkennt?

Vielen Dank im Voraus und beste Grüße



Datley

[Mod: Code in code-Tags eingefasst]

: Verschoben durch Moderator
von Helmut -. (dc3yc)


Lesenswert?

Ich hab jetzt nicht dein Programm angeschaut, da mir das Scrollen zu 
doof ist. Bitte halte dich doch an die Forenregeln: Längeren Sourcecode 
nicht im Text einfügen, sondern als Dateianhang!

Und die Sprache der Elektronik ist ein anständiger! Schaltplan. Da gilt 
das gleiche: Bitte so zeichnen, damit man ohne scrollen etwas sieht!

: Bearbeitet durch User
von Dat L. (datley)



Lesenswert?

Hi Helmut,

danke für den Hinweis, mir war das nicht bewusst mit den längeren Code. 
Diesen füge ich natürlich neu an als Datei.

Die Zeichnung habe ich auch bearbeitet.

Viele Grüße


Dat

von Christoph M. (mchris)


Lesenswert?

Könnte ein Timing-Problem sein. Kannst Du den Multiplexer auf einen 
Kanal fest einstellen und schauen, ob ein Sensor durchkommt?

von Dat L. (datley)


Lesenswert?

Genau, das hatte ich schon probiert. Leider wurde selbst beim Einstellen 
eines Channels vom MUX kein Sensor erkannt.

Ich habe mir jetzt auch noch einen Logic Analyzer bestellt, weil ich die 
Vermutung ebenfalls hatte.

Aber gibt es nicht bei I2C nur zwei verschiedene Taktfrequenzen (100kHz 
und 400kHz)?
Beides hatte ich eingestellt beim Pi, aber ohne Erfolg.


Viele Grüße


Dat

von Helmut -. (dc3yc)


Lesenswert?

Mir kommen R2B und R2D auf der 3V3-Seite etwas groß vor. Würde da auch 
2k7 verwenden. Außerdem solltest du mal am RasPi auch Pullups verwenden. 
Vielleicht sind die doch nicht vorhanden?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Dat L. schrieb:
> Aber gibt es nicht bei I2C nur zwei verschiedene Taktfrequenzen (100kHz
> und 400kHz)?

Nicht wirklich!

Am Rande:
Alle deine genannten µC kommen mit Clockstretching klar.
Dein RPI5 nicht unbedingt.
Ihm hat eine recht eng bemessenen Timeout zwischen Byte und 
Clockstretching zwischen Bit mag ihm gar nicht.
Ist das die Ursache deiner Probleme? KA!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dat L. schrieb:
> Aber gibt es nicht bei I2C nur zwei verschiedene Taktfrequenzen (100kHz
> und 400kHz)?
Das sind die maximal erreichbaren Frequenzen, wenn keines der I2C 
Devices den Takt verzögert.

> Ich habe mir jetzt auch noch einen Logic Analyzer bestellt
Der zeichnet leider nur ein sehr binäres Bild seiner Signale. Und das 
muss nicht genau das Bild sein, das die Busteilnehmer sehen. Denn die 
haben garantiert andere Schaltschwellen als der LA. Deshalb sollte der 
erste Blick auf die Signale mit einem Oszilloskop erfolgen. Dann sieht 
man, ob das hübsche Rechtecksignale mit brauchbaren und stetigen Flanken 
sind. Wenn das der Fall ist, dann reicht für die weitere Analyse ein LA.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Lothar M. schrieb:
> mit einem Oszilloskop

Mit ein paar Serienwiderständen kann man gar das Clockstretching 
beobachten/erkennen.

von Dat L. (datley)


Lesenswert?

Helmut -. schrieb:
> Mir kommen R2B und R2D auf der 3V3-Seite etwas groß vor. Würde da auch
> 2k7 verwenden. Außerdem solltest du mal am RasPi auch Pullups verwenden.
> Vielleicht sind die doch nicht vorhanden?


Tatsächlich habe ich zwei Leiterplatten gebaut, einen mit 2k7 Pullups 
Widerständen und einmal mit 10k zwischen Sensor und MUX.

Ich hatte vorsichtshalber auch die beiden Leiterplatten mit Pullups über 
einem Breadboard zum RasPi5/ RP2040/ Arduino verbunden. Da waren 
ebenfalls die gleichen Ergebnisse. Dabei habe ich ebenfalls die 
Höhe/Größe der Pullups variiert.

RP2040 und Arduino konnten die Sensoren erfassen und deren Werte 
wiedergeben. Der RasPi5 konnte allerdings nur die Multiplexer erfassen. 
Das Skript mit der Channelabfragung habe ich auch abgespielt, jedoch 
ohne großen Erfolg.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.