lumapu / ahoy

Various tools, examples, and documentation for communicating with Hoymiles microinverters
https://ahoydtu.de
Other
953 stars 224 forks source link

NRF24 polling trotz aktiviertem IRQ #83

Closed lumapu closed 8 months ago

lumapu commented 2 years ago

@stefan123t Heute habe ich mir gedacht, ob eigentlich alle libraries die wir nutzen 'echt' ESP8266 tauglich sind. Insbesondere schaue ich auf die NRF24 Lib. Im Bezug auf SPI liest man immer wieder, das ESPs einen Watchdog Reset haben. Das könnte dich am den blockenden Kommandos liegen, da hier evtl. am und an zu viel Zeit verbraucht wird. Durch kurzes recherchieren bin ich auf dieses Repository gestoßen: https://github.com/xsrf/nbSPI

Auf dem SPI Bus ist für mein Gefühl auch etwas viel Traffic, habe aber nur kurz mit dem Oszi drauf geschaut.

Evtl. baue ich mir Mal testweise eine NRF24 Version damit. Am WE habe ich meine Ahoy DTU komplett neu aufgebaut, mit Wemos D1 und geschirmten NRF24 (wir in Forum beschrieben). Leider sind die Abstürze gleich geblieben - vor allem bei Sonnenuntergang habe ich verlässlich einen. Mit ist immer noch nicht klar wo es da klemmt.

stefan123t commented 2 years ago

Hallo Lukas, das mit Sonnenuntergang deckt sich mit meinen Erfahrungen und Beobachtungen. Nach Sonnenuntergang kann der WR nicht mehr antworten, dh der ESP steckt in seiner TX/RX Schleife und verbringt viel (zu viel?) Zeit damit auf Antworten zu warten die aber nicht kommen. Wenn er dann teilweise andere Aufgaben startet (wie MQTT Nachrichten oder gar WiFi Requests) dann wird er manchmal evtl. doch noch durch gelegentliche Antworten oder Fragmente durch angeforderte Retransmits unterbrochen.

Alles in allem scheint er die Zeit für die Routineaufgaben nachts nicht mehr so sauber und gut aug alle „Prozesse“ zu verteilen woe tagsüber wenn er auch antwortrn bekommt. Am nächsten Morgen wenn der WR auch wieder antwortet scheint auch meist wieder alles eitel Sonnenschein.

Einer der Punkte die mir prinzipiell auf/eingefallen sind, wäre statt dem ESP8266WebServer wie in Thomas B.‘s OpenDTU auch den AsyncWebServer zu verwenden. Drg sollte prinzipiell nicht-blockierend sein und kann ggf aucb mehrere Clients/Requests quasi „parallel“ abhandeln/beantworten. Ich hatte gestern versucht seinen OpenDTU Code auf den ESP8266 bzw die dafür benötigten Bibliothrken zu portieren, bin aber an den beiden Interrupt-Handlern als Klassen-Methoden gedcheitert. Ich muss die vermutlich aus der Klasse herauslösen damit es mit dem ESP8266 klappt.

stefan123t commented 2 years ago

Der Einsatz von nbSPI_writeBytes klingt sinnvoll und mit 64Bytes scheint der Buffer für die üblichen nRF24 Pakete auch mehr als ausreichend. Eine Anpassung der nRF24 Bibliothek sollte evtl auch nicht allzu aufwändig sein ? Ggf könnten wir auch Upstream beim nRF24 Entwickler ein issue aufmachen. Hast Du vom Oszi oder Logik Analyzer irgendwelche Screenshots o.a. die die Auslastung des SPI Bus zeigen ? Das wäre ja ein Ansatzpunkt den man ggf überprüfen könnte.

lumapu commented 2 years ago

Ich schaue mir Mal an was man an der Lib ändern müsste. So wie ich nbSpi verstehe kann man das 1:1 einsetzen.

Bzgl. Oszi habe leider nichts gespeichert, das kann ich die Tage noch nachholen, zur Doku.

lumapu commented 2 years ago

@stefan123t jetzt habe ich ein paar Aufnahmen gemacht, allerdings mal wieder im dunkeln. Der IRQ bleibt dauerhaft auf 0, trotzdem ist auf dem SPI irgendwie 'Rushhour'. Ich habe die Lib noch nicht gecheckt, wo und warum diese Daten gesendet werden. (Ob MISO und MOSI richtig sind weiß ich auch nicht)

Capture mit 5ms/div

Detail View of some packages

Long Package (comes from time to time)

and its data (between rulers): 110630_longTransmission.csv

Edit: Der SPI Bus läuft mit 1MHz, siehe 'Detail View' Edit2: Ich glaube ich habe bit Bitorder falsch rum eingestellt, ich denke lt. Nordic Semi Datenblatt eher, dass ständig das Statusregister 0x07 gepollt wird. Edit3: .... aber gedreht würde ja 0x70 heißen ...

stefan123t commented 2 years ago

@lumapu danke für das Update und die Bildchen.

  1. Dass der IRQ dauerhaft bei 0 bleibt wär ja Nachts logisch, da er ja nichts empfängt, für das er den IRQ auslösen muss.

  2. Bitorder umgekehrt würde bedeuten: 0b00000111 bzw. 0x07 => 0b11100000 = 0xE0 Bei Dir steht aber 0x0E also 0x00001110 => 0b01110000 oder 0x70 ?

  3. Auf dem "langen Paket" kann man in der Tat ein bißchen was von einer Payload erkennen: A0 >15< <72 21 41 59> <78 56 34 12> >80< <0B> 00 <62 BE 2A 88> <00 00 00 05> <00 00 00 00> <EB 51> <1C> edit <> passend zum Protokoll Das sieht zumindest in Teilen wie eine Debug Status Message des Ahoy DTU an den nicht erreichbaren Wechselrichter aus. Offenbar sendet er auch noch weitere Daten nach der CRC8, ist das gewollt / notwendig ? Andererseits beginnt das Paket mit 0xA0 also 0b1010 0000 und nicht mit SOF 0x7E / 0b1111 1110 Das Stop Byte sollte 0x7F oder 0b1111 1111 sein.

Vielleicht muß die Variable die gesendet werden soll auch vorher auf NULL gesetzt werden, bevor man sie an den NRF übergibt ?

Auf jeden Fall sollte ich auch mal mein Loqic Squid anschließen, wenn da so hübsche Bildchen rauskommen =^D Ich versuche das noch geistig farblich zuzuordnen, vielleicht kannst Du mich korrigieren / aufschlauen ?:

lumapu commented 2 years ago

warum wird das NRF24 Modul die ganze Zeit gepollt, wir haben doch einen IRQ ... da verstehe ich dann den IRQ nicht

lumapu commented 2 years ago

Das Datenblatt habe ich hier gefunden: Sparkfun - NRF24L01

Status Register (In parallel to the SPI command word applied on the MOSI pin, the STATUS registeris shifted serially out on the MISO pin)

  1. Status Register lesen
  2. Bit 3:1 auswerten um RX Pipe zu wissen
  3. Register 0x11 + RX-Pipe lesen

Bzgl. dem langen Paket: für mich sieht es so aus, als würde das Register 0x0A gelesen (Receive address data pipe 0), 5 bytes. Danach wird wohl automatisch das Payloadregister gelesen (dieses hat keine eigene Adresse). Habe im Datenblatt aber noch keine Beschreibung hierfür gesehen.

Fazit: Ich denke in der von uns genutzen Lib kann man auf jeden Fall noch Performance / Stabilität / Integrität schaffen.

stefan123t commented 2 years ago

Hallo Lukas, bei mir kommen einige Status Kommandos immer wieder und alle dreißig Sekunden die konfigurierte Abfrage an den Wechselrichter:

Einen IRQ konnte ich glaub noch nicht aufnehmen. Und er ist mehrere Sekunden sehr beschäftigt mit dieser langen Sequenz.

Also die anderen Implementierungen DTU-PRO, OpenDTU, etc. setzen den SendBuffer immer komplett auf 0x00 bevor sie ein neues Paket zusammensetzen. Die DTU-PRO setzt sogar eine Dummy CRC-16 Summe bevor sie die dann wieder mit der berechneten überschreibt.

Dabei werden die Daten auch immer wieder vor dem Senden mit ForwardSubstitution() zwischen RS485/Net Schnittstelle und NRF24 (usart_nrf.c/.h) escaped. Bei den Antworten erfolgt dann mit UsartNrf_Backward_substitution1() das Gegenteil mit den empfangenen Daten. Hierbei werden die Escape/SOF/EOF Bytes durch "Escape"-Sequenzen ersetzt, also die zu sendenden Daten ggf auch länger. 0x7d -> 0x7d5d 0x7e -> 0x7d5e 0x7f -> 0x7d5f

lumapu commented 2 years ago

Ja spricht aktuell nicht für die Lib. Evtl. wurde sie vorher nur wenig oder gar nicht mit dem ESP8266 getestet. Wir können zwei Ansätze verfolgen:

Ich bin persönlich ein Verfechter von Interrupts, ihre Effizienz im Vergleich zu den unsinnig vielen Poll-Anfragen überzeugt mich. Gut könnte ich mir auch vorstellen genau diesen Punkt konfigurierbar zu machen

stefan123t commented 2 years ago
  • ohne IRQ und nach unserem Zeitplan / Statemachine pollen

Das ist zumindest die Vorgehensweise, die auch die DTU verwendet. Schau mal in UsartNrf_SendLoop_SetPackageTimeOut() dort finden sich die diversen Timeouts. Das sind bei nRF24 mit 250kHz meist nicht mehr als 300-500 ms je nach Anfrage / Antwort.

Die Sache mit den Interrupts ist halt, daß der normale Programmablauf komplett unterbrochen wird. Und es ist auch nicht 100% sicher, ob nicht während einer unserer Interrupthandler läuft nicht bereits der nächste IRQ hereinkommt ? Das erinnert mich ein bißchen an die "Goto is Evil"-Debatte, wobei wir an der Stelle ein nicht-deterministisches Goto eingebaut haben, das vom NRF24 getriggert wird. D.h. es kann auch mitten in einer MQTT / WiFi / WebServer Aktion mal kurz die CPU kapern.

lumapu commented 2 years ago

Ich bin mir nicht sicher, ob pollen richtig ist, es wäre halt tagsüber wie nachts identisch. Ich glaube nicht, das viele IRQs unseren Ablauf stören, denn wir setzen ja nur noch ein Flag, das wir asynchron abfragen (nach unserem Zeitplan). Was mich an der aktuellen Implementierung stört ist die Dauerkommunikation trotz aktiviertem IRQ.

lumapu commented 2 years ago

@stefan123t Ich habe mal eine Version mit dem AsyncWebServer in einen extra Branch geladen: https://github.com/lumapu/ahoy/tree/asyncWeb

Leider habe ich folgende Probleme, daher mit Vorsicht genießen (Kopie aus commit-log):

Ich habe es mit einem ESP-07 (1MB Flash) getestet, daher kann wahrscheinlich für einen Wemos D1 in der platform.ini folgendes entfernt werden:

board_upload.maximum_size = 1048576
build_flags = -Wl,-Teagle.flash.1m64.ld
stefan123t commented 2 years ago

@lumapu ich schaue es mir mal bei Gelegenheit an. Der AsyncWebServer sollte m.W. auch im AP Modus funktionieren. Das mit dem Platz auf dem D1 mini (EPS-07) kann ich mir vorstellen / erklären der hat ja auch nur 1MB Flash. Vielleicht sollten wir 4MB Flash als Minimum annehmen / vorraussetzen oder wir müssen ein paar unserer Pages im Flashmem kleiner machen ? +1 für 4MB minimum flash, aber wir können auch eine kleine Umfrage im Forum starten, wer überhaupt einen Flash mit 1MB nutzt.

lumapu commented 2 years ago

Ich denke nach deiner Liste in https://github.com/grindylow/ahoy/issues/36#issuecomment-1179792033 können wir von einem Wemos D1 Mini (v3) mit 4MB Flash als Quasi-Standard für dieses Projekt ausgehen.

stefan123t commented 2 years ago

Yes, that would mean we unsupport the Wemos D1 mini LITE v1 version. Lets first ask the number of users of this specific model on the forum ... and decide in a week or two.

NDS234 commented 2 years ago

ESP8266 bei mir 4 MB Flash

eeprom23 commented 2 years ago

Nutze auch einen 4mb !

ghost commented 2 years ago

Nutze einen Wemos D1 Mini v3 4 mb

Ziyatoe commented 2 years ago

Ich meine, die HTML-Seiten sind schön und recht aber ihr könnt niemals alle wünsche erfüllen, irgend wann wollen die noch Grafiken;-)

ghost commented 2 years ago

I understand it like this: It is being considered whether the Wemos D1 mini LITE v1 will no longer be supported. Especially the Wemos D1 Mini v3 4 mb will continue to be supported.

Ziyatoe commented 2 years ago

IRQ: ich habe bei mir beide Versionen, also mit und ohne irq laenger getestet. Es laeuft mit polling definitiv besser, fast keine Abstürze und erwischst mehr Daten. Ich denke die irq in der Lib ist nicht ganz sauber. RX-CH-hopping: mein WR sendet an machen Tagen nur noch über CH61/CH75, also nix mit CH03

lumapu commented 2 years ago

@Ziyatoe sprichst du über MI-1500 oder HM-1500? Wahrscheinlich ist es sogar egal, aber trotzdem wäre es interessant.

Ziyatoe commented 2 years ago

@lumapu ja ich habe MI-1500. Aber auch einige HM user haben berichtet, dass es manchmal halben Tag nichts empfangen und danach gings wieder: https://www.mikrocontroller.net/topic/525778?page=single#7128706 Ich bin ziemlich sicher, dass nur auf CH3 hören ist zu wenig.

lumapu commented 2 years ago

@stefan123t ich habe mal angefangen eine Debug-Firmware zu bauen, um besser zu verstehen was das NRF24 Modul im Hintergrund wirklich macht. Wie wir schon am Oszi gesehen haben wird sehr oft das Statusregister abgefragt, im Schnitt ca. 1000x pro Schreibbefehl - ich weiß nicht ob das die feine Art ist, evtl. sollte man auch hier auf Interrupts setzten, da der ESP für diese Zyklen in einer while-loop hängt. Ein yield in dieser Loop führt zu einen nicht mehr per WebUI erreichbaren ESP.

https://github.com/lumapu/ahoy/tree/nrfdebug

stefan123t commented 2 years ago

@lumapu wollen wir das Issue umbenennen in "NRF24 Status Abfrage 0x07 trotz Interrupt -> Stabilität ESP8266" ?

lumapu commented 2 years ago

@stefan123t hab's umbenannt, finde ich auch besser so

thfcm commented 2 years ago

Zusammenfassung der im Discord gesammelten Informationen zu diesem Issue.

Symptome:

Mögliche Ursachen: Zu 1) Es wurde beobachtet, dass 0xFF via SPI an das NRF-Modul gesendet wird.

0xFF ist in https://github.com/nRF24/RF24/blob/master/nRF24L01.h#L115 als RF24_NOP hinterlegt (Null Operation).

Verwendet wird es in RF24.cpp an 9 Stellen, unter anderem in der Funktion RF24::get_status(void) https://github.com/nRF24/RF24/blob/master/RF24.cpp#L499

Diese Funktion wird an mehreren weiteren Stellen genutzt. Es wird ein NOP Byte gesendet und das Statusregister wird vom NRF-Modul als Antwort zurück erwartet. Damit wird scheinbar u.A. festgestellt, ob das Modul verfügbar ist (wenn es eine Antwort erhält), ob eine Pipe verfügbar ist ( RF24::available(uint8_t* pipe_num)) oder ob Payload verfügbar ist ( RF24::isAckPayloadAvailable(void) )

Von @lumapu kam der Hinweis, dass die Quelle des polling hier zu suchen ist: https://github.com/lumapu/ahoy/blob/nrfdebug/tools/esp8266/nrf24/RF24.cpp#L1255 In dieser Funktion wird get_status() in einer Schleife aufgerufen, was wiederum den NOP-Befehl schickt.

Zu 2) Vermutlich sorgt das in 1) beschriebene Problem dafür, dass der Core des ESP8266 blockiert wird und nicht mehr die utility functions ( -> siehe yield() ) ausführen kann, was zu einem reset durch den WDT führen kann.

Meine Vermutung: Die in 1) beschriebene Schleife wird deswegen abends zum Problem, weil die Gegenstelle (Wechselrichter) nicht mehr antwortet.

Für mich zu prüfen:

lumapu commented 2 years ago

@thfcm issue ist wieder offen

Mir ist noch was eingefallen. Wir sollten uns mal die Möglichkeit anschauen auch den TX interrupt zu aktivieren.

stefan123t commented 2 years ago

Das Problem sollte doch auch bei einer invaliden Inverter Serial ID auftreten. Wenn wir geklärt haben an welchen Methoden das Status oder NOP von der RF24 Bibliothek gesendet wird können wir das entweder vermeiden oder upstream ein issue (preferably in english) für nrf24/rf24 aufmachen und vermutlich auch schnell eine Antwort vom aktuellen Maintainer der Bibliothek @ 2bndy5 bekommen.

stefan123t commented 2 years ago

@aschiffler warum ist eigentlich #83 zu. Wurde das durch das veränderte MQTT reconnect #139 ebenfalls behoben ?

@thfcm @lumapu#4369 oder liegt das an der nRF24 Bibliothek die einfach immer wieder den Status 0xFF RF24_NOP des nRF24 prüft / pollt anstatt auf den IRQ zu warten ?

lumapu commented 2 years ago

das Thema steht noch aus, bitte noch nicht schließen

stefan123t commented 2 years ago

@lumapu Dein Vorschlag auch TX per IRQ zu handlen klingt logisch und gut. Hast Du das schon mal umgestellt und Nachts mit dem Oszi nachgemessen. Da sollten ja nur TX Pakete rausgehen und kein RX IRQ ausgelöst werden da der Wechselrichter schläft. Also wäre logisch dass er vermehrt pollt wenn er keinen TX IRQ verwenden soll/kann.

lumapu commented 2 years ago

nein habe ich noch nicht, steht noch aus

DanielR92 commented 2 years ago

Hallo, was muss hier genau gemacht werden? Wie kann ich hier Unterstützen?

lumapu commented 2 years ago

glaube nicht, man muss die Software auf Interrupts umstellen (auch für write) und dann mit einem Oszilloskop prüfen, ob noch eine Dauerkommunikation besteht

stefan123t commented 1 year ago

@DanielR92 & @lumapu hier sollten wir prüfen ob das Problem dem Polling im TX Modus (vor allem im Nachtbetrieb aufgefallen) behoben werden kann:

Wenn das Problem danach trotzdem noch auftritt, sollten wir uns definitiv Alles von Brendan beschriebene genauer ansehen:

Aber vorher würde ich die anderen o.g. Punkte anpassen.

stefan123t commented 1 year ago

@DanielR92 ja Model und die RF Data Rate und RF Power Amplifier sind die Punkte auf die ich immer schaue.

Auto Retry Delay und Auto Retry Attempts bestimmen glaube unsere TX/RX Timeouts.

Und mir war als hätten Brendan und TmRh20 uns noch was zu der Static Payload Lenght mit 32 Byte als Aufgabe mitgegeben ?

Deren Empfehlungen waren hier https://github.com/nRF24/RF24/issues/877 verlinkt

lumapu commented 1 year ago

@stefan123t ich habe am WE den interrupt für tx_ok und tx_fail testweise aktiviert und die startWrite Funktion verwendet. Leider kam weder ein TX interrupt noch ein RX interrupt.

Weißt du, ob es ein Beispiel mit startWrite gibt?

knickohr commented 1 year ago

Ja verdammt, das lese ich erst jetzt. Würde ja zu meinen Beobachtungen mit der Pause zwischen dem 2. und 3. retransmit passen, oder ?

Würde in meinen Augen auch erklären warum es bei aktivierter Night Communication öfters auftritt, und auch bei mehreren WRs. Denn je mehr WRs und je öfter wir pollen, umso höher ist die Wahrscheinlichkeit das Waldi beißt 😵

Ich habe jetzt mal die Retransmits auf nur 2 eingestellt, also genau da aufhören wo die Pause ist. Vielleicht bringt’s was. Wir werden sehen.

stefan123t commented 1 year ago

@knickohr ja das ist ein bereits seit langem offenes Ticket. Das deckt sich natürlich mit dem was Du bisher in #564 herausgefunden hast. Ich hatte auch in der Vergangenheit im TX only Modus die meisten WDT Resets.

@lumapu nein ich weiß nicht sicher wie wir die startWrite Funktion richtig verwenden. Ich glaube aber es gab in der RF24 Bibliothek auch ein paar Beispiele die zeigen sollten wie es richtig geht. Eventuell sollte hier auch noch das eine oder andere yield() eingebaut werden, damit der ESP im TX only Modus nicht vergißt Waldi den Watchdog zu füttern.

@beegee3 hier sind die Verbindungen zur RF24 Bibliothek und unserem Issue upstream bzgl. dem Polling im TX Modus. M.E. müssten wir hier die Timeouts für die mögliche Antwort des WR auch einbauen, da wir sonst einfach nur senden und gar nicht warten ob evtl. etwas zurück kommt. So überlasten wir vermutlich den ESP wenn wir die ganze Zeit nur den NRF24 pollen.

knickohr commented 1 year ago

Macht mal langsam, nicht gleich eine neue DEV pushen. Wie gesagt, ich habe mal die Retransmits auf 2 runter gedreht weil ich eben zwischen dem zweiten und dritten TX eine „größere“ Pause beobachte. Vielleicht hilft das auf die Sprünge,bzw kann man Waldi hier noch ein Leckerli geben.

Aber vielleicht ist das mit der 76 ja schon gefixt. So eine flüssige DEV gab es seit der 66 nicht mehr 👍

wait and see 🙃

knickohr commented 1 year ago

Vielleicht auch hier relevant : #643