Entweder ist heute einfach zu warm oder ich weiß auch nicht, ich grübel gerade über ein Problem: Ich möchte drei PWM Signale / Kanäle von einem RC Empfänger mit einem AVR (Atmega32u4). Da es ein Road-Empfänger ist (Spektrum SRS) bekomme ich von dem Empfänger kein PPM Summensignal, sondern kann nur die drei Kanäle einzeln einlesen. Wie beim RC üblich folgen die Kanäle jedoch aufeinander, sprich erst kommt Signal von Kanal 1 dann 2 dann 3 dann 4. Jedoch halt nicht in einem Summensignal. Ich dachte mir im Ablauf folgendes: - Die drei Kanäle auf externe Interrupts legen Int0 = Kanal 1 Int1 = Kanal 2 Int2 = Kanal 3 - Timer laufen lassen zur Zeitmessung Entweder 16Bit Timer, zwecks Auflösung oder den 10Bit Timer in 64Mhz (Wird wahrscheinlich zu schnell sein) - Bei einem High Interrupt (z.b. Int0) Timer auf 0 setzen - Bei einem Low Interrupt (z.b. Int0) Timer auslesen Da ja nun keine der Signale auf einmal "zuschlagen", müsste dies doch eigentlich relativ einfach machbar sein? Ich kann ja nur die Highimpulse messen, da die Low-Zeiten sich ja auch mit der PWM der anderen Kanäle ändert. Diese bleibt ja nicht gleich. Hab ich da einen Denkfehler drinn? Oder misst man eine PWM anders? Wie kann ich mit nur einem Timer die drei Kanäle separieren?
Wenn Du Timer1 verwendest, kannst Du die ADC-Eingänge als input-capture Eingänge verwenden. Dazu muß noch der Analogkomparator aktiviert werden.
m.n. schrieb: > Wenn Du Timer1 verwendest, kannst Du die ADC-Eingänge als input-capture > Eingänge verwenden. Dazu muß noch der Analogkomparator aktiviert werden. Danke, das wäre natürlich auch ein schöner Ansatz! Jedoch kann ich ja lediglich PD4 (ICP1) dafür verwenden. Der gesamte Port jedoch geht ja nicht oder?!
Draco schrieb: > Ich möchte drei PWM Signale / Kanäle von einem RC Empfänger mit einem > AVR (Atmega32u4). Da es ein Road-Empfänger ist (Spektrum SRS) bekomme > ich von dem Empfänger kein PPM Summensignal, sondern kann nur die drei > Kanäle einzeln einlesen. > > Wie beim RC üblich folgen die Kanäle jedoch aufeinander, sprich erst > kommt Signal von Kanal 1 dann 2 dann 3 > Wie kann ich mit nur einem Timer die drei Kanäle separieren? Mit nur einem Timer, ja. Mit nur einem ICP-Kanal, nein. Allerdings reichen zwei ICP-Kanäle für 3 Fernsteuerkanäle. Denn die L->H Flanke von Kanal 2 fällt mit der H->L Flanke von Kanal 1 zusammen und die H->L Flanke von Kanal 2 mit der L->H Flanke von Kanal 3. Es reicht also, steigende und fallende Flanken von Kanal 1 und Kanal 3 auszumessen. Kanal 2 ergibt sich durch simple Rechnung. Mit etwas Aufwand auf der Hardwareseite reicht ein einzelner ICP-Kanal. Dazu muß man nur von jedem Fernsteuerkanal ein Monoflop triggern lassen (mit der steigenden Flanke) und die Monoflop-Impulse addieren. Schon ist es wieder ein PPM-Signal. Im einfachsten Fall reichen dazu 3 npn-Transistoren als wired-OR und je ein CR-Differenzierglied vor jeder Transistorbasis.
Das sollte mit den 3 Interrupts so zu machen sein: Hauptprogramm: Initialisiere INT0 auf steigende Flanke und Freigeben. ISR INT0: * setze Timer 1 auf null und starte ihn. MerkeFlag löschen. * Sperre mich selber und konfiguriere INT1 auf steigende Flanke ISR INT1: * Stopp und lese timer1 und speicher das unter PWM1 Länge * Reset Timer1 und starten * Mich selber sperren und INT2 auf steigende Flanke konfigurieren ISR INT2: Wenns Flag nicht gesetzt ist * Stopp und lese timer1 und speicher das unter PWM2 Länge * Reset Timer und starten * Mich auf fallende Flanke konfigurieren. Flag setzen. wenn Flag gesetzt ist * Stopp und lese timer1 und speicher das unter PWM3 Länge * Sperre mich und gebe INT0 mit steigender Flanke frei.
Matthias S. schrieb: > ISR INT0: > * setze Timer 1 auf null und starte ihn. MerkeFlag löschen. ... > ISR INT1: > * Stopp und lese timer1 und speicher das unter PWM1 Länge > * Reset Timer1 und starten ... Nein. Warum sollte man den Timmer immer rücksetzen und neu starten? Einen Timer läßt man ganz einfach durchlaufen. Bei einer Frequenz die hoch genug für die gewünschte Zeitauflösung ist. Und dann liest man ihn in der ISR aus (bzw. läßt die ICP-Unit den Zähler in ein Capture-Register sichern). Wenn man dann 2 oder mehr solche Timestamps hat, kann man die Zeitspanne zwischen zwei Ereignissen ganz einfach ausrechnen, indem man die Zählerstände subtrahiert. So lange zwischen zwei Ereignissen maximal ein Umlauf des Zählers stattfindet, wird auch der Überlauf von der (unsigned) Subtraktion korrekt berücksichtigt. Für die Erfassung eines PPM Signals sollte eine Auflösung von 1µṣ bei weitem ausreichen und läßt bei Verwendung eines 16-Bit Timers mehr als genug Luft. Dann hat man 1000 bis 2000 Ticks des Timers pro Impuls. Und eine Auflösung von 0.1% respektive 10 Bit.
Axel S. schrieb: > Warum sollte man den Timmer immer rücksetzen und neu starten? Du hast dann drei fertige Werte ohne rumrechnen und kannst direkt damit weiterarbeiten. Das Stoppen, Lesen und Reset eines Timers ist in 3 Zeilen erledigt und wenns platzmässig eng wird, auch in einem Unterprogramm für alle drei ISR gemeinsam machbar. Es ist ausserdem eine höhere Auflösung möglich, da man wirklich nur die max. 2ms erfassen muss und nicht den gamzen 20ms Frame, wenn man hohe Auflösung haben möchte. Da muss man nicht kunstvoll den Timer mit ICP laufen lassen und externe Hardware dazu basteln, denn das ganze läuft so auf der Hardware, die der TE schon hat.
:
Bearbeitet durch User
Matthias S. schrieb: > Axel S. schrieb: >> Warum sollte man den Timmer immer rücksetzen und neu starten? > > Du hast dann drei fertige Werte ohne rumrechnen und kannst direkt damit > weiterarbeiten. Oh, hast Du Angst vor simplen Subtraktionen? Draco schrieb: > Der gesamte Port jedoch geht ja > nicht oder?! Es würde auch mit Pin Change Interrupts gehen; nicht so genau und abhängig von anderen Interrupts im Programm. Axel S. schrieb: > Allerdings > reichen zwei ICP-Kanäle für 3 Fernsteuerkanäle. Dann könnte man ICP1 und den AIN0 verwenden, die man intern umschalten kann.
m.n. schrieb: > Oh, hast Du Angst vor simplen Subtraktionen? Nö, aber warum, wenns gar nicht nötig ist. Ihr tut ja gerade so, als darf man um Gottes Willen keinen Timer stoppen und zurücksetzen. Das ist einfach und geradeaus, jegliche Umverdrahtung entfällt, die drei INTs haben sowieso hohe Priorität und kommen sich auch nicht ins Gehege. Warum also kompliziert, wenns auch einfach geht.
Matthias S. schrieb: > Nö, aber warum, wenns gar nicht nötig ist. Ihr tut ja gerade so, als > darf man um Gottes Willen keinen Timer stoppen und zurücksetzen. Du darfst sowieso Alles machen ;-) Aber warum sollte man einen Timer derart behandeln, daß er zu sonst nichts mehr nützlich ist. Lasse ihn mit höchster Geschwindigkeit durchlaufen und Du kannst damit einen 1 ms Tick erzeugen, die PMW-Ausgänge verwenden, und und und.
Matthias S. schrieb: > Axel S. schrieb: >> Warum sollte man den Timmer immer rücksetzen und neu starten? > > Du hast dann drei fertige Werte ohne rumrechnen und kannst direkt damit > weiterarbeiten. Wirklich? Dein µC kann nicht subtrahieren? > Das Stoppen, Lesen und Reset eines Timers ist in 3 > Zeilen erledigt und wenns platzmässig eng wird, auch in einem > Unterprogramm für alle drei ISR gemeinsam machbar. Das ist nicht der Punkt. Beim Zurücksetzen des Timers verlierst du Ticks. Mit einem durchlaufenden Timer und Capture aber nicht. > Es ist ausserdem eine höhere Auflösung möglich, da man wirklich nur die > max. 2ms erfassen muss und nicht den gamzen 20ms Frame, wenn man hohe > Auflösung haben möchte. Ich verstehe dein Argument nicht. Abgesehen davon, daß die Auflösung nur von der Timer-Frequenz abhängt. Und daß die Genauigkeit bei durch- laufendem Timer und Capture natürlich besser ist. Weil meine keine Ticks verliert und die Latenz der ISR dann keinen Einfluß hat. > Da muss man nicht kunstvoll den Timer mit ICP laufen lassen Ich verrate dir mal ein Geheimnis: ICP und OC sind Grundfunktionen der Timer. Die wurden extra dafür gebaut. Die Verwendung dieser Features ist in etwa so "kunstvoll" wie das Einlegen des zweiten Gangs beim Auto. So wie du redest fährst du wahrscheinlich alle Strecken nur im ersten Gang? > und externe Hardware dazu basteln Für die Verwendung von ICP braucht man genau gar keine extra Hardware. Die braucht man nur, wenn man ICP-Kanäle sparen will/muß.
m.n. schrieb: > Du darfst sowieso Alles machen ;-) > Aber warum sollte man einen Timer derart behandeln, daß er zu sonst > nichts mehr nützlich ist. Lasse ihn mit höchster Geschwindigkeit > durchlaufen und Du kannst damit einen 1 ms Tick erzeugen, die > PMW-Ausgänge verwenden, und und und. Das ist schon richtig, aber was mach, wenn ich während eines Zyklus einen Timer-Überlauf habe? Dieser muss ja auch separat abgefangen werden (Wenn TimerStart < TimerStop). Das bedingt ja in der ISR eine weitere Abfrage. Die drei PWM Kanäle extern zu einem PPM Summensignal zusammenzufassen, wäre echt ne schöne Spielerei, kann man sich vielleicht mal auf die Agenda schreiben. Aber für das aktuelle vorhaben zu overkill. An die Pin-Change-Interrupts hatte ich anfänglich auch gedacht, der Vorteil davon wäre: Ich könnte natürlich mehr als 3 Kanäle einfach abfragen. Der Nachteil, die PCInt könnten nur allgemein Flankenwechsel auf dem gesamten Port/Pin feststellen. Da mach ich mir wieder mehr Arbeit mit Abfragen / Schleifen (Welcher Pin hat getoggelt etc..) als es nötig ist, da die meisten Empfänger eh bloß auf max. 4 Kanälen laufen, man aber zu 90% nur zwei davon nutzt. Ich selber benötige bloß zwei (Richtung, Lenkung) und habe den dritten als Reserve für eventuell... andere Dinge :-D Eine Idee wäre auch gewesen den Timer ausschließlich beim ersten Kanal auf null zu setzen und die zwei restlichen Kanäle dann zu dividieren. Ein "festes" Zeitfenster von den üblichen 22ms von RC Empfängern kann ich auch nicht vorlegen, da z.b. Spektrum (Einstellungssache) auch mit 16,5ms und 11ms für ein vollständiges Frame fährt. Ich werde nun mal die drei Versionen umsetzen und ausprobieren: 1.) Timer bei jedem Kanal löschen und setzen (Matthias seine Version) 2.) Den Timer komplett durchlaufen lassen (Axels Version) 3.) Den Timer nur beim High am ersten Kanal zurücksetzen Die Version mit dem Analog Komparator hebe ich mir mal für später auf.
Draco schrieb: > mit einem AVR (Atmega32u4). Was soll der sonst noch tun? Wie genau muss die Zeit ermittelt werden? Hintergrund: wenn du sonst nicht viel zu tun hast, dann kannst du einfach die Eingänge pollen... Matthias S. schrieb: > Ihr tut ja gerade so, als darf man um Gottes Willen keinen Timer > stoppen und zurücksetzen. Würde ich auch nie tun. Denn dadurch hast du potentiell den doppelten Jitter: einmal beim Zurücksetzen und einmal beim Auslesen. Mal ein Beispiel: Wenn man die Aufgabe hat, etwas jede Stunde zu tun, dann setzt man ja auch nicht jede Stunde seine Armbanduhr auf 0 Minuten zurück, sondern lässt sie einfach durchlaufen. Wenn man dann z.B. um 9 Uhr auf dem Klo sitzt und mal 3 Minuten zu spät kommt, kann man diesen Fehler um 10 Uhr wieder korrigieren. Hätte man um 9 die Uhr zurückgesetzt, dann würde sich so ein Fehler aufsummieren... Fazit: Timer laufen durch. Zeiten werden durch Differenzen berechnet.
Draco schrieb: > Das ist schon richtig, aber was mach, wenn ich während eines Zyklus > einen Timer-Überlauf habe? Dieser muss ja auch separat abgefangen werden > (Wenn TimerStart < TimerStop). Das bedingt ja in der ISR eine weitere > Abfrage. > ..... > An die Pin-Change-Interrupts hatte ich anfänglich auch gedacht, der > Vorteil davon wäre: Ich könnte natürlich mehr als 3 Kanäle einfach > abfragen. Der Nachteil, die PCInt könnten nur allgemein Flankenwechsel > auf dem gesamten Port/Pin feststellen. Wie man Timer Überläufe und div. PCINTs handhaben kann, kannst Du hier sehen: Beitrag "4-Kanal Drehzahlmessung mit ATmega88" Auf einem ATmega88 läuft Timer1 frei durch - Überläufe werden gezählt und verrechnet - und liefert die Zeitbasis für 4-Kanäle zur Drehzahlmessung (intern sind es Perioden), wobei die Signale per PCINT erkannt werden. Alles kein Hexenwerk!
Lothar M. schrieb: > Was soll der sonst noch tun? Wie genau muss die Zeit ermittelt werden? > Hintergrund: wenn du sonst nicht viel zu tun hast, dann kannst du > einfach die Eingänge pollen... Das sehe ich später, je nachdem wie Performant das ganze ist. Entweder per LUFA HID an den Rechner weiterleiten lassen, oder aber per UART rüberschicken. Eines von beiden, "mehr" hat er nicht zu tun. Lothar M. schrieb: > Fazit: Timer laufen durch. Zeiten werden durch Differenzen berechnet. Ja ich sehe das alles ein, jedoch stellt sich mir da folgendes Problem. Bei der (z.b. Kanal1) High-Flanke steht der Timer bei 65000 - bei der Low-Flanke steht dann, durch den Überlauf bedingt, der Timer bei 1000. Da muss ich ja in jeder ISR erst eine Abfrage machen ob denn der Start-Timer größer als der Stop-Timer ist, dies dann wieder subtrahieren. Ein Normalfall wäre ja: High = 2000, Low = 3000 - Differenz: 3000-2000 = 1000. ... Moment... wenn ich ja nen uint16 subtrahiere, läuft die Variable ja so oder so auch über, auch ins negative rein. Sprich: uint16 1000-65000 = 535 Oder sehe ich das falsch? Das der Überlauf nur nach "oben" geht?
Draco schrieb: > Das der Überlauf nur nach "oben" geht? Jetzt hast du es: da ist kein zusätzlicher Aufwand da, wenn man nur mit Differenzen rechnet. Binär sieht das so aus: 1000 - 65000 --> 0x03E8 - 0xFDE8 = 0x0600 (+ "Unterlauf"-Flag, das keinen interessiert) Nur darf du eben nicht der zweite Zeitpunkt den ersten "überholen"...
:
Bearbeitet durch Moderator
Draco schrieb: > m.n. schrieb: >> Du darfst sowieso Alles machen ;-) >> Aber warum sollte man einen Timer derart behandeln, daß er zu sonst >> nichts mehr nützlich ist. Lasse ihn mit höchster Geschwindigkeit >> durchlaufen und Du kannst damit einen 1 ms Tick erzeugen, die >> PMW-Ausgänge verwenden, und und und. > > Das ist schon richtig, aber was mach, wenn ich während eines Zyklus > einen Timer-Überlauf habe? Dieser muss ja auch separat abgefangen werden Nein, muß er nicht. Schrieb ich oben schon.
1 | #include <stdio.h> |
2 | int main() |
3 | {
|
4 | unsigned short t1= 0xFFF0; |
5 | unsigned short t2= 0x0100; |
6 | printf("zwischen Zählerstand %hu und %hu liegen %hu Ticks\n", |
7 | t1, t2, t2-t1); |
8 | }
|
1 | $./test |
2 | zwischen Zählerstand 65520 und 256 liegen 272 Ticks |
> Die drei PWM Kanäle extern zu einem PPM Summensignal zusammenzufassen, > wäre echt ne schöne Spielerei, kann man sich vielleicht mal auf die > Agenda schreiben. Aber für das aktuelle vorhaben zu overkill. Eigentlich nicht. Mir ist auch immer noch nicht klar, warum es unmöglich sein soll, an das originale PPM-Signal zu kommen. Ansonsten ist das auch nicht sonderlich aufwendig:
1 | .---------------------*--- ... |
2 | C | C | |
3 | Kanal 1 --||--*--|< Kanal 2 --||--*--|< |
4 | | |e | |e |
5 | R | R | |
6 | | | | | |
7 | GND GND GND GND |
Pro Kanal ein kleiner Kondensator, sagen wir mal 1nF und ein Widerstand, sagen wir 10K und ein Transistor wie BC546 oder n-FET wie BSS138. An die verbundenen Kollektoren (Drains) noch einen Pullup und schon hat man ein (invertiertes) PPM-Signal, das man mit einem einzigen Pin und ICP auf die fallenden Flanken simpelst auswerten kann. > An die Pin-Change-Interrupts hatte ich anfänglich auch gedacht, der > Vorteil davon wäre: Ich könnte natürlich mehr als 3 Kanäle einfach > abfragen. Das halte ich nun wieder für dämlich. Das skaliert nämlich nicht, wenn du für jeden weiteren Kanal einen Pin um µC brauchst. Die Hardware- Variante von oben braucht lediglich weitere drei Bauteile pro Kanal.
m.n. schrieb: > Axel S. schrieb: >> Das halte ich nun wieder für dämlich. > > Du meintest sicherlich 'ungeschickt'? Meinetwegen ;)
Lothar M. schrieb: > Fazit: Timer laufen durch. Zeiten werden durch Differenzen berechnet. Wie soll denn bitte durchs Zurücksetzen 'Jitter' entstehen (davon mal abgesehen, das wir hier höchstens von ein/zwei Takten reden und das bei RC Signalen überhaupt keine Rolle spielt - jeder Joystick im Sender ist viel ungenauer) Der Vorgang des Timer Stoppens und Lesens dauert immer haargenauso lang und geht deswegen als Konstante ein. Die einzige Unsicherheit ist das Auftreten des IRQ innerhalb eines 2 oder 3 byte Befehls. Und das kannste knicken, das sind die o.a. 1-3 Takte Unsicherheit. Würde der MC mit 32kHz laufen, macht sich das evtl. sogar bemerkbar - aber schon bei 1MHz kannste es vergessen. Und beim Tiny, der gar kein ICP hat, musste ich es auch schon so machen (Servoelektronik) und das funktioniert ganz prima.
Also, ich habe nunmal nen Probelauf gemacht und bin eigentlich schon ganz zufrieden damit. Den Timer setze ich aktuell bei der ersten rissing edge an Kanal 1 wieder auf 0 zurück. Das Problem was besteht, ist der mehrmalige Überlauf während der Pulsepause zwischen Kanal3 und zurück zum Kanal1. Das kann man zwar umgehen indem man ein Counter beim Überlauf hochzählen läßt, was man dann aber wiederrum dividieren muss im ersten Kanal. In dem Screenshot sieht man die Ausgabe auf die UART, jede Zahl ist ein Kanal. Das der mittlere Kanal (Gas/Bremse) eine andere Auflösung hat, liegt an dem Spektrum Sender (DX4S auf 11ms). Axel S. schrieb: > Eigentlich nicht. Mir ist auch immer noch nicht klar, warum es unmöglich > sein soll, an das originale PPM-Signal zu kommen. Da dies sich im RC-Car Bereich nicht durchgesetzt hat. Dort gibt es kein PPM Signal bei Spektrum, wird durch den Empfänger gar nicht ausgegeben. Wie dies nun bei den anderen aussieht, kann ich garnicht genau sagen. Futaba zumindest bietet dies auch bei seinen Surface-Receivern nicht an. Bei den Air-Receivern ist dies Standart, ich weiß.
Draco schrieb: > Ich möchte drei PWM Signale / Kanäle von einem RC Empfänger mit einem > AVR (Atmega32u4). Aha ...!? Was ist das Ziel? Du brauchst das PPM-Signal? Das ist ein EXOR Baustein!
1 | ____ |
2 | Kanal 1 o---| =1 | ____ |
3 | | |----,-------| =1 | |
4 | Kanal 3 o---|____| | | |----o PPM |
5 | R ,---|____| |
6 | | | |
7 | +---' |
8 | | |
9 | C |
10 | | |
11 | GND |
Die andere Richtung geht mit einem 4017. Gruß Jobst
Matthias S. schrieb: > Wie soll denn bitte durchs Zurücksetzen 'Jitter' entstehen Wenn das Zurücksetzen z.B. durch einen Interrupt verzögert wird: der Pinchange-Interrupt kommt, wird aber erst ein paar Takte später abgearbeitet, weil gerade noch ein SIO-Interrupt "dran" ist. Dann kommst du ein paar Takte zu spät und setzt damit deine "Uhr" (=Timer) zu viel zurück. Oder auch so: wenns es im Langsamen schon mit der Armbanduhr schief gehen wird, dann geht es sicher auch im Schnellen mit dem uC-Timer schief. Das merkt man natürlich nicht sofort (in der Anwendung hier mit einem exklusiven Timer für die Aufgabe gar nicht), aber einzelne Takte summieren sich auf. Und wenn man mehrere solcher Messungaufgaben parallel machen möchte, aber nur wenige Timer hat, dann bleibt einem gar nichts Anderes übrig, als mit einer durchlaufenden Uhr zu arbeiten. Oder was wäre, wenn es nur 1 Kirchenuhr im Dorf gibt, aber jeder zum Eierkochen die Kirchenuhr auf 0:00 stellen würde? Dann müssten alle nacheinander ihre Eier kochen und hinterher wüsste niemand mehr, wie spät es ist... Draco schrieb: > Das Problem was besteht, ist der mehrmalige Überlauf während der > Pulsepause zwischen Kanal3 und zurück zum Kanal1. Warum lässt du den Timer nicht einfach langsamer laufen? So, dass ein kompletter Zyklus ohne Überlauf da rein passt? Oder warum startest du als Kompromiss nicht den Timer m Kanal 1, lässt ihn einmal hochlaufen und nimmst den Überlauf als Synchronisationshilfe: nach einem Überlauf kommt wieder der Kanal 1.
:
Bearbeitet durch Moderator
So.. ich hatte dann heute erstmal ein kleines Problem. Beitrag "Atmel Installation mit "An Error occured - AVR8 Device support" beheben" Ich werde das morgen alles nochmal durchtesten.
Draco schrieb: > Das kann man zwar umgehen indem man ein Counter beim Überlauf hochzählen > läßt, was man dann aber wiederrum dividieren muss im ersten Kanal. Wo muß man denn da etwas dividieren? Lass zur Not den Timer langsamer laufen, was aber nicht sehr elegant ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.