Hur löser ni avstudsning av kontakt i mjukvara (Arduino) IRQ
Hur löser ni avstudsning av kontakt i mjukvara (Arduino) IRQ
Så.
Jag har en liten vindsnurra med okänd typ av detektor i, två kablar, kortsluter ett okänt antal gånger varje varv.
Ska göra en enkel vindmätare av det här. Signalerna genereras på INT0, intern pullup och sensorn kortsluter mot jord.
Det verkar fungera bra - om jag bara kan bli av med kontaktstudsarna.
Programmet i all enkelhet består av en interruptrutin som mäter tiden sedan förra interrupten, flanktriggad.
Jag undrar egentligen två saker:
1) Hur löser jag avstudsningen i IRQ-rutinen, läste någonstans att man inte ska/kan använda delay() i en interruptrutin!?
2) Hur hanterar Arduino hårdvaruIRQ? Finns det någon risk att eventuella kontaktstuds kommer att buffras och trigga ytterliggare en interrupt när rutinen kört klart? Eller är alla IRQ automatiskt disablade i irq-rutinen? Eller måste jag säga åt programmet att stänga av och sätta på irq medan min rutin körs?!
Eller ska jag göra någon slags global irq-reset innan min RETI?
Jag har en liten vindsnurra med okänd typ av detektor i, två kablar, kortsluter ett okänt antal gånger varje varv.
Ska göra en enkel vindmätare av det här. Signalerna genereras på INT0, intern pullup och sensorn kortsluter mot jord.
Det verkar fungera bra - om jag bara kan bli av med kontaktstudsarna.
Programmet i all enkelhet består av en interruptrutin som mäter tiden sedan förra interrupten, flanktriggad.
Jag undrar egentligen två saker:
1) Hur löser jag avstudsningen i IRQ-rutinen, läste någonstans att man inte ska/kan använda delay() i en interruptrutin!?
2) Hur hanterar Arduino hårdvaruIRQ? Finns det någon risk att eventuella kontaktstuds kommer att buffras och trigga ytterliggare en interrupt när rutinen kört klart? Eller är alla IRQ automatiskt disablade i irq-rutinen? Eller måste jag säga åt programmet att stänga av och sätta på irq medan min rutin körs?!
Eller ska jag göra någon slags global irq-reset innan min RETI?
- PHermansson
- EF Sponsor
- Inlägg: 4340
- Blev medlem: 22 december 2004, 00:46:38
- Ort: Särestad Grästorp
- Kontakt:
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Enligt dokumentationen fungerar inte delay om man använder attachInterrupt-funktionen. Men man kan ju stänga av alla interrupts i början av interrupt-rutinen som man gör vid vanlig Mcu-programmering.
The Arduino also has the ability to temporarily ignore all the interrupts. You may want to do this if you have some sensitive code that must be executed without interruption. In this case you would issue a noInterrupts() call. Once your sensitive code block has completed, interrupts can be restarted by calling interrupts().
http://www.dave-auld.net/index.php?opti ... Itemid=107
The Arduino also has the ability to temporarily ignore all the interrupts. You may want to do this if you have some sensitive code that must be executed without interruption. In this case you would issue a noInterrupts() call. Once your sensitive code block has completed, interrupts can be restarted by calling interrupts().
http://www.dave-auld.net/index.php?opti ... Itemid=107
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Sätt en flagga som talar om att den fått ett interuppt från knappen. Om flaggan är false startar den en timer som pollar I/O porten ytterligare en gång. Är det samma värde som först kom in släpper du igenom värdet annars inte. Timern nollställer flaggan oavsett I/O portens värde. Timerns tid anpassar du till tiden det tar för kontaktstudsarna att klinga ut.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Är du säkert på att sensorn studsar? låter inte som någon vidare bra rotationssensor.
För att avstudsa skulle du kunna prova med något sånt här:
Initiering: Ställ in att få interrupt på nedåtgående flank.
INT0-interrupt: Stäng av INT0. Ställ in en timer att ge interrupt ~10ms senare. Spara tiden/beräkna perioden.
Timer-interrupt: Aktivera INT0 med triggning på uppåtgående flank.
INT0-interrupt: Stäng av INT0. Ställ in en timer att ge interrupt ~10ms senare.
Timer-interrupt: Aktivera INT0 med triggning på nedåtgående flank.
PHermansson: Det där ser ut som något som ska användas i main-programmet. Interrupten är avstängda i interrupt-rutinen om man inte avsiktligt ändrar Interrupt-flaggan.
För att avstudsa skulle du kunna prova med något sånt här:
Initiering: Ställ in att få interrupt på nedåtgående flank.
INT0-interrupt: Stäng av INT0. Ställ in en timer att ge interrupt ~10ms senare. Spara tiden/beräkna perioden.
Timer-interrupt: Aktivera INT0 med triggning på uppåtgående flank.
INT0-interrupt: Stäng av INT0. Ställ in en timer att ge interrupt ~10ms senare.
Timer-interrupt: Aktivera INT0 med triggning på nedåtgående flank.
PHermansson: Det där ser ut som något som ska användas i main-programmet. Interrupten är avstängda i interrupt-rutinen om man inte avsiktligt ändrar Interrupt-flaggan.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Då du använder Capture-funktionen ("...som mäter tiden sedan förra interrupten...") är det ganska enkelt:
Om tiden är för kort avslutas "denna" interrupt utan ytterligare åtgärder.
Detta sätt använder jag ofta, speciellt när jag använder en riktig Capture-funktion.
Man kan såklart expandera det hela lite och "mellanspara" en variabel som innehåller tiden sedan förra interrupt, oavsett om den interrupt var "rätt" eller fel.
Men en hårdvara-debounce är också en attraktiv lösning! ICM7555 kan vara en hjälp där, den kan triggas av sensorn och då ge en fast puls som är längre än stutsen, sedan är saken biff.
Om tiden är för kort avslutas "denna" interrupt utan ytterligare åtgärder.
Detta sätt använder jag ofta, speciellt när jag använder en riktig Capture-funktion.
Man kan såklart expandera det hela lite och "mellanspara" en variabel som innehåller tiden sedan förra interrupt, oavsett om den interrupt var "rätt" eller fel.
Men en hårdvara-debounce är också en attraktiv lösning! ICM7555 kan vara en hjälp där, den kan triggas av sensorn och då ge en fast puls som är längre än stutsen, sedan är saken biff.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Jag ser hårdvarulösningen som en sista utväg... Mest för att det känns som att det *borde* gå att lösa i mjukvara...
Sensorn är en sådan här: http://shop.floridautomatedshade.com/Re ... 050110.htm
Satt kopplad till vår gamla markis, tänkte att man kunde använda den i stället för att slänga på tippen.
Snurrar jag den långsamt så får jag allt mellan 1 och 14 pulser per varv så nog studsar det alltid...
Använda timer kan vara en lösning ja. Tipset att mäta tiden och hoppa ur om den är för kort är också bra..
Men då måste jag först forska fram vad en "rimlig" tid är... och det enklaste sättet vore ju att mäta live, fast det kan jag ju inte göra nu när den studsar och då blir det moment 22. ;.)
Får testa mig fram helt enkelt.
Sensorn är en sådan här: http://shop.floridautomatedshade.com/Re ... 050110.htm
Satt kopplad till vår gamla markis, tänkte att man kunde använda den i stället för att slänga på tippen.
Snurrar jag den långsamt så får jag allt mellan 1 och 14 pulser per varv så nog studsar det alltid...
Använda timer kan vara en lösning ja. Tipset att mäta tiden och hoppa ur om den är för kort är också bra..
Men då måste jag först forska fram vad en "rimlig" tid är... och det enklaste sättet vore ju att mäta live, fast det kan jag ju inte göra nu när den studsar och då blir det moment 22. ;.)
Får testa mig fram helt enkelt.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Hm, det är alltså en reed-switch.
Fann den här sidan när jag googlade efter info om sensorn.
http://www.qsl.net/on7eq/projects/arduino_davis.htm
Där används 15ms som avstudsning, samt ett en liten konding för att filtera bort det värsta. Men koden i övrigt verkar inte vara något att utgå ifrån, tycker jag.
Fann den här sidan när jag googlade efter info om sensorn.
http://www.qsl.net/on7eq/projects/arduino_davis.htm
Där används 15ms som avstudsning, samt ett en liten konding för att filtera bort det värsta. Men koden i övrigt verkar inte vara något att utgå ifrån, tycker jag.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Det enklaste sättet jag brukar använda är att nyttja millis() parametern (En konstant räknare som räknar upp antal millisekunder som gått efter uppstart).
Skapa en variabel som heter typ debounce eller nå.
Skapa en variabel som heter typ check eller nå.
Sätt variabeln debounce till hur lång tid du vill skall gå mellan att du accepterar knapptryck.
Vi knapptryck
Vid varje del som omfattar knapptryck, kolla om "check" är större än millis() innan du gör något.
Varje gång du agerar på en knapp sätt check=millis() + debounce.
Observera att check behöver vara av typen long och millis() är long, så metoden snor lite cykler, men i 99% av fallen är detta inte ett problem då beräkning enbart sker vid knapptryckningar.
Skapa en variabel som heter typ debounce eller nå.
Skapa en variabel som heter typ check eller nå.
Sätt variabeln debounce till hur lång tid du vill skall gå mellan att du accepterar knapptryck.
Vi knapptryck
Vid varje del som omfattar knapptryck, kolla om "check" är större än millis() innan du gör något.
Varje gång du agerar på en knapp sätt check=millis() + debounce.
Observera att check behöver vara av typen long och millis() är long, så metoden snor lite cykler, men i 99% av fallen är detta inte ett problem då beräkning enbart sker vid knapptryckningar.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Då det rör sig om en interrupt som triggas av sensorn är delay inne i ISR'n inte att föredra!
Då det inte finns information om hur fort pulserna kan komma är det ganska svårt att ge rätt råd men om vi utgår ifrån 15ms som debounce-tid samt att PRF'en inte är kortare än 30ms blir det inte så svårt!
För varje sensor-interrupt ska en timer laddas med ett värde som bör vara 10 eller gärna(!) högre. Dess räknefrekvens ska vara så att värdet-1 ihop med frekvensen säkrar en time-out på 16ms eller så, alltså aningen mer än den maximala debounce-tid.
När timern sedan har räknat till noll (alltså ger interrupt) har den varit omstartsfri i 16ms, därmed har man en "ren" puls. I timerns interruptrutin stoppas timern och det flaggas för en puls på något vis.
Men det är en sak som får mig att fundera på om inte informationen är lite väl sparsam...
"...som mäter tiden sedan förra interrupten..."
Hur ska det ske?
Är det en Capture-funktion är det ju hur enkelt som helst att lösa utan en massa delay o skit:
1: Läs Capture-tiden.
2: Jämför den med "Förra Capture-tiden".
3: Är den kortare än 15ms gå till punkt
4: Markera för en start på puls vid att använda differensen som värde.
5: Spara den lästa Capture-tiden som "Förra Capture-tiden".
Klart! Ingen delay eller annan osäkerhet, bara snabb behandling av värdet.
Då det inte finns information om hur fort pulserna kan komma är det ganska svårt att ge rätt råd men om vi utgår ifrån 15ms som debounce-tid samt att PRF'en inte är kortare än 30ms blir det inte så svårt!
För varje sensor-interrupt ska en timer laddas med ett värde som bör vara 10 eller gärna(!) högre. Dess räknefrekvens ska vara så att värdet-1 ihop med frekvensen säkrar en time-out på 16ms eller så, alltså aningen mer än den maximala debounce-tid.
När timern sedan har räknat till noll (alltså ger interrupt) har den varit omstartsfri i 16ms, därmed har man en "ren" puls. I timerns interruptrutin stoppas timern och det flaggas för en puls på något vis.
Men det är en sak som får mig att fundera på om inte informationen är lite väl sparsam...
"...som mäter tiden sedan förra interrupten..."
Hur ska det ske?
Är det en Capture-funktion är det ju hur enkelt som helst att lösa utan en massa delay o skit:
1: Läs Capture-tiden.
2: Jämför den med "Förra Capture-tiden".
3: Är den kortare än 15ms gå till punkt
4: Markera för en start på puls vid att använda differensen som värde.
5: Spara den lästa Capture-tiden som "Förra Capture-tiden".
Klart! Ingen delay eller annan osäkerhet, bara snabb behandling av värdet.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Enda nackdelen med det där är väl att det kan bli en väldans massa interrupts ifall brytaren studsar mycket.
Om man stänger av capture i 15ms efter flanken så blir det max 2 interrupt per varv, ett vid flanken, och ett efter 15 ms.
Om man stänger av capture i 15ms efter flanken så blir det max 2 interrupt per varv, ett vid flanken, och ett efter 15 ms.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Och? µC'n kör ju ändå och en interrupt är snabbt avklarat ändå, mycket snabbare än 15ms delay!
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Ja, antagligen tar det inte så mycket kraft att behandla studsarna. Ett interrupt på en AVR har overhead på runt 30 cykler, så med 10 studs blir det 300 cykler + tiden det tar att köra själva koden, så det kanske blir 500 cykler. Och det är antagligen helt obetydligt. Men det är roligt att fnula på olika lösningar.
Jag menar inte att den ska ligga och loopa i 15 ms i interruptet. I capture-interruptet kan man byta till compare, och sätta tiden till 15ms framåt. I compare interruptet byter man sedan tillbaka till capture igen.
Jag menar inte att den ska ligga och loopa i 15 ms i interruptet. I capture-interruptet kan man byta till compare, och sätta tiden till 15ms framåt. I compare interruptet byter man sedan tillbaka till capture igen.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
Många bra tips.
Min första tanke var att räkna pulser under en viss tid men den enklare lösningen blir nog att mäta tiden mellan två pulser.
Således, IRQ vid varje puls, mät tiden från föregående puls och är den för kort så anta att det bara var kontaktstuds.
Dessvärre ger min vindsnurra fyra pulser per varv så vi pratar relativt korta pulstider, jag har nog inte råd med mer tid för avstuds än ca 5ms.
Min första tanke var att räkna pulser under en viss tid men den enklare lösningen blir nog att mäta tiden mellan två pulser.
Således, IRQ vid varje puls, mät tiden från föregående puls och är den för kort så anta att det bara var kontaktstuds.
Dessvärre ger min vindsnurra fyra pulser per varv så vi pratar relativt korta pulstider, jag har nog inte råd med mer tid för avstuds än ca 5ms.
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
En förutsättning är självklart att det finns fysiska möjligheter att
över huvutaget se skillnad på en kontaktstuds och "nästa puls" !!
Gör det inte det så kan ingen lösning i världen hjälpa dig...
över huvutaget se skillnad på en kontaktstuds och "nästa puls" !!
Gör det inte det så kan ingen lösning i världen hjälpa dig...
Re: Hur löser ni avstudsning av kontakt i mjukvara (Arduino)
laban12, kasta den där enkodern i junkboxen och skaffa en bättre som inte studsar fullt så mycket. Eller så sätter du ingång och experimenterar med den du har istället för att fortsätta och diskutera ditten och datten i tråden. Mera verkstad och mindre prat är ett koncept som ofta leder till framgång.
När det dyker upp problem som du försökt finna lösningar på utan att lyckas återkommer du till tråden med en tydlig beskrivning av problemställningen och gärna med bifogad kjällkod. Gör du på detta vis är jag helt övertygad om att du kommer att lyckas med ditt projekt.
Ovanstående ett framgångsrecept som en del andra har använt här i forumet många gånger och såvitt jag kan se har de flesta lyckats med sina projekt när de använder mera verksatd och mindre prat. Om du emellertid har som mål att enbart diskutera olika lösningar i denna tråd snarere än att få något konktret utfört i ditt så är det givetvis bara att forsätta med att göra olika inlägg i din tråd.
För övrigt önskar jag dig lycka till med projektet. Det skall bli spännande att se hur du lyckas oavsett vilken väg du väljer lösa enkoderproblematiken.
När det dyker upp problem som du försökt finna lösningar på utan att lyckas återkommer du till tråden med en tydlig beskrivning av problemställningen och gärna med bifogad kjällkod. Gör du på detta vis är jag helt övertygad om att du kommer att lyckas med ditt projekt.
Ovanstående ett framgångsrecept som en del andra har använt här i forumet många gånger och såvitt jag kan se har de flesta lyckats med sina projekt när de använder mera verksatd och mindre prat. Om du emellertid har som mål att enbart diskutera olika lösningar i denna tråd snarere än att få något konktret utfört i ditt så är det givetvis bara att forsätta med att göra olika inlägg i din tråd.
För övrigt önskar jag dig lycka till med projektet. Det skall bli spännande att se hur du lyckas oavsett vilken väg du väljer lösa enkoderproblematiken.