Forum: Mikrocontroller und Digitale Elektronik AVR: Jitter bei TIMER0_COMPA_vect


von Harstad (Gast)


Lesenswert?

Hi,

ich nutze einen ATTiny85 um variable Frequenzen auszugeben. Dazu 
verwende ich den TIMER0 im Compare-Mode:

1
// Initialisierung
2
TCCR0A = (1<<WGM01); // CTC Modus
3
OCR0A=1;
4
TCCR0B&=~0x07; // stop timer
5
TIMSK |= (1<<OCIE0A);
6
7
// Starte Timer, so bald er benötigt wird
8
TCCR0B|=0x04;
9
10
//Timer-ISR
11
ISR(TIMER0_COMPA_vect,ISR_NOBLOCK)
12
{
13
   ...
14
}

Die Frequenz erzeuge ich über eine Zählvariable, diese wird in der ISR 
runtergezählt und ein Ausgangsbit immer dann geswitcht, wenn der Zähler 
bei 0 angekommen ist. Mit 16,5 MHz Takt und dem gewählten Teiler 
erreiche ich damit eine Maximalfrequenz von ca. 16 kHz. Parallel dazu 
habe ich den V-USB laufen, um von außen Kommandos schicken zu können.

Dabei habe ich jetzt zwei Probleme:

1. Die Maximalfrequenz müsste bei ca 32. kHz liegen: 16,5 MHz durch 
Teiler 256 durch 2 (Bit setzen und Bit löschen in separaten Aufrufen der 
ISR) wären ca. 32226 Hz, nicht 16113 Hz. Für die Maximalfrequenz ist die 
Zählvariable immer 0 und es wird das Ausgangsbit bei jedem Aufruf der 
ISR getoggelt. Wo habe ich mich hier verrechnet?

2. Ich habe einen ziemlichen Jitter auf der ausgegebenen Frequenz. Der 
entsteht durch den USB-Anschluß, wenn ich die CPU ohne USB laufen lasse, 
ist der Jitter weg. Vermutlich funkt hier also irgend ein Interrupt von 
den für V-USB verwendeten Eingängen dazwischen. Welche Möglichkeiten 
habe ich hier, den Jitter zu verkleinern? Interruptprioritäten kann ich 
ja nicht setzen, oder? Eine andere Hardware kann ich auch nicht 
einsetzen, ich bin an den ATTiny85 gebunden.

Es ist jeder konstruktive Hinweis willkommen :-)

Danke!

von Karl H. (kbuchegg)


Lesenswert?

Harstad schrieb:

> 1. Die Maximalfrequenz müsste bei ca 32. kHz liegen: 16,5 MHz durch
> Teiler 256 durch 2 (Bit setzen und Bit löschen in separaten Aufrufen der
> ISR) wären ca. 32226 Hz, nicht 16113 Hz.

OCR0A=1;

Durch noch mal 2, weil der Timer 2 Zählzyklen braucht um bei 1 angelangt 
zu sein.

> 2. Ich habe einen ziemlichen Jitter auf der ausgegebenen Frequenz. Der
> entsteht durch den USB-Anschluß, wenn ich die CPU ohne USB laufen lasse,
> ist der Jitter weg.

Nimm das NO_BLOCK aus der ISR Definition raus.
Du willst nicht haben, dass dir der USB Code deine ISR unterbrechen 
kann.

Problem könnte natürlich sein, dass dann der USB Code auf die 
kurzzeitigen Unterbrechungen durch deinen Timer allergisch reagiert. 
Aber ein bischen Luft wird da hoffentlich schon drinnen sein.

Einen gewissen Grundjitter wirst du natürlich so immer haben, denn 
während der USB Code in einer ISR hängt, muss dein ISR Aufruf warten.
Das kriegst du nur mehr dadurch weg, dass du einen PWM Modus nimmst, bei 
dem die Timer-Hardware selber den Pin umschaltet. Das könnte allerdings 
bei den längeren Zeiten etwas tricky werden, wenn du den Timer nicht 
langsam genug einstellen kannst.

Fazit:
Wenn das ordentlich werden soll, kommst du nicht umhin dir ein Verfahren 
auszudenken, wie du aus der gewünschten Frequenz für den Timer einen 
geeigneten Vorteiler samt Compare und Top Wert bestimmen kannst, mit 
denen du eine PWM im Modus 15 füttern kannst, so dass dir die Hardware 
die Frequenz erzeugt.

: Bearbeitet durch User
von Harstad (Gast)


Lesenswert?

Karl H. schrieb:
> Nimm das NO_BLOCK aus der ISR Definition raus.
> Du willst nicht haben, dass dir der USB Code deine ISR unterbrechen
> kann.

Keine Chance, dann ist der USB-Anschluss sofort tot. Dann müsste ich die 
Timer-Frequenz auf max 10 kHz begrenzen, damit mir die ISR das 
USB-Timing nicht killt.

> Wenn das ordentlich werden soll, kommst du nicht umhin dir ein Verfahren
> auszudenken, wie du aus der gewünschten Frequenz für den Timer einen
> geeigneten Vorteiler samt Compare und Top Wert bestimmen kannst, mit
> denen du eine PWM im Modus 15 füttern kannst, so dass dir die Hardware
> die Frequenz erzeugt.

Den PWM habe ich bisher nicht genommen, weil ich auch Rampen können 
muss. Sprich die Frequenz wird nicht einfach nur angeschaltet, sondern 
mehr oder weniger langsam (=parametrisierbar) von 5 Hz bis auf die 
Zielfrequenz erhöht bzw. von dort auf 5 Hz gesenkt. Und sowas ist mit 
dem PWM-Modul ja nicht machbar!? Zumindest habe ich keinen Modus 
gefunden, in dem ich die PWM-Frequenz langsam steigen/sinken lassen 
kann...

von Peter D. (peda)


Lesenswert?

Harstad schrieb:
> Welche Möglichkeiten
> habe ich hier, den Jitter zu verkleinern?

Einen PWM-Ausgang benutzen.
Der Interrupt bereitet ihn nur vor (setzen oder löschen) und mit dem 
nächsten Compare wird der Pin umgeschaltet, unabhängig von der 
Interruptlatenz.

von Karl H. (kbuchegg)


Lesenswert?

Harstad schrieb:

> Den PWM habe ich bisher nicht genommen, weil ich auch Rampen können
> muss.

Das schliesst sich nicht automatisch aus.
Nur weil der Timer eine PWM erzeugt, bedeutet das nicht, dass er keine 
Interrupts mehr erzeugt.

Ein wenig wirst du dich in der Frequenz einschränken müssen, aber ob die 
Berechnung für den jweils folgenden PWM Zyklus ein paar Takte länger 
dauert oder nicht, ist dann nicht mehr so tragisch (d.h. wenn der USB 
Code nicht zuviel Takte abzieht). Du musst nur fertig sein, bis die 
Hardware den Pin das nächste mal umschalten will.

von Clemens L. (c_l)


Lesenswert?

Harstad schrieb:
> Karl H. schrieb:
>> Nimm das NO_BLOCK aus der ISR Definition raus.
>> Du willst nicht haben, dass dir der USB Code deine ISR unterbrechen
>> kann.
>
> Keine Chance, dann ist der USB-Anschluss sofort tot.

Dann nimm eine CPU, die USB kann.

> Den PWM habe ich bisher nicht genommen, weil ich auch Rampen können
> muss.

Bei einem Timer mit PWM-Ausgabe kannst du eine Rampe erzeugen, indem du 
regelmäßig den Vergleichswert änderst.
(Mit DMA (hat der ATTiny nicht) und einem zweiten Timer ginge das 
vollautomatisch.)

: Bearbeitet durch User
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.