Forum: Projekte & Code ATtiny Clock Recalibration ohne externe Referenz


von Horst M. (horst)


Angehängte Dateien:

Lesenswert?

Resultierend aus einer Idee, um die ATtinys mit interner PLL auf 20 MHz 
Taktfrequenz zu bringen, hier ein kleines Stückchen Assembler-Code.
Als Referenz wird die werkskalibrierte Frequenz des RC-Oszillators 
benutzt, gemessen wird mit dem Watchdog-Timer. Da relativ zum Basistakt 
kalibriert wird, ist die Absolutgenauigkeit des Watchdog-Timers nicht 
relevant (ich bin davon ausgegangen, daß die Kurzzeitstabilität 
ausreichend ist).
Die Genauigkeit der Ziel-Taktfrequenz wird natürlich nicht besser sein 
als die ab Werk kalibrierte Frequenz, also bitte nicht zuviel erwarten.

Das Verfahren ist nicht auf ATtinys mit PLL beschränkt, sondern sollte 
eigentlich auf allen AVR-Controllern mit OSCCAL-Register und 
Watchdog-Interrupt funktionieren.

von c-hater (Gast)


Lesenswert?

Horst M. schrieb:

> Da relativ zum Basistakt
> kalibriert wird, ist die Absolutgenauigkeit des Watchdog-Timers nicht
> relevant

Ja, und die Kinder bringen die Störche.

> Die Genauigkeit der Ziel-Taktfrequenz wird natürlich nicht besser sein
> als die ab Werk kalibrierte Frequenz, also bitte nicht zuviel erwarten.

Sie wird bei statistischer Betrachtung mit hinreichende Sample-Basis im 
Mittel natürlich sogar weit schlechter sein. Man braucht sich nichtmal 
den Code anzuschauen, um das heraus zu bekommen, sondern nur deine 
Beschreibung des Verfahrens zu lesen und die Genauigkeit des 
Watchdog-Timers nachzuschlagen...

Mein Gott, hast du niemals die Grundweisheit gelernt: Messen heisst 
Vergleichen? Du kannst nix ohne Referenz kalibrieren. Und du kannst nix 
genauer kalibrieren als die Referenz ist.

Ob dir das nun gefällt oder nicht: die böse Physik unseres Universums 
gibt das als unabänderliches Gesetz vor. Wenn du nachweislich einen Weg 
darum herum gefunden hättest, wärst du der einsame Kandidat für den 
nächsten Nobelpreis. Du hast wahrscheinlich überhaupt kein Vorstellng 
davon, was das alles zum Rutschen bringen würde...

Aber: Du wirst keinen Nobelpreis ernten und die Physik wird sich weiter 
mit der Auflösung der gravierenden Widersprüche beschäftigen, die sie 
derzeit hat. Da sind aber nur zwei, jweisl sehr gut abgesicherte Säulen 
der Erkenntnis miteinander im Widerspruch.

Dein Ding würde aber beide komplett aushebeln...

von Walter S. (avatar)


Lesenswert?

c-hater schrieb:
> Und du kannst nix
> genauer kalibrieren als die Referenz ist.

und genau das hat er ja geschrieben:

Horst M. schrieb:
> Die Genauigkeit der Ziel-Taktfrequenz wird natürlich nicht besser sein
> als die ab Werk kalibrierte Frequenz,

also entspann dich mal. Wenn Du wirklich einen Fehler entdeckst dann 
schreib das in in ein paar Zeilen hin anstatt dich seitenweise 
aufzuspielen

von org (Gast)


Lesenswert?

>  .org WDTaddr
>  pop r0        ;remove the interrupt return address from stack
>  pop r0
>  reti        ;return to calling point of subroutine "measure"


Was zur Hölle? Warum funktioniert das überhaupt?

von Horst M. (horst)


Lesenswert?

org schrieb:
>>  .org WDTaddr
>>  pop r0        ;remove the interrupt return address from stack
>>  pop r0
>>  reti        ;return to calling point of subroutine "measure"
>
>
> Was zur Hölle? Warum funktioniert das überhaupt?

Weil's folgendermaßen läuft:
1
        ...
2
        rcall measure
3
;hier soll's nach dem Watchdog-Interrupt weitergehen
4
        ...
5
6
measure:
7
  clr r24
8
  clr r25
9
  wdr
10
delay:  ldi r18,LOW(int(bclock*16))
11
delay1: dec r18
12
  brne delay1
13
  adiw r25:r24,1
14
  rjmp delay

Die "measure"-Subroutine ist im Prinzip erstmal eine Endlosschleife, aus 
der es regulär kein Entkommen gibt.
Der Watchdog-Timer ist auf 2048 Watchdog-Oszillator-Takte eingestellt 
und wird unmittelbar, bevor die Schleife losläuft, zurückgesetzt.
Wenn der Watchdog-Interrupt zuschlägt, wird die Return-Adresse auf den 
Stack gelegt. Ein Rückkehr aus dem Watchdog-Interrupt in die 
Endlosschleife macht natürlich keinen Sinn, deshalb wird diese 
Return-Adresse mit zweimal POP verworfen und stattdessen die zuvor 
gespeicherte Return-Adresse des "RCALL measure"-Aufrufs verwendet.

Hier wird auch das Meßverfahren erkennbar.
Zunächst wird mit dem originalen 16 MHz-Controller-Takt 
(werkskalibrierter RC-Oszillator, PLL ein) gemessen. Nach dem 
Watchdog-Interrupt wird R25:R24 irgendeinen Wert enthalten, die absolute 
Zahl ist dabei nicht entscheidend, deswegen ist die genaue Frequenz 
des Watchdog-Oszillators nicht relevant (wie erwähnt gehe ich davon aus, 
daß die Stabilität der Watchdog-Frequenz für die paar hundert 
Millisekunden der Gesamtlaufzeit des Progrämmchens ausreichend ist).
Mittels des soeben gemessenen Referenzwerts wird der Zielwert errechnet 
(eine simple Multiplikation mit dem Verhältnis 
Zielfrequenz/Originalfrequenz; um von 16 MHz auf 20 MHz zu kommen, also 
mit 1.25). Über sukzessive Approximation wird dann der Controller-Takt 
so eingestellt, daß der Messwert so nah wie möglich an dem errechneten 
Zielwert zu liegen kommt - fertig.

von org (Gast)


Lesenswert?

Horst M. schrieb:
> Die "measure"-Subroutine ist im Prinzip erstmal eine Endlosschleife, aus
> der es regulär kein Entkommen gibt.
> Der Watchdog-Timer ist auf 2048 Watchdog-Oszillator-Takte eingestellt
> und wird unmittelbar, bevor die Schleife losläuft, zurückgesetzt.
> Wenn der Watchdog-Interrupt zuschlägt, wird die Return-Adresse auf den
> Stack gelegt. Ein Rückkehr aus dem Watchdog-Interrupt in die
> Endlosschleife macht natürlich keinen Sinn, deshalb wird diese
> Return-Adresse mit zweimal POP verworfen und stattdessen die zuvor
> gespeicherte Return-Adresse des "RCALL measure"-Aufrufs verwendet.

Ach du meine Güte...
Ja, funktionieren tut das wohl. Aber das wars auch schon.

> Mittels des soeben gemessenen Referenzwerts wird der Zielwert errechnet
> (eine simple Multiplikation mit dem Verhältnis
> Zielfrequenz/Originalfrequenz; um von 16 MHz auf 20 MHz zu kommen, also
> mit 1.25). Über sukzessive Approximation wird dann der Controller-Takt
> so eingestellt, daß der Messwert so nah wie möglich an dem errechneten
> Zielwert zu liegen kommt - fertig.

Und warum nutzt du überhaupt den WDT? Warum multiplizierst du den per 
Werkseinstellung kalibrierten OSCAL-Wert nicht einfach mit 1.25 (oder 
was auch immer) und fertig?

von Horst M. (horst)


Lesenswert?

org schrieb:
> Und warum nutzt du überhaupt den WDT? Warum multiplizierst du den per
> Werkseinstellung kalibrierten OSCAL-Wert nicht einfach mit 1.25 (oder
> was auch immer) und fertig?

Weil die RC-Oszillator-Frequenz nichtlinear vom OSCCAL-Wert abhängt 
(Figure 22-42. auf Seite 194 
http://www.atmel.com/images/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf).
Und letztlich ist die Abweichung zwischen "OSCCAL einfach mit einem Wert 
multipliziert" und der vorgestellten Methode womöglich entscheidend, ob 
ein UART noch läuft oder nicht.

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.