pyr0skull
17.04.2011, 15:23
Ich stehe vor der Herausforderung, die Einspritzzeit eines Ventils in Mikrosekunden zu messen. Die Auflösung beträgt 100 Mikrosekunden, ein Ventil ist i.d.R. ca. 1200 Mikrosekunden geöffnet.
Als Controller benutze ich einen Atmega168 mit 12MHZ-Quarz. Ich habe also Timer0 mit einem Prescaler von 8 versehen und benutze den CTC-Modus mit einem TOP-Wert von 150. Dadurch sollte rein rechnerisch alle 100 Mikrosekunden ein Interrupt ausgelöst werden.
Um die Genauigkeit zu überprüfen, hab ich eine simple Uhr programmiert. Diese geht allerdings nach, hochgerechnet etwa 8 Minuten pro Tag. Das ist mir zuviel.
Die Frage ist jetzt, ist diese Abweichung ein Fehler im Code (siehe unten) oder einfach die Ungenauigkeit des Quarzes (bzw. der Beschaltung)?
Die Schaltung befindet sich z.Z. auf einer Streifenrasterplatine, ist also von der Leiterbahnlänge am Quarz nicht optimal.
Hier mal der Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "dog_glcd.h"
#include "keypad.h"
#include "uart.h"
#include <stdlib.h>
volatile struct {
uint8_t hour;
uint8_t minute;
uint8_t second;
uint16_t usec;
} time;
char temp[40];
int main() {
sei();
DDRD |= _BV(PD6);
PORTD |= _BV(PD6);
// Timer
TCCR0A |= _BV(WGM01);
TCCR0B |= _BV(CS01);
TIMSK0 |= _BV(OCIE0A);
OCR0A = 150;
spi_init();
lcd_init();
time.hour = 14;
time.minute = 28;
lcd_clear();
while (1) {
[Ausgabe auf LCD]
}
return 1;
}
ISR(TIMER0_COMPA_vect)
{
time.usec++;
if (time.usec == 10000) {
time.usec = 0;
time.second++;
if (time.second == 60) {
time.second = 0;
time.minute++;
if (time.minute == 60) {
time.minute = 0;
time.hour++;
if (time.hour == 24) {
time.hour = 0;
}
}
}
}
}
Als Controller benutze ich einen Atmega168 mit 12MHZ-Quarz. Ich habe also Timer0 mit einem Prescaler von 8 versehen und benutze den CTC-Modus mit einem TOP-Wert von 150. Dadurch sollte rein rechnerisch alle 100 Mikrosekunden ein Interrupt ausgelöst werden.
Um die Genauigkeit zu überprüfen, hab ich eine simple Uhr programmiert. Diese geht allerdings nach, hochgerechnet etwa 8 Minuten pro Tag. Das ist mir zuviel.
Die Frage ist jetzt, ist diese Abweichung ein Fehler im Code (siehe unten) oder einfach die Ungenauigkeit des Quarzes (bzw. der Beschaltung)?
Die Schaltung befindet sich z.Z. auf einer Streifenrasterplatine, ist also von der Leiterbahnlänge am Quarz nicht optimal.
Hier mal der Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include "dog_glcd.h"
#include "keypad.h"
#include "uart.h"
#include <stdlib.h>
volatile struct {
uint8_t hour;
uint8_t minute;
uint8_t second;
uint16_t usec;
} time;
char temp[40];
int main() {
sei();
DDRD |= _BV(PD6);
PORTD |= _BV(PD6);
// Timer
TCCR0A |= _BV(WGM01);
TCCR0B |= _BV(CS01);
TIMSK0 |= _BV(OCIE0A);
OCR0A = 150;
spi_init();
lcd_init();
time.hour = 14;
time.minute = 28;
lcd_clear();
while (1) {
[Ausgabe auf LCD]
}
return 1;
}
ISR(TIMER0_COMPA_vect)
{
time.usec++;
if (time.usec == 10000) {
time.usec = 0;
time.second++;
if (time.second == 60) {
time.second = 0;
time.minute++;
if (time.minute == 60) {
time.minute = 0;
time.hour++;
if (time.hour == 24) {
time.hour = 0;
}
}
}
}
}