dinsdag 20 december 2022

Snelheidsmeter

Eerder al heb ik wat berichten (hier en hier) geschreven over de snelheidssensor en hoe die het analoge signaal van de versnellingsbak (lees: kabel naar de oorspronkelijke snelheidsmeter) omzet naar een digitaal signaal (blokgolf). De sensor geeft twee pulsen per omwenteling. Als de k-factor gelijk is aan 1.0, dan betekent dit per omwenteling precies één meter afgelegde weg.


Bij 120 km/h (haal ik waarschijnlijk nooit) wordt één meter afgelegd in 3600 [s/h] / 120 [km/h] = 30 milliseconde. De lengte van één puls is dan minimaal 30 / 4 = 7.5 milliseconde. De ESP32 heeft een standaard Tick Time (o.a. gebruikt voor het schakelen tussen Tasks) van 10 milliseconde. De puls al pollend inlezen in een Task is dan geen optie. Hiervoor is de blokgolf/pulstrein te snel. Met een Interrupt moet dit echter wél lukken. Interrupts kunnen de 'normale' afloop van het programma onderbreken. Wanneer een Interrupt Event optreedt, wordt een Interrupt Service Routine (ISR) aangeroepen. Dit is een functie die gebruikt wordt om het event af te handelen.

In eerste instantie heb ik gekozen om de interrupt zo in te stellen dat deze reageert op de opgaande flank van de blokgolf. Telkens wanneer de ISR doorlopen wordt, wordt de systeemtijd (het aantal microsecondes vanaf de start) van de microcontroller in een buffer gezet. Die buffer (de juiste term is eigenlijk Queue) wordt later door een 'normale' taak uitgelezen en verwerkt tot snelheid.

De eerste resultaten van deze opzet waren niet bepaald hoopgevend. Om niet te zeggen: frustrerend slecht. De tijd tussen twee pulsen schiet echt alle kanten op.

Pulstijd bij verschillende snelheden van de accuboormachine

In bovenstaande grafiek wordt de tijdsduur tussen twee interrupts in microsecondes getoond. Een korte tijd is een hoge snelheid. De meting is uitgevoerd met een accuboormachine die omgerekend ongeveer een snelheid van 120 km/h kan nabootsen. Maar wat gaat hier nu mis? Is dit een elektrisch, mechanisch of softwareprobleem? Hoe dan ook, het moet opgelost worden want met deze data kan ik geen stabiel en actueel snelheidssignaal genereren.

Mogelijk ligt het aan de snelheidskabel. Da's nog de oude kabel uit de Eend. Ik heb de snelheidsmeter in de Eend ook wel eens op en neer zien trillen bij bepaalde snelheden. Dit probleem is uit te sluiten door een meting te doen met de boormachine direct op de speedsensor; dus zonder kabel ertussen. Helaas zien die metingen er ongeveer hetzelfde uit.

Een andere mogelijkheid is de boormachine zelf. Het is er een van het brushless type. Hierin zit een softwarematige besturing van de elektromagneten die misschien iets van onbalans veroorzaakt. Een meting met een oude boormachine mét koolborstels laat ook weer zien dat het probleem niet opgelost is.

Elektrisch misschien? In eerste instantie leek dit voor mij onwaarschijnlijk omdat de meting optisch is, er een laagdoorlaatfilter met een tijdsconstante van 1 milliseconde toegepast is en de analoge meting netjes digitaal gemaakt wordt met een LM393 comparator.

Dan moet het wel aan de software liggen. Maar veel simpeler dan wat er nu geprogrammeerd is, kan het niet gemaakt worden. De ISR leest 'slechts' de processortijd uit en zet die in een buffer. Gaat er dan toch iets mis met de interruptafhandeling in de ESP32 zelf? Of zit hier jitter op of lagging in, in verband met het Real Time Operating System (FreeRTOS) van de ESP32? Het gebruik van een interrupt in een Task Switching systeem is ook wel een beetje discutabel... "Op een andere manier meten", tipte een collega. Da's natuurlijk geen slecht idee. Om uit te sluiten dat de interruptafhandeling van de ESP32 debet is aan het probleem, heb ik de meting in een Arduino UNO geprogrammeerd. De Arduino heeft geen RTOS en is hierdoor per definitie veel eenvoudiger. Er is niet veel wat de werking van de interrupt kan beïnvloeden.

De test met de Arduino liet twee problemen zien:
  1. Met enige regelmaat (ongeveer 50%) wordt de interrupt twee keer direct na elkaar afgevuurd.
  2. De tijdsduur tussen de interrupts is de helft van wat de ESP32 als resultaat gaf.
Probleem 2. is erg vreemd, want dat zou betekenen dat de Burton 240 km/h zou rijden ;-). Het lijkt net alsof de neergaande flank ook een interrupt oplevert. Probleem 1. zou betekenen dat er iets met de opgaande flank aan de hand is. Het wordt tijd om de blokgolf nog maar eens met een oscilloscoop te bekijken (5 milliseconde per divisie):


120 km/h: pulslengte ongeveer 7.5 milliseconde


Bovenstaand plaatje komt overeen met ongeveer 120 km/h. Mooie nette pulsen, korter zullen ze niet worden. Geen reden tot zorg toch? Als er echter ingezoomd wordt op de opgaande flank (500 nanoseconde per divisie), dan wordt de oorzaak duidelijk:


Onregelmatigheden in de opgaande flank.


De opgaande flank ziet er in het microseconde-bereik helemaal niet zo mooi uit. Het is heel goed mogelijk dat er twee opgaande flanken gedetecteerd worden. Dus twee snelle interrupts na elkaar. Probleem 1. is hiermee verklaard. Als er vervolgens naar de neergaande flank gekeken wordt (geen plaatje van), dan zie je ook hier wat bouncing/dender. Heel goed mogelijk dat ook hier een opgaande flank gedetecteerd wordt. Mooi, want dat verklaart probleem 2.

Interrupt events in opgaande en neergaande flank


Wel vreemd dat de LM393 dit lijkt te veroorzaken. Een snelle blik in de datasheet van de LM393 laat zien dat deze comparator een Response Time heeft van 300 nanoseconde.


Response Time uit de datasheet van de LM393


Dat klopt wel ongeveer met het scope-beeld hierboven. Verderop staat er nog een notitie in de datasheet:



www.ti.com


"Oscillation Tendencies", daar had ik geen rekening mee gehouden. Ze worden minder als de weerstand aan de ingang kleiner is dan 10 kOhm. Bij mij is die weerstand precies 10 kOhm, dus dat er nog iets dendert valt dus te verwachten. De interrupt van de Arduino/ESP32 pikt die oscillaties naadloos op.

Nu de oorzaak bekend is, kan een oplossing bedacht worden. Die is eigenlijk achteraf gezien niet zo ingewikkeld. Door een tweede interrupt binnen een bepaalde tijd ná de eerste te negeren (het grijze vlak in onderstaande figuur) wordt probleem 1. opgelost. Als de software zo geconfigureerd wordt dat er naast de opgaande flank ook een interrupt gegenereerd wordt voor een neergaande flank, en dat ook hier een snel opvolgende tweede interrupt genegeerd wordt, houden we twee nette interrupt events over. Eentje op de opgaande flank en eentje op de neergaande flank.


Twee nette voorspelbare interrupt events


Dat betekent dat er vier events per omwenteling optreden (het vijfde event in onderstaande figuur is het eerste event van de volgende omwenteling). De vier tijdsduren bij elkaar opgeteld levert precies de tijd op van één volle omwenteling en dus één meter afgelegde weg. Ideaal om de snelheid mee uit te rekenen.




Dit alles levert het volgende resultaat op met een Arduino:


Omwentelingstijden bij verschillende snelheden van de accuboormachine


Dat ziet er strak uit. De software is ongeveer een-op-een van de Arduino naar de ESP32 gezet, met als resultaat dat het hierin nu ook prima werkt. Da's fijn, want nu hoef ik in ieder geval geen nieuwe oplossing te zoeken in de hardware. Zoals de collega het al tipte, soms is het nodig om even uit te zoomen en op een andere manier te meten om achter eventuele problemen en bijbehorende oplossingen te komen.


1 opmerking: