- LiFePO4 Speicher Test         
Ergebnis 1 bis 5 von 5

Thema: Genaue Zeitmessung mit einem AVR

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.08.2006
    Beiträge
    105

    Genaue Zeitmessung mit einem AVR

    Anzeige

    Praxistest und DIY Projekte
    Servus,

    ich habe mir eine kleine Rundenzeiten-Messanlage gebaut...

    Wie kann ich die Messung möglichst genau bekommen?
    Ich habe ein Abweichung die ich mir aktuelle nicht erklären kann.

    Zunächst kurz wie ich es bisher gelöst habe:

    Hardware:
    Bild hier  
    Tiny26 mit externem 11,0592Mhz Quarz
    HD44780 Display
    Infrarot- bzw. Laserlichtschranke


    Software:
    Timer1 mit Prescaler 512
    Vergleichsregister so eingestellt, dass alle 10ms ein Interrupt ausgelöst wird.
    Bei Interrupt wird Zählregister rückgesetzt und die Hunderstel addiert.

    Time0 sorgt alle 200ms dafür, dass das angeschlossende LCD aktualisiert wird.

    Hier mal der Code des Zählers:
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #include "global_time.h"
    
    //Variable für Zeitmessung
    time_struct globalTime; 
    volatile uint8_t milliSeconds = 0;
    volatile uint8_t secondFlag = 0;
    
    
    ISR(TIMER1_CMPA_vect)
    {
    	TCNT1 = 0x00;
    	if (100 == ++milliSeconds)
    	{
    		secondFlag = 1;
    		milliSeconds = 0;
    	}
    }
    
    void globalTimeRefresh()
    {
    	if (secondFlag)
    	{
    		if (60 == ++globalTime.sec)
    		{
    			globalTime.min++;
    			globalTime.sec = 0;
    		}
    		secondFlag = 0;
    	}
    	globalTime.hSec = milliSeconds;
    }
    
    void globalTimeInitialize(void)
    {
    	/*
    		Timer1:
    			Interrupt genau jede Millisekunde
    			Prescaler 512
    			Vergleichsregister = F_CPU / 512 / 100
    			Zähler zurücksetzen, wenn OCR1A erreicht ist
    			
    	*/
    	TCCR1B = (1<<CS13)|(0<<CS12)|(1<<CS11)|(0<<CS10);
    	OCR1A = F_CPU / 512 / 100 + 1;
    
    	TIMSK |= (1<<OCIE1A);		//Interrupt
    }
    Problem:
    Aktuell geht die Zeitmessung 0,3% zu langsam (ca 4s auf 23Min).
    Die Genauigkeit des Quarzes ist mit ppm angegeben, also nicht ursächlich für die Abweichung.

    0.3% sind bei 11Mhz immerhin 30.000 Takte pro Sekunde - wobei gehen die "verloren"?

    Bei der Interruptbehandlung der anderen Interrupts?
    Oder durch das manuelle Rücksetzen des Zählers? (TCNT1 = 0);

    Es gibt keinerlei atomaren Code, es können also keine Interrupts unterdrückt sein.

    Geht vielleicht mein Handy falsch?

    MfG
    Tobias

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Lass das das TCNT=1 weg. In dem Mode, den du eingestellt hast, erledigt das die Hardware. Wenn du es nochmal zurüchsetzt, geht deine Uhr zu langsam.
    Disclaimer: none. Sue me.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.08.2006
    Beiträge
    105
    Leider nicht.

    der TIMER1_CMPA_vect-Interrupt wird korrekt ausgelöst, der Timer1 zählt aber bis 0xFF weiter.

    Der Tiny26 hat irgendwie keinen Mode um den Zähler nach erreichen von OCR1A automatisch zurückzusetzen. Der Tiny44 hats... mal schauen.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Du betreibst den Timer im "normal" Mode. Schau mal ins Datenblatt und verwende den CTC-Mode. Da fehlt wohl noch ein Bit im TCCRnB. CTCx oder WGMx.

    Zitat Zitat von Manual pp. 73
    Bit 7 CTC1: Clear Timer/Counter on Compare Match

    When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare match with OCR1C Register value. If the control bit is cleared, Timer/Counter1 continues counting and is unaffected by a compare match.
    Du schreibst also den Wert nicht nach OCR1A, sondern nach OCR1C und setzt OCR1A=0.

    Ausserdem hast du einen schlechten OCR-Wert. Der Wert muss in 8 Bit passen und die Division muss ausgehen, ansonsten hasst du Ungenauigkeit wegen der Rundungsfehler (Timer geht schneller als gewünscht). Zudem muss da eine -1 hin und keine +1.
    Disclaimer: none. Sue me.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.08.2006
    Beiträge
    105
    Kurz nachdem ich das oben gepostet habe, habe ich das CTC1-Flag auch bemerkt.

    Dazu habe ich noch den Interupt auf TOIE1 geändert und es klappt.

    Die Genauigkeit muss ich aber noch bestimmen.

    /edit
    Beim setzen von OCR1C subtrahiere ich noch eine 1:
    OCR1C = F_CPU / 512 / 100 - 1;

    Und schon zeigt die Uhr die gewünschte Genauigkeit.
    Nach 21Minuten ist keine Abweichung in Hundertstel zu bestimmen.

    Danke.

Berechtigungen

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

LiFePO4 Speicher Test