- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Uhr mit 32768Khz mit der Zeit ungenau - Code Probleme?

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    14.04.2008
    Ort
    Esslingen
    Alter
    36
    Beiträge
    235

    Uhr mit 32768Khz mit der Zeit ungenau - Code Probleme?

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Nabend zusammen,

    Hab nen ATMEGA32 mit dem ich gerne erst mal nur eine Uhr realisieren möchte.
    Hab dafür den Timer2 mit 32768Khz laufen und sollte somit doch eigentlich
    eine ziemlich genau Uhr haben oder? Habe aber nach ca. 12 Std. eine Verzögerung von 5 Sek.
    Könnte einer mal den Code überprüfen, bin noch ziemlich grün hinter den Ohren was C angeht :/.

    Code:
    #include <inttypes.h>
    
    #include <avr/io.h>
    
    #include <avr/pgmspace.h>        
    #include <avr/interrupt.h>
    #include <util/delay.h>
    
    #ifndef F_CPU
    #define F_CPU 8000000
    #endif
    
    
    #include "ks0108.h"
    
    #include "font12x16.h"
    
    #include "font6x8.h"
    
    volatile int sek=0;
    volatile int min=0;
    volatile int std=0;
    
    
    
    
    int main(void) {
        cli();
        TIMSK &=~(1<<TOIE2);
        ASSR = (1<<AS2);
        TCNT2 = 0;
        TCCR2 |= (1<<CS22) | (1<<CS20);
        while((ASSR & 0x01) | (ASSR & 0x04));
        TIFR = 0xFF;           
        TIMSK |=(1<<TOIE2);     
        sei();
    
    	PORTC = 0xff;
    	PORTC |= (1<<PC1);
    	struct font largeFont, smallFont;
    	unsigned char sek2[5];
    	unsigned char min2[5];
    	unsigned char std2[5];
    	ks0108Init();
    	largeFont.width = FONT12X16_WIDTH;
    
    	largeFont.height = FONT12X16_HEIGHT;
    
    	largeFont.charData = Font12x16;
    
    	
    
    	smallFont.width = FONT6X8_WIDTH;
    
    	smallFont.height = FONT6X8_HEIGHT;
    
    	smallFont.charData = Font6x8;
    	while(1)
    	{
    
    
    
    	itoa(sek,sek2,10);
    	itoa(min,min2,10);
    	itoa(std,std2,10);
    
    
    	
    
    	
    	ks0108GotoXY(0,0);
    
    	ks0108PutString(sek2,smallFont);
    
    	ks0108GotoXY(0,10);
    	ks0108PutString(min2, smallFont);
    
    	ks0108GotoXY(0,20);
    	ks0108PutString(std2, smallFont);
    
    	}
    	
    return 0;
    
    }
    
    
    ISR(TIMER2_OVF_vect) {
    	sek++;
    	ks0108Init();
    
    	if (sek>59)
    	{	
    		min++;
    		sek=0;
    
    	}
    
    	if (min>59)
    	{
    		std++;
    		min=0;
    	}
    
    	if (std>23)
    	{
    		std=0;
    		min=0;
    		sek=0;
    	}
    }

    Für Tips und Verbesserungen wäre ich dankbar

    Mfg Mel
    Elektronische Bauteile funktionieren mit Rauch. Lässt man den Rauch raus, sind sie kaputt.

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Also warum die Uhr mit 32768Khz (das sind ja mehr als 32MHz!) so genau sein soll ist mir unklar. Auch mit 32768Hz wird es nicht wirklich besser: 8000000/32768 sind 244,140625. Dein Timer läuft aber offensichtlich im Overflow-Mode, also mit 8000000/256=31250Hz.

    Könnte einer mal den Code überprüfen, bin noch ziemlich grün hinter den Ohren was C angeht :/.
    Ist das die Umschreibung für "Macht euch mal die Mühe und checkt mein Timersetup. Kommentare habe ich nicht eingefügt, weil ich nicht weiß, wie das funktioniert?"

    Code:
    ISR(TIMER2_OVF_vect) {
       sek++;
       ks0108Init();
       ...
    So etwas sollte man nicht tun! Wenn man Funktionen in einer ISR aufruft provoziert man geradezu einen Überlauf der Interrupts. Und dann ist das Timing auf jeden Fall gestorben.

    volatile int sek/min/std: Hier würde vielleicht auch ein Char ausreichen ;)

    PORTC = 0xff;
    PORTC |= (1<<PC1);

    Alle Pins des Port C werden gesetzt, dann wird nur der Pin PC1 gesetzt? Das bedeutet letztlich: Alle PullUps an Port C sind eingeschaltet?

    Aber deine Signatur macht ja vieles wieder gut. Bei mir ist sie unter den Top10 ;)

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Das
    ks0108Init();
    In der ISR sollte man vermeiden, auch wenn die Routine nur jede Sekunde einmal aufgerufen wird. Genau wiess ich zwar nicht was da drinsteht, aber ein Zugriff aufs LCD dauert oft sehr lange. Man sollte generell Funktionsaufrufe in einer ISR vermeiden, denn dann werden fast alle Register gesichert.

    Beim Hochzählen der Zeit, kann man die IFs etwas ander Schachteln, die Studen werden nur hochgezahl, wenn auch die Sekunden dran waren. Außerdem ist am Ende des Tages die Sekunde und Minute ohnehin schon bei 0. Die variablen für sek, min und Stunde sollten ein 8- bit Typ ( z.B. char) sein. Sonst müßte man den Zugriff im Hauptprogramm jeweils Atomar gestallten.

    Ein 32678 Hz Quarz muß nicht genauer sein als welche im 8 MHz Bereich. Auch da muß die Beschaltung mit den Kondensatoren stimmen. Welche Kapazitäten richtig sind hängt vom Quarz ab, da gibt es Unterschiede. Weil die Kapazitäten da oft recht klein sind, kommt es auch auf das Layout und die Eingangskapazität an. Den Hauptvorteil, den man mit einem 32kHz Quarz hat, ist die geringe Leistung, wenn man Stromsparmodi nutzt.


    Wenn es sein muß, könnte man Abweichungen in der Frequenz auch noch softwaremäßig korrigieren: Nach einer Zeit im Bereich mehrerer Minuten den Zähler mit einem Anderen Wert Vorladen um so ein Intevall um 1/256 Sekunde zu verlängern oder verkürzen.

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    14.04.2008
    Ort
    Esslingen
    Alter
    36
    Beiträge
    235
    Ok nein es sollen natürlich 32768 Hz sein. Und ja, das Timersetup checken war einer meiner "Aufgaben", wobei dies natürlich alles auf freiwilliger Basis passieren soll, sieh dich also nicht gezwungen.

    Und den Timer wollte ich eig. als asynchron Timer laufen lassen, also dass er nur für die Uhr zuständig ist. Kann durchaus sein dass ich mich da wohl noch mal mit auseinandersetzen muss, ob ich das alles richtig konfiguriert hab, mein Code bis jetzt ist eine Zusammensetzung aus verschiedenen Quellen aus dem Internet .
    Ok das mit der ks0108init() werd ich noch mal schauen.

    Und die Signatur sollte eigentlich nur als Signatur gewertet werden, und nicht auskunft über meine Projekte geben
    Elektronische Bauteile funktionieren mit Rauch. Lässt man den Rauch raus, sind sie kaputt.

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Jetzt habe ich das auch mit den 32768 kapiert. Es handelt sich wohl um einen zusätzlichen Quarz der den Timer ansteuert (das Timersetup habe ich immer noch nicht gecheckt Zusammen mit einem Prescaler von 128 würde das genau den Sekundentakt ergeben: 32768/256=128. Dann hätte die ISR aber auch eine Sekunde Zeit zur Ausführung, ein Überlauf sollte nur schwer erreichbar sein.

    Mein Verdacht fällt nun auf die Toleranz des Quarzes. Ok, jetzt müsste ich eigentlich passen, weil ich mich damit noch nie beschäftigt habe. Aber ich versuche es trotzdem mal, weil ich ja was lernen will. Der erste 32768er den ich gefunden habe (Link) hat einen Fehler von +-100 ppm (ppm bei Spurt), also 0,01%. Das wären in 12 Stunden mit 43200 Sekunden also 43200/10000=4,32 Sekunden. Das würde schon mal gut passen

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    14.04.2008
    Ort
    Esslingen
    Alter
    36
    Beiträge
    235
    Genau so soll das eigentlich laufen. Der µC soll später im Powersave Modus laufen und nur die Uhr soll noch weiterlaufen. Die Toleranz könnte ich nochmal kontrollieren, danke für den Hinweis. Mir ging es nur in erster Linie darum ob die Verzögerung evtl. durch schlechte Programmierung entstanden sein könnte. Denn sonst würd ich diese einfach durch die Software korrigieren.
    Elektronische Bauteile funktionieren mit Rauch. Lässt man den Rauch raus, sind sie kaputt.

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Der Code sieht soweit gut aus, dass es dadurch wohl keine Fehler gibt, es sein denn das ks0108Init(); macht wirklichen Murks und braucht eine Zeit im Sekundenbereich.


    Zur Tolleranz von vielleicht 100 ppm kommt ggf. noch ein Fehler in ähnlicher Größenordnung dazu, wenn die Kondesatoren nicht stimmen.

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    14.04.2008
    Ort
    Esslingen
    Alter
    36
    Beiträge
    235
    Hmm Kondensatoren hab ich noch gar nicht dran.

    http://www.elv.de/output/controller....fmt=2&affmn=18

    So einen habe ich am µC angeschlossen, sind da Kondensatoren noch erforderlich?

    Die ks0108Init hab ich noch drinnen um das Display zu "clearen" weil sonst die Zahlen übereiander geschrieben werden, aber das lässt sich denk ich auch noch besser regeln.
    Elektronische Bauteile funktionieren mit Rauch. Lässt man den Rauch raus, sind sie kaputt.

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.214
    Ich gebs zu, ich hab den Code jetzt nicht im Detail angesehen...

    Zu der KS0108 Problematik:

    Man könnte doch in der Interruptroutine nur die Zeitwerte in Variablen hinterlegen und ein Flag setzen.

    Im Hauptprogramm in der Main Schleife wird dann dieses Flag abgefragt, das Display refreshed und dieses Flag wieder gelöscht.

    Die Interruptroutine wird dadurch wesentlich kürzer blockiert.
    Die Reaktionszeiten des Displays dürften dabei noch wesentlich länger sein, als man Zeitverzögerungen durch diese Methode kriegt.

  10. #10
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Auch für die 32 kHz Quarze braucht man noch Kondensatoren, ähnlich wie bei den Quarzen im MHz Bereich. Der Wert sollte im Datenblatt zum Quarz stehen. Wenn da "load-capacitance" angegeben ist, sollte man an den beiden Seiten etwa 5 pF weniger als das doppelte dieses Wertes nehmen.

    Die angegebene Frequenz gilt bei der nominelen Lastkapazität - ohne Kondensatoren ist es normal dass die Frequenz nicht stimmt.

    Im Datenblatt der AVRs steht zwar, dass man da auch Chip interne zuschalten kann. Allerdings steht weiter hinten unter Errata auch das die internen Kondensatoren nicht funktionieren.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen