Hallo zusammen, Ich will mit meinem Atmega8 die Pulslänge eines RC-Empfängers messen, das Signal ist zwischen 1ms und 2ms lang. Ich nutze dazu den PinD2 mit aktiviertem Interrupt. Das InterruptFlag wird bei steiler Flanke gesetzt und dann in den Interrupt-Handler gesprungen. Dort wird der Timer eingeschaltet und zählt solange, bis der Port wieder low (0) ist. Den Wert aus TCNT0 schiebe ich dann in ein Register, deaktiviere den Timer und reinige dann das Register TCNT0 von "Messrückständen". Soweit zur Theorie, das Programm läuft auch im Simulator vom AVR-Studio sauber durch, eben genau so wie es oben steht. Nur auf dem µC hängts dann, hat jemand ne Idee, worans liegen könnte? Die Source hängt im Anhang... Danke schonmal für Eure Hilfe, Grüße, Hanno
Warum nicht Input Capture Unit benutzen? Ist der ICP-Pin oder der Timer schon anderweitig verplant? Einfacher gehts doch nicht... Gruß Johnny
Ich könnte natürlich auch die Input Capture Unit nutzen, das Problem ist nur, daß über den gleichen Pin schon die PWM läuft. Das Programm ist quasi ein Vorversuch zu einer Schaltung, wo später vier Kanäle vom RC-Empfänger gemessen werden sollen, natürlich alle mit der selben Auflösung. Die Ausgabe erfolgt dann auf vier Motoren in Hardware PWM. Das geht natürlich nicht mit dem ATmega8, weshalb ich dazu einen ATmega128 nehmen werde. Der ATmega8 ist so zu sagen nur das Proof of Concept. Das Problem scheint schlicht zu sein, daß der Controller in der Zählschleife hängen bleibt, sonst würde es wohl funktionieren. Ich habe um den Interrupt zu testen auf dem anderen Interrupt-Pin gelauscht und darüber einen Pin eingeschaltet, was auch funktioniert hat. In der endgültigen Version des Programms sind dann die zwei 16-bit Timer für die PWM vorgesehen und jeweils einer der beiden Timer für Sensoren und das RC-Signal. Das ist der Grund, weshalb ich das so machen will und nicht mit der Capture-Unit. Gruß, Hanno
Hallo Hab mir doch mal den Code angeschaut. So wie ich das sehe vergleichst Du PIND mit r18. In r18 steht aber gar nix drin (bzw. ne null aus main). müsstest vorher (vor oder hinter der Timer-Initialisierung (Eingang_int...)) den Vergleichswert setzen, z.B. ldi r18, 0x04 und dann ldi r16, pind... Hoffe ich hab mich nicht verguckt:-) Gruß Johnny
Ach, übrigens, Du solltest das Pin-Register nicht direkt mit nem Vergleichswert vergleichen, sondern nach dem Einlesen von PIND in r16 den Pin 2 isolieren (z.B. mit andi r16, 0x04). Sonst kommste da nicht wieder raus, wenn an den anderen Pins von PORTD irgendwas anderes passiert. Außerdem hab ich jetzt erst gesehen, dass das reti auskommentiert ist. Das kann natürlich dann auch nicht funktionieren. Müsste also z.B. so lauten: Eingang_int: ;Timer0 konfigurieren ldi r16, 0x02 out TCCR0, r16 ;*********************************** ldi r18, 0x04 ;*********************************** Mess: in r16, PIND ;*********************************** andi r16, 0x04 ;*********************************** cpse r16, r18 rjmp Mess in r17, TCNT0 ldi r16, 0x00 out TCCR0, r16 out TCNT0, r16 reti Gruß Johnny
Danke!!! Super, jetzt reagiert er wenigstens schonmal auf die Pegeländerung am Eingang. Jetzt muß ich den Code noch etwas trimmen und dann habe ich einen einfachen RC-Motorsteller (oder LED-Leutdichtesteller). Due glaubst gar nicht wie lange ich da gestern vor gesessen habe und mir die Augen aus dem Kopf gesucht habe, woran das liegt. Also nochmal vielen, vielen Dank! Schöne Grüße, Hanno
> Die Ausgabe erfolgt dann auf vier Motoren in Hardware PWM. > Das geht natürlich nicht mit dem ATmega8, weshalb ich dazu einen > ATmega128 nehmen werde. Wie wäre es mit dem Mega48?
Schau mal hier: http://www.hanneslux.de/avr/mobau/index.html speziell das hier: http://www.hanneslux.de/avr/mobau/fr_2313a/2313fra.html http://www.hanneslux.de/avr/mobau/fr_2313a/2313frd.html ...
>Wie wäre es mit dem Mega48?
Ich habe mir den ATmega88 besorgt, das Problem ist dabei nur, daß es
nur zwei externe Interrupts gibt, von denen einer auf dem zweiten
OutputCompare Pin von Timer0 liegt. Der scheidet also leider aus. Es
bliebe noch der ATmega32, aber ich habe den mega128 günstig bekommen,
also werde ich den wohl einsetzen.
@HanneS
Danke für die Links, Deine Seite hatte ich schon vor ein paar Tagen
gefunden. Ich hatte mir die Sourcen von den Fahrstellern auch schon
angesehen. Die Ideen sind toll und die Konzepte gefallen mir, mein
Problem ist nur, daß ich aus dem sehr komplexen Sourcecode leider nicht
ersehen kann, wie Du das Signal in den Controller holst. Und um zu
verstehen, wie das geht, hatte ich mir dann überlegt, es selbst heraus
zu finden. Nur bin ich dann an o.g. Problem hängen geblieben. Das
nächste ist jetzt, daß ich mir mit dem Timing was einfallen lassen muß,
weil mit Empfänger klappts noch nicht, aber es klappt mit "von Hand
erzeugten" Impulsen. Ich denke, ich rechne jetzt nochmal hin und her
und denke, daß ich mal mit dem Überlaufbit ein wenig rumspielen werde.
Grüße,
Hanno
@jphnny.m: Die beiden Codeschnipsel von Dir waren schon soweit ganz hilfreich, nur muß das Register r18 weiter 0x00 bleiben, habe ich festgestellt, da wenn ich r16 logisch und mit 0x04 verknüpfe (andi), r16 dann ja solange 0x04 bleibt, solange PinD 0x04, also high auf Pin3 (res. Int0) ist. So springt er dann nach dem Befehl cpsi aus der Messchleife, mit r18 = 0x00 tut er das nicht... Grüße, Hanno
@Hanno: Da ich demnächst in Richtung RC-Decoder etwas mit dem Mega48 machen möchte, habe ich schonmal versucht, eine Kanalimpulsbreitenmessung mit Softwaretimer und Pin-Change-Interrupt zu programmieren. Es liest in der Maximal-Version einen kompletten Port (also 8 Kanalimpulse) ein, lässt sich aber leicht abrüsten. Timer0 steuert einen 16-Bit-Softwaretimer mit 100kHz, also einer Auflösung von 10µs. Zur Impulsbreitenmessung wird nur das untere Byte ausgewertet, es entstehen Werte zwischen 100 (1ms) und 200 (2ms). Das obere Byte wird zur Erfassung des Impulsabstandes verwendet, mit dem eine Plausiblitätskontrolle (Empfangsqualität) durchgeführt werden kann. Die eigentliche Messung erfolgt in der ISR des Pin-Change-Interrupts. Die jeweils ermittelte Zeitdifferenz seit dem letzten PC-Int. wird anhand das vorletzten Zustands der Eingänge in die entsprechende SRAM-Adresse geschrieben. Dabei wird davon ausgegangen, dass die Impulse nacheinander eintreffen und daher immer nur 1 Impuls gleichzeitig aktiv sein kann. Das Programm ist bisher nur im Simulator getestet, es war noch nicht im AVR. Ich denke aber, dass es dir einen Denkanstoß für dein eigenes Projekt geben kann. Denn es ist noch sehr klein und überschaubar, da es erst der Anfang ist. ...
Sorry, hatte nicht bedacht, dass Du nen positiven Impuls abfragst. Dann ist natürlich klar, dass es weitergehen soll, wenn der Pin2 wieder null wird und nicht umgekehrt. Nur in r18 sollte dann auf jeden Fall (allein der Übersicht wegen) in der ISR definiert ne null reingeschrieben werden. Weiterhin viel Erfolg! Gruß Johnny
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.