esp8266 onbegrijpelijk seriele bitbang instabiliteit ?

Pagina: 1
Acties:

Vraag


  • PtrO
  • Registratie: November 2001
  • Laatst online: 01:26
Heeft iemand hints of tips die kunnen verklaren waarom een C++/Arduino esp8266 programma door het te inhoudelijk wijzigen, met bv totaal ongebruikte code, (te) instabiel wordt om seriële data via bitbang uit te lezen ?

Ik laat mij graag verder hoe dingen daarin beter tot werking te brengen. Mochten er specifieke tldr; vragen zijn over inhoudelijk hoe/waarom/anders ipv van het boek hier beneden door te akkeren, zijn die natuurlijk ook welkom.

Bvd Peter

//--//
Het issue zelf is vrijwel identiek met wat iemand anders ooit (zonder oplossing/antwoord) had besproken op https://github.com/esp8266/Arduino/issues/4193. Een willekeurige sourcecode aanpassing, maakt de programmawerking op andere plaatsen instabiel.
////---////
Het programma zelf is o.a. multitaskend bedoeld als autonome homecontroller, o.a. daarin P1 data data afkomstig van twee meters via software middels 2 GPIO poorten om -en-om seriële bitbangend uit te lezen.
Eenmaal de telegramdata hebbend, wordt dit verder verwerkt en via MQTT naar elders gecommuniceerd.
FYI: De totale hele spaghetti en chili-concarne is te beproeven op GitHub (disfunctionele kritiek op aard of persoon, graag per DM).

Het serieel bitbangen gaat doorgaans goed totdat ik ergens (maakt totaal niet uit waar en/o die actief wordt gebruikt) programmacode verander waarna de ISR (ICACHED) bitbang soms - te vaak - in de datasoep loopt.

NB: in P1 zelf ontbreekt de synchronisatie van bytes en de gebruikte ISR/Gpio routine halverwege een byte op een verkeerd startbit kan triggeren die daarna de rest in de soep draait. Een volledig P1 telegram, wordt permanent elke 10Sec uitgelezen, bevat ca 750bytes die op snelheid van 115200Baud in ongeveer 0.8S dan al bitbangend wordt aangeboden.
Hierbij kan het (soms/frequent) voorkomen dat data vanwege timing e.d. corrupt raakt. Een datastream van bv
code:
1
1-0:31.7.0(002*A)
wordt dan ineens gelezen als runningaway
code:
1
1-0:31.7.0(0aeefegeghdgeh
.

Gelukkig zijn er ook zg "P1 segmentgaps" van ca 0.2-0.3mS, tussen & in de verschillende datadelen, die seriële starttransport weer wat op orde brengt.
Indien ik foute data heb gelezen, probeer ik die automagisch te herstellen door het inhoudelijk al checksummend te vergelijken met een voorheen wel geslaagde actie. Fout gelezen bytes worden dan zo hersteld.

Kern is dat het programma (voor mij) prima werkt wanneer ik het eenmaal heb voorzien van totaal nutteloos "stabiliserende" code toevoegingen. Dit door in de source - maakt niet uit waar/toe - ongebruikte if-then-else, functies oof nop's bij te plaatsen of juist weg te halen. een keer zou direct denken aan corrupt/overlay waar hier geen sprake van lijkt te zijn. een source code vernadering lijkt specifiek betrekking te hebben op het ISR gedrag dat dan ineens te laat start.

Zover ik kan beoordelen lijkt er dus geen sprake van fragmentatie, overlow, stack of heap conflicten. Ik heb de boel inmiddels een keer of 3-4 van de grond af aan opnieuw gebouwd met wanneer het programma wat groter wordt, het daarmee gevoeliger wordt voor sourcecode veranderingen.

Ik ben (ooit) begonnen vanuit de gekende SoftwareSerial (https://github.com/plerup/espsoftwareserial) die ik in allerlei maten/versie heb verbouwd en voorzien heb van aanpassing om seriële poort stuurbaar te krijgen en de "data" leesbaar te krijgen op 115200Baud. De meest stabiele was versie daarin 2.4.1 die daarvoor verregaand is verbouwd zodat het specifiek o.a. werkt op P1-netbeheer telegrammen van ca 600-800bytes. Een datatelegram begint met "/" , eindigt op "!"; gevolgd door een CRC16 checksum. De verwerking van het telegram zelf, mits leesbaar, is verder geen probleem.

NB: het is uitdrukkelijk NIET mijn bedoeling de redenen, mijn (dis)kwaliteiten en werkwijze tot doel van het programma te bespreken, die te bekritiseren of te verklaren met laat staan, dat dit met ander tooling, methoden, hardware of oplossingen kan worden bereikt.
Ik kan ipv de slecht remmende auto te repareren, natuurlijk een nieuw kopen en dan prima een hardware rs232 interface inzetten. Datgene verklaard (mij) nog niet waarom een code aanpassing, tot een andere werking leidt.

Waar ik knettergek van wordt is zodra ik ook maar één byte in de source verander, het programma in meer of minder mate instabiel wordt. Ik heb versies gemaakt die bijna 100% foutloos de seriële lezen en versies dat totaal niet doen.
Ik vervolgens uren tot dagen bezig ben om op willekeurige plaatsen ad-random (dummy) code moet invoegen om het stabiel te krijgen. het meest effectieve is dan invoegen van zg NOP's machinecode instructies die daarmee de objectcode wat doet verschuiven.

Klein voorbeeld waar ik ergens een optelling of aftrekking doe, kan het al gebeuren dat de stabiliteit van de ISR routines daarmee in de soep draait. Dit wordt weer opgelost door ergens dummy code, meest effectief is invoegen van zg één of (veel) N.NOP's (Extensa assembler Instructie die de processor 1 cycle, niets laat doen).
...
Ik begon ooit simpel met de Arduino IDE en stapte later over VSCode/patformIO om het esp8266/ NodeMCU12 programma on the flyby te ontwikkelen.
Daar de boel erg gevoelig bleek op welk platform ik opereerde, heb ik de boel nu vastgezet op: espressif8266@2.5.3 , toolchain-xtensa @ 2.40802.200502 en framework-arduinoespressif8266 @ 3.20701.0 (= --> Github: esp8266 Arduino 2.7.1)
Migreren naar hogere versie van dat , als inmiddels veel vaker gedaan, blijkt effectief zinloos en is vwb het stabiel krijgen vooral tijdrovend bezigheidstherapie.

Wat ik al gevonden of geprobeerd heb : Talloze probeersel, waarom invoegen van dummycode, ongebruikte datavelde, vergroten van databufffers, invoegen van NOP/assembler instructies etc.etc.
Om het programma stabiel te krijgen voeg ik her -en der ongebruikte dummy code toe zodat het van het niet slechtwerkend gaande weg verbeterd tot bijna foutloos. Dit totdat ik het programma weer ander en dat exercitie pad opnieuw kan doen.

Vast dank d:)b hier alles tot hier gelezen te hebben en ik beantwoord natuurlijk graag specifiek vragen mbt tot dit instabiliteitsissue. Ik neem het risico dat niemand zich hierin herkent en dat is het iig opgenomen in de annalen O-) van een verdere toekomst.
...

Go with the flow blocking your way and use AD for achieving results

Beste antwoord (via PtrO op 15-08-2026 01:26)


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:24
Lijkt me dat je het resultaat ziet van het verschil in code optimalisatie door de compiler (let wel, en een gemiddelde code base is het performance verschil huge tussen wel en niet goed kunnen optimaliseren) en andere tijd/scheduling gerelateerde effecten.

Daarnaast vermoed ik dat je code bugs bevat, in de zin dat de compiler zaken wel of niet wegoptimaliseert waarvan jij denkt/vindt dat ze nodig zijn. In (moderne) C en C++ is dat een dingetje. Wat je beschrijft is precies dat.

Beste is om een hardware serial port te gebruiken.

Je code is trouwens niet te volgen (maar dat wist je al) dus daar zouden ook legio logica fouten in kunnen zitten. Serial.print in een ISR lijkt me ook niet handig trouwens, dat zal ook andere ISRs blokkeren. Naja...

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.

Alle reacties


Acties:
  • Beste antwoord

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 00:24
Lijkt me dat je het resultaat ziet van het verschil in code optimalisatie door de compiler (let wel, en een gemiddelde code base is het performance verschil huge tussen wel en niet goed kunnen optimaliseren) en andere tijd/scheduling gerelateerde effecten.

Daarnaast vermoed ik dat je code bugs bevat, in de zin dat de compiler zaken wel of niet wegoptimaliseert waarvan jij denkt/vindt dat ze nodig zijn. In (moderne) C en C++ is dat een dingetje. Wat je beschrijft is precies dat.

Beste is om een hardware serial port te gebruiken.

Je code is trouwens niet te volgen (maar dat wist je al) dus daar zouden ook legio logica fouten in kunnen zitten. Serial.print in een ISR lijkt me ook niet handig trouwens, dat zal ook andere ISRs blokkeren. Naja...

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • PtrO
  • Registratie: November 2001
  • Laatst online: 01:26
Helemaal Cool 8-) l !!!!
tldr; ineens viel het muntje ..... de compiler optimaliseert globale variabelen die ooit 'zomaar ' in de BitBang ISR zijn geslopen !!!! Guess the issue what happens elsewhere |:( .
Het probleem is mij nu duidelijk en daarmee min of meer opgelost. Thx _/-\o_

//--//

Ik gebruik op de esp8266 een aantal verschillende ISR's waarvan er twee heel kritisch zijn t.w. seriële 115K2 bitbang van twee verbonden RS232's (P1 van de elektra en een P1 van de verwarming). Daarnaast een ISR om een wobbelende draaiend blinkertje van een watermeter te detecteren.
Ik heb mij t.a.v. RS232 bitbang onvoldoende gerealiseerd om de daarin gebruikte (global) variabelen w.o. met name de databuffers NIET doro de compiler te laten optimaliseren (middels "volatile" declaratie op velden en o.a. pointers). Door ad-random code in te voegen, gaat de compiler anders (of juist niet) optimaliseren. Dit tot een volgende source wijziging en het verhaal zich herhaalt.

FWIW en voor wie dat nog niet (onder)kent: compiler optimalisatie is o.a. dat die aannames doet op de te vertalen code waarbij dingen logisch voorspelbaar zijn zoals 1+1=2, dat dan ook verderop die 2 blijft. Dit niet alleen qua data maar ook (jump/pointer)instructies waarbij bv register-offsets een rol spelen.
Een ISR springt asynchroon weg uit die normale logica en kan dan die compiler - inclusief onveranderlijk aangenomen register/pointer associaties - compleet verprutsen.
Dit laatste is dus precies wat er in mij code gebeurd(e) wat leidt tot een onverklaarbaar gedrag.
Voor een betere uitleg: https://barrgroup.com/embedded-systems/how-to/c-volatile-keyword

Nu dit muntje ruim op de neus is gevallen, is mijn probleem (bijna) als sneeuw voor de zon verdwenen.
Inzake printen in een ISR gaat dat verder prima, zoals je maar niet de ISR van "Hardware Serial" gebruikt. Voor de P1's kon/wilde ik geen hardware serial gebruiken omdat ik die in de toekomst wilde gebruiken om te communiceren met een (highspeed) MBUS systeem.

Thx verder voor de terechte en zacht geuite kritiek. De code is idd erg rommelig en daar wil ik verder niets aan afdoen, anders dat alles een oorzaak tot gevolg is. VSCode helpt mij gelukkig om wat op een spoor te blijven. Nu ik de oorzaak in het snotje heb, wordt het straks puinruimen.
Bedenk hier dat een Arduino/ESP loopmodus moet doen zonder dat die ergens op een WatchDogTimeout instort. Wat daarin mijn uitdaging dan verder compliceert is het gebruik van (wisselende) Wifi en MQTT-monitoring daarin/uit ook wordt afgehandeld. Voorts allerlei andere allerlei I/O (temperatuur & dag/licht) sensoren worden verwerkt en ik de boel ook fault-tolerant zodat mijn verwarming altijd operabel blijft en niet in de winter gata bevriezen.
De ESP (o.a. vv UPS) vormt daarmee min of meer het hart van/naar mijn meterkast.

Alles begint met 10 regels totdat het er 10.000 zijn geworden met weer een idee om op een wankele basis in poging iets te herstellen. In de "code" zit zeker allerlei overbodige troep die er in gekomen om het proberen te begrijpen.

En ja de compiler deed mij hier overduidelijk met optimalisatie ergens de das om.
Daar heel lang al naar zitten kijken zonder te "begrijpen" waar ik faliekant mis ga/ging. Zelf zover dat ik tientallen disassemblies bytewise heb doorgeworsteld en dan idd op hele rare dingen uitkwam de ik totaal niet kon plaatsen.

Go with the flow blocking your way and use AD for achieving results