Arduino - noggrann tidmätning & interrupt

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Hedning
Inlägg: 425
Blev medlem: 27 november 2011, 15:19:00
Ort: Linköping

Arduino - noggrann tidmätning & interrupt

Inlägg av Hedning »

... eller "Uno - den italienske cykeltjuven ertappad på bar gärning!"

Har haft lite huvudbry med att få så noggranna tidmätningar som möjligt
på Arduino Uno (för användning till mätning av mynningshastighet på
luftpistol). Programstrukturen är enkel med en givare som nollställer
timer1 via interrupt från ISR0 (på pin 2). Nästa givare läser räknarvärdet
via interrupt TIMER1_CAPT (från pinne_8). Void loop () gör inget alls om inte
en flagga är satt som anger att ett värde finns att beräkna och visa på
LCD.

Fungerar stabilt så när som på att korta tider bli lite fel och efter att
ha gjort en längre mätserie med verkligt pulsavstånd och räknarvärde
över hela registret från ca. 10 us till 4000 us visar sig att någon snor
klockpulser som inte kommer med i resultatet. Excel har funktionerna
SLOPE och INTERCEPT som är användbara för att visa sambandet mellan
mätserier i form av offset och lutning på kurvan när man har räknarvärde
på X-axeln och verkligt pulsavstånd på Y-axeln. Resultatet blir ---

intercept = -57,09876275
slope = 16,0029568 => klocka ns (1000/slope) = 62,48845213

Det fattas 57 pulser på timern (och kristallen är lite "off")
Inga andra interrupt är aktiva under mätningen men kanske efter om
LCD-biblioteket smyger in något. Andra har samma erfarenhet och antyder
att boven (Uno) är inblandad via kompilatorn som lägger in en hel del
i hanteringen av interrupt som snor klockcykler utan att man kan se det direkt.
Sökning på "arduino interrupt overhead" ger bl.a. följande utmärkta förklaring:
https://billgrundmann.wordpress.com/200 ... nterrupts/

Har testat att tröska mig igenom detta recept:
https://blog.benoitblanchon.fr/arduino- ... -assembly/
och man kan se en massa maskinkod i interrupthanteringen som förklarar
de saknade klockpulserna. Listningarna kan bli låååånga så jag har nöjt mig
med att det inte är oförklarliga fenomen och jag kan med gott samvete lägga
till 57 på räknarvärdet. Det är dessutom alltid denna offset.

I toppen av assemblerlistningen får man en översikt av alla interruptvektorer
och oanvända pekar på 0xfc <__bad_interrupt>. Ska kolla om LCD-biblioteket
lägger till något när det är med. Att tjuvkika bakom kulisserna kan kanske ge
information (om man inte somnat dessförinnan).

Det är nog bara om man kör timer1 utan prescaler som man behöver bry sig om
cykeltjuvarna. Det här upplägget funkar nog inte för tidmätning < 57 klockpulser.
Andra gränsen blir 4096 us om man som jag inte har brytt sig om att hantera
att timer1 rullar över, det kommer inte att hända i mitt fall, kort mätsträcka
och hög hastighet. Normalt område blir 100 - 200 m/s, 500 - 250 us (på 50 mm)

Färdigtrimmat blir det [interval_us = 62.48845 * (timer1_count + 57) / 1000]
i min kod för denna mätpryl. Mindre än 100 ns fel upp till 4000 us pulsavstånd
blir det om man använder formeln på det redan uppmätta timertiderna. De "verkliga"
tiderna mätta på HP5315A med kalibrerad OXCO (återanvänd /// GSM REFO).

... undrar om någon orkar ända hit?
Användarvisningsbild
ecenier
Inlägg: 1104
Blev medlem: 13 december 2007, 17:51:42
Ort: Älvsjö
Kontakt:

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av ecenier »

Implementera i assembler. Kan ju inte vara så svårt.
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av Icecap »

Det är i grunden fel att nollställa en timer för att ta tid.

Jag brukar använda Capture med frittlöpande timer, jag brukar då ha 2 separate Capture-ingångar.

Den första trigger en "spara detta värde (och nollställ high byte om det behövs)".
Den andra trigger samma sak fast som stoppvärde.

Dessa två funktioner är snabba och viktigast: har samma latency.

Om Capture är 16 bit och der räcker till den tid som ska mätas ska man inte blanda in high byte eller liknande, det är enbart att subtrahera första värdet från andra - unsigned.

Annars får man fibbla lite med någon high-byte som räknas upp när timern rullar över. Jag har såklart detta då tiderna kan bli längre än en timer roll-over.
Användarvisningsbild
Hedning
Inlägg: 425
Blev medlem: 27 november 2011, 15:19:00
Ort: Linköping

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av Hedning »

Det är i grunden fel att påstå något utan argumentera för vilka otäcka saker
som händer om man resettar timer1. Din kladdiga lösning är just det jag undviker.
... och min variant funkar alldeles utmärkt!
... åsså är jag "hedning" som inte har någon särskild timer-religion.
Användarvisningsbild
ecenier
Inlägg: 1104
Blev medlem: 13 december 2007, 17:51:42
Ort: Älvsjö
Kontakt:

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av ecenier »

Antingen läser du i arduino-koden vad som egentligen kompileras på en mega328, eller så skriver du just interruptdelen i assemblera och behåller resten av koden för display. På så sätt har du järnkoll på hur många cykler interruptet stjäl och som du kan kompensera för.
Användarvisningsbild
hawkan
Inlägg: 2585
Blev medlem: 14 augusti 2011, 10:27:40

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av hawkan »

Interruptoverhead (vilket språk är det egentligen) finns det helt klart.
Man jag tycket nog att Icecap har en bra lösning på det och det ska väl
gå att få in i en mega328 utan större problem.
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av Icecap »

Skillnad i latency vid "din metod" gör att "långa" tider har mycket lite fel medan det blir en offset av betydelse vid korta tider.

Om värden sparas på "mitt sätt" är latency den samma i båda fall och de nollar därför ut varandra.

Om jag inte minns fel måste man ofta stoppa timern för att kunde skriva ett värde i den, alltså kan prescaler (om använd) vara i fel läge också.

Och det går enkelt att köra med samma Capture, på varje interrupt ska man då först kopiera förra värdet ner i "Old_Value" och sedan spara det nya i "New_Value".
Användarvisningsbild
Hedning
Inlägg: 425
Blev medlem: 27 november 2011, 15:19:00
Ort: Linköping

Re: Arduino - noggrann tidmätning & interrupt

Inlägg av Hedning »

Hårdvaran testad och kalibrerad, mätsträckans längd är knepig att justera
och kommer aldrig att bli lika noggrann som tidmätningen. Bara lådifieringen
kvar och lite uppstädning av mekaniken. Sparar förslagen i tråden tills nästa
projekt som kanske behöver något liknande. Assemblerlistningen blev runt
45 A4-sidor för den slutgiltiga versionen med statistik-tillägg.
FWB-80-1.jpg
LCD-n visar skott-nr, timerpulser, mynningshastighet, Max + MIn-värde,
genomsnitt och standardavvikelse. Det som visas är för billiga skrutt-kulor
som har stor variation. Det är spridningen som är kärnpunkten i denna typ
av mätning.
FWB-80-2.jpg
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Skriv svar