OnkelTobi
11.03.2007, 04:14
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:
http://farm1.static.flickr.com/169/417047402_d04b280117.jpg
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:
#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
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:
http://farm1.static.flickr.com/169/417047402_d04b280117.jpg
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:
#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