Forum: Mikrocontroller und Digitale Elektronik Pulslänge mit Hilfe eines Timers messen, klappt nicht...


von Hanno Dahlhaus (Gast)


Angehängte Dateien:

Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

Warum nicht Input Capture Unit benutzen? Ist der ICP-Pin oder der Timer
schon anderweitig verplant? Einfacher gehts doch nicht...

Gruß

Johnny

von Hanno D. (Gast)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

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

von Hanno D. (Gast)


Lesenswert?

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

von Rolf Magnus (Gast)


Lesenswert?

> 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?

von Hannes L. (hannes)


Lesenswert?


von Hanno D. (Gast)


Lesenswert?

>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

von Hanno D. (Gast)


Lesenswert?

@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

von Hannes L. (hannes)


Angehängte Dateien:

Lesenswert?

@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.

...

von johnny.m (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.