Forum: Mikrocontroller und Digitale Elektronik Mehrere ESP32 via I2C im High Speed Mode


von Heiner W. (heiner1)


Lesenswert?

Hallo zusammen!

ich habe einen Aufbau, bei dem ein ESP32 als I2C-Master fungiert.

3 weitere per I2C verbundene ESP32 im Slave Mode liefern Werte zu 33 
Bytes pro Abfrage mit einer Frequenz von 100 Hz. Dazu fragt der Master 
jeden Slave an, welcher die Werte zurück gibt. Ich nutze die Library 
Wire.h aus dem ESP32-Core.

Diese Werte werden zusammengefasst über die serielle Schnittstelle an 
den Computer gegeben. Insgesamt dauert der Prozess dabei für alle 3 
Slave-ESPs zwischen 9 und 11 ms. Ein Request zum Slave dauert 1-2 ms, 
eine Rückmeldung vom I2C Slave ebenfalls. Das überschneidet sich dann in 
der maximal erlaubten Gesamtdauer von 10ms, um mit 100 Hz die Daten zu 
übertragen.

Jetzt würde ich gerne die clockSpeed am I2C Master höher drehen. 
Standard sind 100 KBit/s. 200 KBit/s sind auch noch problemlos möglich.
Sobald ich aber den Fast Mode mit 400 KBit/s über den Befehl 
"Wire.setClock(400000L)" oder gar noch mehr versuche, klappt die Abfrage 
der Slaves nicht mehr.

SDA und SCL sind per 2.2kOhm Widerstand mit 3.3 V als Pull-Up verbunden. 
Testweise 4,7 und 1 kOhm haben auch nicht funktioniert. Die internen 
Pull-Ups habe ich mit folgenden Zeilen schon versucht zu deaktivieren, 
bin mir aber nicht sicher, ob das so geklappt hat. Stand so auf der 
Espressif Website:

gpio_pullup_dis(GPIO_NUM_21);
gpio_pullup_dis(GPIO_NUM_22);

Hat jemand noch eine Idee woran das liegen könnte?

Vielen Dank! :-)

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

34Byte * 3St. * 100Hz = 81.600Bit/s

100K kann also durchaus knapp werden. 400K macht also durchaus Sinn.

- Können deine Slaves überhaupt 400k, kommt deren Software da überhaupt 
hinterher? Elektrisch sind 400k eigentlich problemlos, außer du hast da 
größere Kabellängen dazwischen?

- Sind deine Widerstände richtig angeordnet? Nicht das du die viermal 
angeschaltet hast?

Also, wie sieht dein Aufbau aus?

Beitrag #7120842 wurde vom Autor gelöscht.
Beitrag #7120850 wurde vom Autor gelöscht.
von Heiner W. (heiner1)


Angehängte Dateien:

Lesenswert?

Ja wird recht knapp, zumal ja neben der Datenübertragung vom Slave zum
Master noch der vorherige Request kommt + ein gewisser Overhead. Mit 100
KBit/s gehen in etwa 1/4 der Daten verloren. Mit 200 KBit/s noch so um
die 2-5 %, je nachdem wie er gelaunt ist.

Zusätzlich sollen die 3 Slaves im Optimalfall auf bis zu 15 Slaves
erweitert werden können, womit dann definitiv der 3,4 MBit/s Ultra High
Speed Mode her müsste, den der ESP32 aber eigentlich beherrschen müsste.

-> Kabellängen sind mit 5-10cm unproblematisch
-> Als Slaves fungieren ja wiederum ESP32 im SlaveMode nach dem Schema
aus dem WireSlave Example des ESP32 Core. Ob die im SlaveMode 400k
unterstützen weiß ich nicht, aber ich habe nichts gegenteiliges
gefunden. Der Master gibt die Clock ja vor, von daher muss ich an den
Slaves meines Wissens nach nichts verändern. Funktionieren ja auch bei
100k und 200k, ohne Veränderungen im Code. Die Slaves haben auf dem 
einen Core nichts anderes zu tun, als auf die I2C Requests zu reagieren, 
von daher sollte das eigentlich hinkommen. Auch wenn ich testweise den 
Slaves keine andere Aufgabe gebe, als auf die Requests zu reagieren, 
läuft das ganze immer noch nicht.
-> Widerstände sollten so korrekt sein. Einfach an SCL und SDA jeweils
einen 2,2 kOhm Widerstand auf 3.3V. Hier noch ein Bild der im Grunde
sehr simplen Schaltung

: Bearbeitet durch User
von Heiner W. (heiner1)


Lesenswert?

Ich komme nach wie vor nicht weiter und bin über jeden Denkanstoß 
dankbar :-)

von Stefan F. (Gast)


Lesenswert?

Sei froh, dass es überhaupt ein bisschen funktioniert. Mikrcontroller 
als I²C Slave waren nämlich schon immer schwierig, und bei ESP besonders 
problematisch.

Wenn man verstanden hat, wie der Bus funktioniert, wird das auch 
sonnenklar. Der Bus erfordert eine Antwortzeit von weniger als einem 
Takt, was du auf Mikrocontrollern nur mit besonderen Klimmzügen 
erreichen kannst. Wenn dann auch noch ein ganzer IP Stack parallel dazu 
läuft, kann es nicht mehr vernünftig funktionieren.

Du brauchst ein anderes Bus-System, das erheblich längere Antwortzeiten 
erlaubt, und zwar in Größenordnung um 100ms. Nur dann kann es auf dem 
ESP richtig zuverlässig laufen.

von Heiner W. (heiner1)


Lesenswert?

Danke für die Rückmeldung!

Bis 200 KBit/s läuft es über I2C tatsächlich vollkommen rund und 
fehlerfrei. Dazu beschäftige ich den Core 1 ausschließlich mit der 
Aufgabe als I2C Slave, um eben das Timing hinzubekommen. Aber auch wenn 
auf Core 0 parallel ein Datenempfang via BLE läuft, funktioniert alles.

Erstaunlich ist: Auch wenn der Slave wirklich keine andere Aufgabe hat, 
als auf I2C requests zu antworten, funktioniert das über 200K nicht 
mehr.

Antwortzeiten um 100ms kommen nicht in Frage, weil ich die Daten in 
harter Echtzeit mit 100 Hz übertrage. Also maximal 10ms Intervalle.

Welche Möglichkeiten gäbe es denn noch insgesamt 16 ESP32 miteinander zu 
verbinden und die 33 Bytes pro ESP mit 100 Hz weiterzuleiten? Eine 
Überlegung ist es noch, die ESPs über UART quasi "in Serie" zu schalten. 
D.h. jeder gibt seine BLE Daten dazu und leitet das ganze an den 
nächsten weiter. Da addieren sich aber auch die Millisekunden, könnte 
aber evtl noch eine Lösung sein.

Man könnte langsam meinen, dass ich der erste bin, der versucht den 
ESP32 im Fast Mode als Slave zu betreiben. Finde im Netz auch 
tatsächlich nichts dazu.

von DerEgon (Gast)


Lesenswert?

Hat der ESP32 keine UART?

von Stefan F. (Gast)


Lesenswert?

Der ESP32 ist für Echtzeit-Anwendungen im einstelligen ms Bereich eine 
sehr problematische Wahl. Schon dessen Art Code zu cachen und sein 
Betriebssystem passen kaum dazu.

Der ESP ist eigentlich als Master designt, welcher ggf durch externe 
Slaves unterstützt wird.

von Heiner W. (heiner1)


Lesenswert?

Danke für die Einschätzung!

Wie gesagt läuft mit bis zu 3 I2C Slaves alles flüssig und zuverlässig 
und ist daher bisher glücklicherweise für meine Anwendung durchaus 
echtzeitgeeignet im Bereich von unter 10 ms. Sobald es mehr werden, 
reicht eben die Geschwindigkeit nicht mehr aus, um alle Slaves in einem 
10 ms Takt auszulesen.

Für meine Zwecke reicht das jetzt vorerst. Über den zweiten I2C Bus 
könnte ich ja nochmal 3 Slaves anklemmen und schauen, ob das läuft. Und 
wenn es dann dringend wird, schaue ich vielleicht nach einer UART 
Lösung, bei der die ESPs quasi in Reihe geschaltet werden.

Die Hoffnung nach einem einfachen Weg den ESP32 als Slave mit über 200 
KBit/s zu betreiben lebt aber immernoch. Vielleicht kennt ja jemand den 
Kniff dafür ;-)

von Stefan F. (Gast)


Lesenswert?

Dann achte künftig darauf, weiterhin die Dual-Core Version des ESP32 zu 
verwenden. Denn die Single-Core Version kann im Falle von 
Übertragungsstörungen beträchtliche Zeit mit der WLAN Schnittstelle 
beschäftigt sein, so dass die I²C Slave Schnittstelle nicht schnell 
genug bedient wird.

Du kannst den Programmcode, der den I²C Slave bedient, eventuell ins RAM 
kopieren, damit er nicht immer wieder (bei Bedarf) vom Flash Speicher in 
den Code Cache kopiert werden muss.

Siehe dazu 
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/memory-types.html 
"How to place code in IRAM".

von seriell (Gast)


Lesenswert?

> Und wenn es dann dringend wird, schaue ich vielleicht nach
> einer UART Lösung, bei der die ESPs quasi in Reihe geschaltet werden.

Wieso in Reihe schalten? Halbduplex, fertig. Macht I2C ja auch. Zur 
Entkopplung der Tx-Ausgänge der Slaves genügt ein Tristate-Treiber, der 
vom jeweiligen Slave nur beim Antworten aktiviert wird.

Der Master sendet die Clientadresse, der jeweilige Client antwortet, der 
Master sendet die nächste Clientadresse, der nächste Client antwortet 
etc.

So wird es auch bei RS485-Bussen gehandhabt (da schaltet der Master nach 
dem Senden auch seinen Treiber aus, damit nur ein Teilnehmer am Bus 
jeweils gerade antworten darf).

Alle Slaves empfangen alle Daten auf dem Bus und müssen erkennen, welche 
Nachricht für sie bestimmt ist und welche nicht. Das ist nicht besonders 
kompliziert.

Die ESP32-Software bietet ausführliche Unterstützung für den 
RS485-Betrieb, genau die kannst Du verwenden, und statt des 
RS485-Treibers o.g. Tristate-Treiber ansteuern.

Wenn die Leitungslänge allerdings über das I2C-übliche Maß < 1m 
hinausgeht, solltest Du gleich mit echtem RS485 arbeiten. Das ist 
erprobt.

Da der ESP32 eine Hardware-UART hat, entfällt auch das Problem, den 
Empfang per schnellem Bitbanging abwickeln zu müssen, wie es Dein 
I2C-Slave machen muss.

von Heiner W. (heiner1)


Lesenswert?

Die Art der Verbindung war mir bisher überhaupt nicht bekannt, klingt 
aber sehr gut geeignet für das Projekt und vielversprechend! Ich muss im 
Moment an anderen Baustellen arbeiten, lese mich da aber ganz sicher 
zeitnah ein und schaue mir das genauer an.

Besten Dank!

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.