Forum: Mikrocontroller und Digitale Elektronik int RC-Oscillator kalibrieren ohne Stk500


von Zoltan (Gast)


Lesenswert?

Hallo,

gibt es eine Möglichkeit, wie ich ohne Stk500 den internen Oscillator
meines Atmega8 messen und justieren kann?

Gruß
Zoltan

von Jörg Wunsch (Gast)


Lesenswert?

Warum messen?  Die Kalibrierwerte werden doch von Atmel
bereitgestellt.

Ansonsten: ja.  Jeder ordentliche Programmer sollte das können.

von Zoltan (Gast)


Lesenswert?

ich kann mit Ponyprog den OSCCAL ja lesen, aber ich weiß nicht, wie
schnell jetzt der Oscillator in wirklichkeit arbeitet. Und das muss ich
wissen ja, um den OSCCAL richtig setzen zu können.

Grund für die Aufregung: Ich habe zwei Atmega8 mit der selben Software.
Bei einer funktiniert die Datenübertragung nur ab und zu, und ich meine,
dass liegt an der Takt-Frequenz.

von Hagen (Gast)


Lesenswert?

Ich habe ein Projekt, ebenfalls mit ATmega8L, den ich mit 3 Volt
betreibe. Die Vorgabe OSCCAL Werte sind aber Werte die bei 5 Volt
ermittelt worden. Dadurch entsteht zB. bei mir schon eine enorme
Differenz zu den tatsächlich nötigen OSCCAL Werten. Zb. für 8 Mhz wurde
OSCCAL mitx$A0 vorgegeben, aber nach einer Kalibrierung wäre 0xB0 für 3
Volt richtig.

Nun, in meinem Projekt arbeite ich mit einem 32KHz Uhrenquarz als
asynchronen Taktgeber. Diesen benutze ich um den internen Osz. zu
kalibrieren. Im Asynchronen Timer OVR, mit 4Hz Takt, benötigt diese
Kalibrierung 2 Sekunden. Ich benutze eine binäre Suche dafür.

Der Startwert des OSCCAL ist 0x80. Nun wird 250ms lang die Taktanzahl
gemessen. Sollte diese kleiner als erwartet sein so wird vom 0x80
OSCCAL Wert 0x40 subtrahiert ansonsten addiert, Danach steht also 0x40
oder 0xC0 im neuen OSCCAL. Nun wird wieder 250ms lang gemessen, und
abhängig vom Resultat eben 0x20 subtrahiert oder addiert, usw, usw.

Du bräuchtest also einen externen und genauen Takt der insgesamt 8 mal
gepulst wird. Du intialisierst den OSCCAL mit $80 und einen globalen
Korrekturwert auf $40. Dieser Wert wird nach jedem Messen durch 2
dividiert. So kommst du exakt auf die 8 nötigen Messungen.

#define  XTAL = 8064000;  // leicht overtunded, aber besser für UART

uint8_t Calibrate = 0;

SIGNAL(SIG_OVERFLOW2) {

  if (Calibrate != 0) {
// lese 16 bit Timer als Referenz
    uint16_t Timer = TCNT1L | (TCNT1H << 8);
    TCNT1H = 0;
    TCNT1L = 0;

// kalibriere mit binärer Suche,
    if (Calibrate < 0x80) {
      int8_t Increment = Calibrate;
      if (Timer > XTAL  256  4) {
  // 256 = Prescaler Timer1,
  //   4 = async. Timer2 Aufrufe pro Sekunde
        Increment = -Increment +1;
      }
      OSCCAL += Increment;
    }

    Calibrate >>= 1;
    if (Calibrate == 0) {
      fertig, speichere OSCCAL in EEPROM etc.
    }
  }
}

void Main() {

// initialisiere 16 bit Timer1 mit Prescaler 256.
// initialisiere asnc. Timer2 auf 250ms.

  OSCCAL = 0x80;
  Calibrate = 0x80;
}

D.h. der 16 bit Timer1 dient zum Messen der Taktzyklen pro 250ms.
Der async Timer2 ist die exakte Zeitbasis mit einer Frequenz von 4Hz.
Diesen Timer2 könntest du auch durch eine externe Zeitbasis ersetzen.

Ich habe nun diese einfache, und auf den ersten Blick un-exakte,
Methode mit den Resultaten aus der doch komplizierten AVR Application
Notes verglichen. Beide Methoden errechneten immer den selben OSCCAL
Wert.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Achso nocheines: nachdem ich so kalibriert hatte konnte ich die
Fehlertoleranzen des UART's exakt im Bereich von 2 Prozent
einjustieren. D.h. der UART läuft nun ohne Probleme obwohl nur der
interne Oszi. benutzt wird.

Gruß Hagen

von Jörg Wunsch (Gast)


Lesenswert?

Klar, daß die vorgegebenen Werte für 5 V sind, ist so beschrieben.
Wenn Du sie für 3,3 V brauchst, mußt Du sie selbst ermitteln.

Aber Zoltan ist sicher einem anderen Irrtum unterlegen: die OSCCAL
Werte, die Du liest, sind ja die, die Du in das OSCCAL-IO-Register
schreiben mußt, damit es den Sollwert (1,0 MHz etc., natürlich bei 5
V) erreicht.  Damit ist der Oszillator dann kalibriert.

Leider kann man die Tuning-Werte nicht direkt via EEPROM-Interface
(o. ä.) aus dem Programm heraus lesen.  Wenn ich eine
Massenapplikation hätte, würde ich ihn per Programmer auslesen und in
eine normale EEPROM-Zelle umschreiben, aus der sich das Programm dann
den Wert lesen kann.  Für ein Einzelstück lohnt der Aufwand natürlich
nicht.

von Hagen (Gast)


Lesenswert?

Genau, und deshalb habe ich's in meinem Projekt so gemacht das im
EEPROM der OSCCAL Wert gespeichert wird. Diesen lese ich aus, ist er
0xFF so wurde noch nicht kalibriert oder eben nicht durch den
Programmer berechnet. In diesem Moment läuft meine obige Kalibrierung
im Hintergrund sofort nach einem Reset an. Den asynchronen Timer 2
benötigte ich sowieso, also lag es nahe auf diese Weise zu kalibrieren.
Desweiteren benötigte ich eben eine Kalibrierung auf einem krummen XTAL
Wert, eben 8.064MHz weil dieser Takt UART freundlicher ist als exakte
8Mhz. So gesehen kam ich in meinem Projekt garnicht um eine
Kalibrierung drumherum.

Gruß Hagen

von Peter D. (peda)


Lesenswert?

Wenn man die UART benötigt, muß man immer einen externen Quarz
anschließen, sonst hat man keine Zuverlässigkeit.


Rein theoretisch kann man auch den internen RC-Oszillator durch einen
externen Quarz nachkalibrieren.

Ob und wie oft man das dann aber wiederholen muß, um z.B.
Temperaturdrift auszugleichen, darüber gibt es keine Aussagen von
Atmel.
Auch kann der Ziehbereich nichtlinear sein, d.h. es kann durchaus
passieren, daß man das OSCAL Register garnicht so genau einstellen
kann.

Diese Lösung würde ich daher nur dann nehmen, wenn wirklich geringste
Stromaufnahme und ständiges Mitzählen der Uhrzeit die absolute
Priorität hat.


Eine andere Möglichkeit ist die automatische Baudratenerkennung, wie
z.B. in meinem Bootloader.
Da kommt es jedoch nur auf Kurzzeitstabilität an (wenige Sekunden) und
außerdem wird durch eine CRC die Korrektheit der Daten überprüft.


Peter

von Hagen (Gast)


Lesenswert?

Hi Peter,

Das ist korrekt. Ich habe deswegen auch den UART intensivst getestet
und Zb. extra für Windows eine Anwendung geschrieben die die Baudraten
Toleranz ermitteln kann. Der AVR sendet permanent seine Zeichen und
diese Software ermittelt den erbrachten Toleranzbereich. Dabei zeigte
sich, eben auch bei unterschiedlichen Temperaturen des AVR's, das der
interne RC Oszillator garnicht mal so schlecht ist, nachdem man ihn
kalibiriert hatte.

In meinem Projekt besteht die Möglichkeit über ein Menu manuell nachzu
kalibrieren. Da der UART des Projektes nur sehr sehr selten zum Update
der Software benutzt wird, stört diese manuelle Kalibrierung nicht so
sehr.

Mit dem Gedanken der Baudratenerkennung habe ich auch schon gespielt,
und sogar deinen Bootloader analysiert (was übrigens garnicht so
einfach war ;).

Allerdings müsste ich das Konzept umdrehen, statt nur die Baudrate zu
erkennen müsste ich anhand der erkannten Baudrate den OSCCAL
kalibrieren. Dies ist ungleich schwerer, aber ein dringende
Notwendigkeit um die effektive Baudrate exakt einstellen zu können.

Nungut, wie man sieht ist der effektive Source auch ziemlich einfach
und kurz gestrickt, es kann also nicht schaden es so zu machen wenn die
Gegebenheiten da sind.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

>Diese Lösung würde ich daher nur dann nehmen, wenn wirklich geringste
>Stromaufnahme und ständiges Mitzählen der Uhrzeit die absolute
>Priorität hat.

Bei meinem Projekt geht es um einen Wecker, obige Bedinungen haben also
absolute Priorität ;)

Gruß Hagen

von Zoltan (Gast)


Angehängte Dateien:

Lesenswert?

Hi Hagen,

ich habe auch einen DesignNote gefunden:
http://www.avrfreaks.net/Tools/ToolFiles/299/DN_018.pdf

Dort wird auch ein Quarz mit 32,768 Khz benutzt.
Gleich eine Frage dazu: Ich habe auch einen alte Quarzuhr auseinander
genommen. Den Quarz muss ich genau so über Kondensatoren an TOSC1 und
TOSC2 anschließen, wie einen "normalen" Quarz?

Es scheint nun mit der Code aus der Design Note zu funktionieren.
Ich habs etwas abgeändert, damit ich den int. Oscillator mit 8Mhz
messen kann.

Was mir auffält, dass von vier gemessenen Atmega8 einer um 9 von dem
original Kalibrationswert abweicht. Die restlichen 3 AVR liegen 1..3
Werte neben dem original Kalibrationswert.


-Wie kann ich ausrechnen, wie viel z.B. die 9 Werte Unterschied in
Frequenz ausmacht?
-Wie kann ich den neuen OSCCAL Wert brennen?

Gruß
Zoltan

von Hagen (Gast)


Lesenswert?

Wird der async. Oszi. benutzt musst du deine Fuses überprüfen und die
internen Kondensatoren aktivieren. Beim Mega8 wäre das die Fuse CKOPT.
In diesem Moment wird nur der Uhrenquarz an TOSC angeschlossen, weiter
nichts.


> Wie kann ich ausrechnen, wie viel z.B. die 9 Werte Unterschied in
> Frequenz ausmacht?

Wie Peter schon andeutete kann der Frequenzunterschied nichtlinear
sein. D.h. wenn zB. der Unterschied von OSCCAL = 0xA0 zu OSCCAL = 0xB0
eben 500KHz beträgt dann könnte denoch der Unterschied zwischen OSCCAL
= 0xB0 zu OSCCAL = 0xC0 eben 750 KHz sein. Schon wenige Sekunden
später, nachdem der AVR um 20 Grad Celsius gekühlt wurde, ist die
Wahrscheinlichkeit groß das beide Werte nicht mehr stimmen. Und noch
schlimmer ist das jeder ATMega8 eben individuell reagieren kann.

Den Unterschied kannst du aber berechnen. Du kehrst die Methode der
Kalibrierung um. Zuerst stellst du OSCCAL auf 0xA0 sein und misst über
den Timer1 die Anzahl der Takte/Prescaler in 250ms. Dann stellst du
OSCCAL auf 0xA9 und misst erneut. Die Differenz ist dann nichts anderes
als der Frequenzunterschied.

> Wie kann ich den neuen OSCCAL Wert brennen?

Im AVR Studio kann man ja entweder den FLASH oder den EEPROM extern
programmieren. Nachdem also der Kalibrierungswert für das OSCCAL
Register ermittelt wurde, kannst du diesen im EEPROM zB. an Adresse
0x3F speichern. In deinem Source liest du diese Speicherzelle beim
RESET aus und speicherst diese in das OSCCAL Register.

Wie Jörg oben schon sagte kann man eben zur Laufzeit im AVR NICHT die
Factory Einstellung oder die Fuses des AVR's auslesen. Man muß also
immer extern diese Werte per Programmer auslesen und in eine geeignete
EEPROM Speicherzelle programmieren oder eben Hardcoded im Quelltext
diesen Wert reinschreiben.

Einzigste Möglichkeit auf beides zu verzichten wäre eben die dynamsiche
Kalibrierung gleich mit in die Software zu integrieren. Exakt das habe
ich bei meinem Weckerprojekt auch gemacht. Aber, da war dies auf Grund
der Gegebenheiten -> Uhrquarz, 3 Volt, async. Timer ISR für RTC usw.
auch möglich.

Gruß Hagen

von Hagen (Gast)


Lesenswert?

Achso, obige Application Note ist die die ich benutzt habe um beide
Methoden zu vergleichen. Ich persönlich finde die Methode der
Application Note eher als nicht so clever gelösst.

Gruß Hagen

von Zoltan (Gast)


Lesenswert?

Da es mir nicht klar war, dass sich die Frequenz des internen
RC-Oscillators dermaßen stark ändert, werde ich lieber versuchen, auf
der Platine noch einen externen Quarz zu platzieren.

Wie genau ist denn ein Quarz, wenn sich die Temperatur ändert?
Kann ich in einem Bereich von 0..25°C sicher sein, dass die Frequenz
dann ausreichend konstant bleibt, um die serielle Schnittstelle noch
benutzen zu können?

Gruß
Zoltan

von Hagen (Gast)


Lesenswert?

Ähm, obige Angaben sind natürlich nur überzogene Beispielwerte.
Laut Datenblatt des ATMega8 auf Seite 270 unteres Diagram wird bei 4.0
Volt und 0°C die Frequenz ca. 7.85Mhz betragen und bei 80°C sinken auf
7.45 Mhz. Das sind pro Grad Celcius also 5KHz. Interessant ist das die
Kurven linear zur Temperatur sind und Voltageabhänig parallel
zueinander sind.
Schaut man aber im Datenblatt die nächsten Diagramme genauer an so
erkennt man das das RC Glied eben keineswegs linear zu Vcc ist.
Das hiese aber auch das, wenn die Stromversorgung mit einem genauen
Spannungsregler exakt geregelt wird, das RC Glied linear von der
Temperatur abhänig ist. In diesem Falle sollte dann aber Diagram 172
des Datenblattes eine geradlinige Kurve darstellen, tut es aber nicht.
D.h. Figure 172 des datenblattes beantwortet deine Frage in wieweit die
Änderungen am OSCCAL Register die Frequenz beeinflussen.

Nebenbei wäre es mal interessant ob man auf Grund dieser Diagrame den
AVR als Temperatursensor mißbrauchen könnte !
Pro Grad Celcius mit konstanter Stromversorgung wären das 5000 Hz
Änderung am RC Glied. Mit einem externe Uhrenquarz sollte man dies doch
messen können.

Im Bereich von 0°C bis 80°C also eine Änderung von 400Khz, das sind
dann 5 Prozent. Nimmt man dagegen einen Temperaturbereich von 10°C bis
40°C an sind das 150KHz Gangänderung was ca. 2 Prozent wären. Ein
kalibriertes RC Glied wäre demnach sehr wohl im relevanten
Temperaturbereich mit guter Spannungsversorgung als UART Takt zu
gebrauchen.

@Peter, ist in meiner Argumentation irgendein Fehler ??

Gruß Hagen

von Zoltan (Gast)


Lesenswert?

Wow, mit dem OSCCAL kann man den internen Oscillator fast auf 15 MHz
tunen. Ich dachte es wären nur ein paar Prozent. Ich hatte auch ein
altes Datenblatt von dem Atmega8. Ja die Diagramme benatworten
natürlich alle Fragen.
Ich habe mich auch wegen den Quarzen schlau gemacht. Sie haben eine
Frequenztoleranz von 100 ppm. D.h. dass bei 8 Mhz die Frequenz um 800
Hz wandert, wenn die Temperatur sich von -10 bis 70 °C ändert.

Verglichen zu dem Drift des RC-Oscillators im selben Temperaturbereich
ergibt sich aus dem Atmega8 Datenblatt eine Frequenz-Differenz von
350000 Hz zwischen -10 und 70°C.

Der RC-Oscillator ändert seine Frequenz also ~450 mal stärker, als ein
Quarz-Oscillator.

http://www.quarze.com/auris/pdf/quarztext.pdf (Bild 2)

Gruß
Zoltan

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.