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! :-)
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.
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
Ich komme nach wie vor nicht weiter und bin über jeden Denkanstoß dankbar :-)
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.
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.
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.
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 ;-)
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".
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.