Eine Abweichung von 0,0055% ist doch erstmal nicht so schlecht. Aber 8 min Pro Tag scheinen mir auch recht viel.
Was ist das für ein Quarz? Du meinst aber nicht den internen RC?!
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:
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; } } } } }
Deine Signatur ist zu lang.
Eine Abweichung von 0,0055% ist doch erstmal nicht so schlecht. Aber 8 min Pro Tag scheinen mir auch recht viel.
Was ist das für ein Quarz? Du meinst aber nicht den internen RC?!
Nein, ist ein "richtiger" Quarz im HC49-Gehäuse. Ich müsste mal ausrechnen, ob die ISR zu lang ist.. Aber das sollte doch eigentlich passen, bei 100 Mikrosekunden.
Deine Signatur ist zu lang.
Nö, für einen alle-100µs-Interrupt muss TOP 149 sein. Du willst 150 Zählerschritte haben, also von 0 bis 149.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.
MfG
Stefan
Wie misst du denn die Ventilöffnungszeit? Mit einem Timer mit Input Capture solltest du die Zeit imho am genauesten messen können. Vorausgesetzt, das Signal kommt von aussen.
Mit dem Input Capture wollte ich das zuerst auch machen, dieser spricht aber nur auf eine steigende Flanke an. Da ich aber nicht die Frequenz sondern die Pulslänge brauche, fällt das leider raus..
Gemessen wird das dann über einen externen Interrupt, je nach Pegel wird ein Counter hochgezählt und der gemessene Wert auf einen 64 Bit Integer addiert (reicht für ein Jahrhundert Dauerbetrieb..). In der Hauptschleife kann ich mir dann einen entsprechenden Literwert zusammenrechnen.
Deine Signatur ist zu lang.
Du kannst programmieren, ob er auf fallende, oder steigende Flanke reagieren soll. TCCR1B Bit 6 0=> fallende Flanke, 1=> steigende Flanke.
Und dann in der ISR jeweils das Bit togglen?
Deine Signatur ist zu lang.
Genau. Die Methode dürfte noch ein wenig präziser sein.
Lesezeichen