Hallo, gibt es eine Möglichkeit, wie ich ohne Stk500 den internen Oscillator meines Atmega8 messen und justieren kann? Gruß Zoltan
Warum messen? Die Kalibrierwerte werden doch von Atmel bereitgestellt. Ansonsten: ja. Jeder ordentliche Programmer sollte das können.
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.
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
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
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.
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
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
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
>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
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
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
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
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
Ä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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.