Jag jobbar med att jämföra autopiloter som Ardupilot , CC3D , KK2.1.5 . Jämförelsen handlar om systemreaktioner / beteenden som den ger under flygningen. För detta ändamål måste jag läsa PWM-arbetscykeln (som osilaskop – PWM-frekvensen kan variera från 50 till 430 Hz) från autopilotkortet. Det finns 4 PWM-ingångar för kommandon och 4 PWM-styrningskontroller för en typisk fyrrotor. Jag måste läsa 8 arbetscykelvärden med digitala / analoga ingångsstift. Hur mäter jag arbetscykel på 8 PWM-signaler? Är digital eller analog mätning exakt och snabbare?
Anmärkning om attachInterrupt -kommando: Enligt arduino.cc AtMega328-serien har 2 avbrott , Arduino ATmega 2560-serien har 7 avbrott.
Svar
Koden som visas i mitt svar på fråga 18183 , ”Läs RC-mottagarkanaler med Interrupt istället för PulseIn ”. Det svaret har kod för att läsa fyra kanaler för RC PWM. Den kan enkelt anpassas för att fungera med åtta kanaler. Den har en ISR som körs när valda stift byts. Det sorterar ut vilka kanaler som har ändrats och lagrar värdet på micros()
vid varje ändring.
Se även mitt svar på fråga 19106 , ”Kan externa avbrott ELLER” d tillsammans på ”328 (Uno)?” Svaret innehåller en skiss för att generera lämplig ISR-kod. Mitt svar på fråga 32572 , ”Hur upptäcker man riktningen för en roterande kodare?”, visar en annan instans.
Digital ingång, som används i koden som nämns ovan tar under en mikrosekund tio mikrosekunder i ISR. Som noterats i dannyfs kommentar kan rullning av for
-slingan och (där det är möjligt) att använda konstanter istället för variabler minska in-ISR-tiden till 3,4 μs. lägg fortfarande till flera mikrosekunder.
10-bitars analog ingång, å andra sidan, tar cirka 104 mikrosekunder per avläsning, en tid som kan jämföras med några av de pulsbredder du kommer att mäta. Så det är inte tillräckligt snabbt. Om försämrad ADC-noggrannhet är acceptabelt kan en minskning av ADC-klockans skalfaktor som förklaras i en webbsida på microsmart.co.za kan få AD-omvandlingstid ner till 20 μs. Det här är ungefär tre gånger så lång som digital ingång tar, så ganska långsam.
Kommentarer
- > tar en mikrosekund i ISR, det tycker jag är osannolikt. Självklart är jag ' inte säker på vilka kodbitar du pratade om – som de är tre av dem. men en kausal titt på dem skulle föreslå att det kommer att ta mer än 16 fästingar för att avrätta ISR-kroppen – räknas inte omkostnaderna. Faktum är att en liten fågel av mig sa att det skulle ta nära 8us för att köra dem på en Uno, 🙂
- @dannyf, jag tittade på en av de enklare ISR: erna (räknar med en enda kodare) när jag skrev det, så måste du redigera svaret med korrekt tid. Ledsen!
- inget problem. två förslag: 1) rulla ut while-slingan; 2) använda konstanter snarare än variabler. och jag skulle också göra rcOld en statisk inuti ISR så att koden är mer modulär. med det fick jag körningstiden ner till 3.4us.
- Kan du dela din kod istället för länkar. Dessutom har AtMega328-serien 2 avbrott, Arduino ATmega 2560-serien har 7 avbrott. Så hur kan jag mäta åtta PWM-signaler samtidigt? arduino.cc/en/Reference/attachInterrupt
- @acs, ATmega328 ' har 26 olika avbrottsvektorer. Vektorerna som används i den refererade koden är för stiftbytesavbrott, eller PCINT, som använder 3 av dessa vektorer. PCINT finns på 22 av de ATmega328-baserade Nano-stiften och ett liknande antal på Uno ' s. Se koden som visas i föregående frågor – just nu har jag arbetsfrister att uppfylla.
Svar
om det görs analogt, kör pwm genom en lpf och utför en adc på utgången.
om du gör det i digital, använd en timerfångningsfunktion eller använd extern interrupt / pin-switchavbrott för att fånga tidpunkten från en tidsbas.