Guten Tag,
hab schon die Suchfunktion bemüht und schon einige Stunden mit
Experimenten verbracht, aber ich komme nicht zum gewünschten Ergebnis.
Auch im Datenblatt habe ich für mein Problem nichts gefunden. Leider
komme ich nicht drauf was genau passiert.
Mein Projekt:
Tacho der mittels Reedkontakt die Umdrehungen meines Rades mißt und
daraus unter anderem die Geschwindigkeit errechnet.
Prozessor: ATMEGA169 der dauernd schläft und beim Ticken des asynchronen
Timer2 (64 mal pro Sekunde, macht immer 64 Schritte bei 4096Hz)
aufwacht. Der Reed ist am Pin Change Interrupt welcher auch den Schläfer
weckt.
Code ist mal im Anhang was die problematischen Teile angeht. Um den PCI
kurz zu halten, lese ich beim Schließen des Kontaktes den Timer2 Zustand
aus und die Variable revolution. Mein Rad dreht so langsam, dass der
Timer2 mehrfach tickt, bis eine Umdrehung fertig ist.
Um die Anzahl der Timerschritte zu berechnen, multipliziere ich die
Anzahl der revolutions mit 64, addiere der Timerstand hinzu und
subtrahiere den alten Timerstand vom letzten Mal.
Oh Wunder: Funktioniert wunderbar.
Aber hin und wieder ist das Resultat der Timerschritte falsch, es
scheint um 64 zu hoch oder zu wenig zu sein. Hab beide Effekte.
Liegt es daran, dass beide Interrupts gleichzeitig feuern und dabei die
Berechnung einen Fehler bekommt? Ich inkrementiere die revolutions im
Timer2 Interrupt, denke wenn beide gleichzeitig feuern kommt das einmal
zu spät.
Habe daraufhin in diesem Falle eine revolution zur gezogenen Kopie
hinzugefügt, es kommt aber immer mal sporadisch solch ein Ausreisser
vor.
Timer1 mit 16 Bit wäre natürlich besser geeignet, da entfällt das
Aufzählen der Timer Interrupts. Wegen Stromsparen nutze ich aber nur den
asynchronen Timer2 der leider nur 8 Bit hat.
Ich teste zur Zeit mit einem externen Frequenzgenerator ohne Reed, also
da ist nix mit Prellen und so.
Also: Es funktioniert im Prinzip, aber es kommen selten sporadisch
Ausreisser. Woher kann das kommen? Wie fange ich diese Dinger ab?
Interrupt Spezies: Wer kanns erklären?
Besten Dank
Thomas
Es könnte ein problem mit fast gleichzeitig auftretenden Interrupts
sein. Es kann dann passieren das die Reihenfolge mit der der Overflow
Interrupt und der PCI aufgerufen werden nicht stimmt. Den Fall muß man
dann in Software abfragen, anhand des Zählerstandes. Ein ähnliches
Problem gibt es auch bei der Messung über timer1 mit ICP und Überlauf.
Das prüfe ich schon ab:
if (TIFR2&0x02) //in case Timer2 and PCI fire at the same time, PCI has
priority
{
tmp_rev++;
revolution=0;
}
else
revolution=0;
Wenn beide gleichzeitig feuern hat der externe PRIO und sieht bei TIFR2
nach ob der andere auch will. Dann wird bei tmp_rev einer zugezählt und
das Ergebnis stimmt. Hab den Fall analysiert und die Geschwindigkeit
stimmt hier. Die Ausreisser kommen woanders her. Soweit hab ich es
nachvollzogen...
Kannst du uns ein Modell-Flow-Chart machen.
(Skizze ) und dann hier reinposten.
Möglicherweise geht das noch trickreicher zu
lösen.
Siehe hier im Forum das Project mit
dem 32 Bit-Zähler von Peda. glaube ich.
Das war echt ausgefuchs gemacht.
Mit der mathematischen Korrektur u.
Konditioneller Nachberechnung.
Suche ich auch noch raus.
Ich poste noch das Komplette PDF
Teil. Embedded Design Pattern.
Der Professor schreibt, sonst ist das nicht
störungfrei möglich, OK
aber wieso. ???? Geht das nur so
100% richtig???,
und hier bei dir nur 99,99 %
Der Professor aus der FH Klaustal
hat einen Leitfaden dazu geschrieben,
aber nur nicht das „Zauberwort“ volatile hat
er vor die dedizierten IRQ-Variablen geschrieben.
OK ist halt so... aber warum meldet der
Prof. da bedenken an. ????
Und schaltet dediziert den IRQ_ab und geht die
volatile Varaiablen holen. bzw. lesen und
zwischenspeichern.
Und schaltet danach dediziert den General-Master-IRQ
wieder an.
Aber auch speziell bei den AVRs mit dem GNU C Compiler
ist das volatile var „atomar“ wichtig.!!!!
Siehe Anhang: Störungfreie Ubergabe der
volatile Variablen vom IRQ zum MAIN
1) Dedizierte Befehle mit cli, bzw. sei ...
Befehl im Main.
Hast du Z.B erst mal zum testen
Z.B 10K-Pull-Ups an dem dedizeiten Extern-IRQ PINs??
PitFall:
Die intern MCU-Pulls sind soo weak sometimes.
Grundsätzlich wird
der z.B IRQ_#1 als flg im Latch gespeichert,
falls der andere bearbeitet wird.
Es geht also kein IRQ veschütt.
Der im Rahmen der z.B Latenzzeit
z.B bei 16MHZ respektive liegt.
Hallo Holger,
danke erstmal für die Posts, auch wenn ich nicht ganz folgen kann.
Ich versuche es mal zu erklären was ich tu:
Es gibt zwei Interrupts, den PCI und den Timer2.
Timer2 feuert 64 Mal pro Sekunde und macht zwischendurch 64 Schritte.
Ich möchte die Anzahl der Schritte des Timer2 zwischen zwei PCI messen.
Dazu setze ich im PCI den Wert revolution (volatile) auf 0 und
inkrementiere den in jedem Timer2 Interrupt. Damit weiß ich, wie oft der
Timer gefeuert hat. Wenn der nächste PCI kommt nehme ich mir eine KOPIE
dieses Wertes. Da das in einem Interrupt erfolgt brauche ich kein cli()
und sei(), ich mach keine nested Interrupts. Einverstanden? Die
Atomarität sollte also gewährleistet sein.
Mit new_round=1 signalisiere ich der main() dass eine neue
Geschwindigkeit berechnet werden soll.
Ich habe vorher mir den Wert des TCNT2 kopiert (auch im Interrupt) als
curr_TC.
Dieser fließt bei der Berechnung mit ein und wird für die nächste
Berechnung als old_TC behalten nachdem die Berechnung fertig ist. Alle
Variablen sind volatile.
Die vergangenen Timerticks sind also:
tmp_rev *64 + curr_TC - old_TC im Moment wenn der PCI feuert.
Die Falschwerte die ich ab und an bekomme sind haben immer 64 zu wenig
bei den Timerticks, dadurch bekomme ich eine falsche Geschwindigkeit.
Die Werte für TCNT2 sind oft aber nicht immer 0 in diesem Fall. Den Fall
dass beide IRQ gleichzeitig vorliegen, der PCI also Vorrang hat und der
Timer noch nicht die revolution hochzählen konnte, habe ich abgefangen.
Dieser liefert das korrekte Ergebnis. Die Ausreisser haben einen anderen
Grund.
Ist da in dem Konzept ein Fehler den ichnicht sehe?
Gruß
Thomas
Hi
Sieht mir nach Zählerüberlauf aus. Wenn ich dich richtig verstanden
habe, möchtest du eine Geschwindigkeit messen. Die ergibt sich aus
Zeiteinheiten pro Umdrehung. Also: Zeitinterrupte zählen.
Ereignisimpuls von Umdrehung löst folgendes aus: Gezählte Zeiteinheiten
der Berechnungsroutine auf sep. Variable zur Verfügung stellen und
Zeitzähler auf 0 setzen.Entweder direkt von hier die Berechnung und
Aktualisierung der Anzeige aufrufen, oder Flag setzen und vom
Hauptprogramm Flag bearbeiten lassen. Entschuldige, wenn ich's nicht mit
Code verdeutliche, ich hab von "C" nur einen ganz blassen Schimmer. Aber
immerhin, ich weiß, wie man es schreibt ....
Also, vielleicht noch mal in Blöcke gefasst:
Timer_ISR: Zählen der Interrupts
IO_ISR: Zeitzähler umkopieren,
Zeitzähler löschen
Berechnung auslösen
So sollte es gehen und der Zähler kann so gewählt werden, das er nicht
"überläuft".
Gruß oldmax
Hi Oldmax,
genau so mache ich es und es funktioniert ja richtig!
Nur ab und an bekomme ich "Ausreisser":
Hab das mal analysiert:
Mein externer Taktgenerator läuft mit einer Frequenz, so dass ich etwa
107 "Sachen" fahre. Passt! Jedoch dann und wann fahre ich entweder 135
oder auch mal 88 Sachen.
Bei 4096Hz Takt für Timer2 und einem Radumfang von 2.16m vergehen also
etwa 300 Ticks bei 107km/h.
Bei 88 sind es etwa 364, bei 135 etwa 236. Diese Werte bekomme ich
sporadisch. Es ist also ab und zu ein Fehler von genau 64 Ticks da,
WARUM??
Es kommt nicht vom Doppelinterrupt, wenn also beide zugleich feuern. Den
Fall hab ich analysiert und abgefangen, passt.
Gruß
Thomas
Thomas schrieb:> Bei 88 sind es etwa 364, bei 135 etwa 236. Diese Werte bekomme ich> sporadisch. Es ist also ab und zu ein Fehler von genau 64 Ticks da,> WARUM??>> Es kommt nicht vom Doppelinterrupt, wenn also beide zugleich feuern. Den> Fall hab ich analysiert und abgefangen, passt.
Ganz sicher?
Da sich deine Geschwindigkeit ja normalerweise nicht sprunghaft
verändert, könntest du ja auch mal die Ausreisser mitprotokollieren
(also die Ausgangswerte), wenn es doch passiert. Dann hast du besseres
Zahlenmaterial zur Analyse und bist nicht auf Ratespielchen angewiesen.
Ich bin ziemlich sicher.
Habe einen Parameter definiert, der mir ein Segment meiner Anzeige
einschaltet. Dieser wird mit der Bedingung
if (TIFR2&0x02)
im PCI gesetzt. Das ist wohl der Fall hier. Im PCI ist TIFR2 auf 2, also
wartet der Timer2 Interrupt bis der PCI fertig ist da dieser höhere Prio
hat.
Einsprüche hier?
Mein Segment geht dann und wann an, die Geschwindigket ist aber richtig
in dem Moment. Und im Gegensatz dazu geht mein Segment nicht an, es hat
aber eine falsche Geschwindigkeit gegeben.
Deshalb bin ich einigermassen sicher dass der Fall Doppelinterrupt nicht
mein Problem ist. Ich hab die Ausreisser mal mitprotokolliert, es ist
meist ein Wert von 364 oder 236 Timerticks wenn 300 erwartet wird.
Das sind immer 64 zu viel oder zu wenig, meine simulierte Frequenz von
aussen ist konstant.
Das Abfangen des geleichzeitigen Interupts sieht mir noch nicht ganz
richtig aus. Wenn man den verpaßten Timer Overflow erkannt hat, und dann
durch
tmp_rev++;
revolution=0;
nachholt, muß man den anstehenden Timerinterupt auch noch löschen. Sonst
wird 2 mal erhöht.
Je nachdem ob der Effekt beim Start oder Stop bekommt, gibt das dann den
einen overflow zu viel oder zu wenig.
Sonst ggf. nochmal den kompletten Code zu den ISRs posten.
Ich habe schon diverse Versionen die alle das selbe Problem haben.
Den Timer Interrupt will ich nicht löschen, der macht noch andere
Sachen:
Uhr weiterzählen
LCD steuern. Deshalb bin ich auch auf 64Hz festgelegt.
Ich hänge mal meinen Code dran, das ist eine Version die noch am
wenigsten das Problem zeigt.
Der problematischste Fall ist zu hohe Geschwindigkeit, die wird als
Maximalgeschwindigkeit abgespeichert.
Die Ausreisser nach unten sind nicht ganz so kritisch. Aber ich will
wissen woran es liegt.
Also: ZIP im Anhang.
Besten Dank!!
Super das du den Code gepostet hast.
An duo tüftel IRQ#s rumspielen macht immer viel Spass,
und ich lernt was dabei.
Ich versuche mir immer ein Bild von der Anwendung. zu machen.
Du hast viel Zeit in dein Projekt investiert.
Ist deine Anwendung etwar so wie in diesem Video???
Die ist mit einem PIC gemacht.
Ich habe mal eine Drehzahl in (RPM) mit CAPTURE MODE gemacht.
PIN-EXT-IRQ EDGE GATE geht Puls in das Capture Reg.=Zähler
von 80535 MCU.
Hast du einen Anderen Weg vor falls das nicht
mit deinem Algorithmus klappen sollte.???
1)Ist das so ein Schaltbild ????
http://www.youtube.com/watch?v=ic7t_mYDPWM
Analoges Integral nachbilden. Digitaler Analog-Tacho RPM Rounds Per
MINUTE.
Stichwort: CAPTURE MODE:
VIA TIME-CLOCKS triggers Gated Counter.
++CountedClocks per MCU-CLOCK SPEED
Wie bei der ADC Messung mache ich einen Messbuffer auf,wo die Werte
gemittelt
werden, damit ich da arithmetisch via Mittelwert FILTER:geglättet
rauskomme.
Du hast keinen Mittelbuffer in deinem Code.
Viel Erfolg.
Gruss Holger.
Bei der Erkennung eines noch ausstehenden Overflow Interrupts könnte ein
Fehler passieren. Genau hab ich es nicht kontrolliert, aber besonders
wenn der Takt relativ hoch ist, könnte es passieren, das die ISR für den
Overflow zu schnell fertig wird, trotz der länge. Dann wäre der Counter
2 noch beim Wert 0, obwohl die Overflow ISR schon ganz fertig ist.
Meiner meinig nach sicherer geht das Erkennen eines aussteheden
Interrupts über das Interrupt flag Register, zusammen mit der Forderung
das der Timerwert klein ist. So funktioniert es jedenfalls bei Timer1
und ICP.
An 2.tes Mögliches Problem könnte ein mechnisches Prellen sein. Das
sollte dann aber zu ausreißen mit deutlich zu hoher Geschwindigkeit
führen, nicht gerade der eine falsche Überlauf.
http://www.ermicro.com/blog/?p=1461
Flow-Charts sind auch dabei.
Ich habe den Code mal analysiert.
Da ist eine STATE-ENGINE für PCI drin
(PIN-CHANGE-IRQ)= PCI
Einfach und sicher, denke ich..
Mit Kombinations-Hilfe als TIMER OVERFLOW IRQ
= (TOVR-IRQ)
Sauber gemacht mit case switch().....
IRQ ACK, u. volatile....Koppel-Variablen.
Gruss Holger.
// PIC18 High-priority Interrupt Service
void interrupt high_isr(void){
static unsigned char pulse_state=0;
unsigned int rpm_timer;
if (TMR0IF) { // Check for TIMER0 Overflow
Interrupt
rpm_value = 0; // Reset the global volatile RPM
Value
TMR0IF=0; // Clear TIMER0 interrupt
flag,T-OVR_(ACK-IRQ#1AVR)
}
if (INT0IF){ // Check for External INT0 Interrupt
switch(pulse_state) {
case 0: // First Low to High Pulse
TMR0H = 0; // Zero the high byte in TMR0H
Buffer
TMR0L = 0; // Clear 16-bit TIMER0 Counter
pulse_state=1; // P´reset for-Next_STATE ‘#S1
break;
case 1: // Second Low to High Pulse at STATE
‘#
rpm_timer=TMR0L; // Get the first 8-bit TIMER0
Counter
rpm_timer+=(TMR0H << 8); // Get the last 8-bit TIMER0 Counter
// Calculate RPM = 60 x (1/Period)
// RPM Value = 60000 (1 / (0.032 ms x rpm_timer))
rpm_value = (int) (60000.0 / (0.032 * rpm_timer));
pulse_state=0;// XOR P´reset forNext_STATE ‘#S0
}
INT0IF = 0; // Clear INT0 interrupt flag,
_(ACK-IRQ#1AVR)
}
Danke erstmal an euch, aber ich bin nich sicher dass ich das Problem
verstehe. Ulrich schreibt:
"Bei der Erkennung eines noch ausstehenden Overflow Interrupts könnte
ein
Fehler passieren. Genau hab ich es nicht kontrolliert, aber besonders
wenn der Takt relativ hoch ist, könnte es passieren, das die ISR für den
Overflow zu schnell fertig wird, trotz der länge. Dann wäre der Counter
2 noch beim Wert 0, obwohl die Overflow ISR schon ganz fertig ist."
Was ist damit gemeint? Die Erkennung des ausstehenden Timer IRQ wenn der
PCI feuert?
Was ist gemeint mit "zu schnell fertig"? Wenn TCNT2 nach dem Timer
Interrupt immer noch auf 0 ist so ist das aus meiner Sicht normal und
OK. Ich hab das Problem mit 500KHz Takt und auch 8MHz.
Welchen Fall muss ich denn nun genau analysieren? Ich sehe drei
Möglichkeiten:
1.PCI feuert alleine, so ist es üblich. Sollte unproblematisch sein.
2.Timer und PCI feuern gleichzeitig: PCI hat Prio, Timer wird nacher
bedient.
3.Timer IRQ wird bedient, PCI funkt dazwischen.
Für Punkt drei habe ich es mal mit und ohne nested Interrupt versucht,
das Problem bleibt.
Was meinst du Ulrich? Geht es um Punkt 2?
Ich fürchte ich stehe hier auf dem Schlauch.
Das Problem mit der zu schnellen Ausführung des Interrupts könnte
passieren, wenn erst der Timer Interrupt Auftriff, und dann gleich
danach der PCI. Mit dem 500 kHz Takt sollte das aber eher selten
passieren. Auch sonst ist da Zeitfenstser vermutlich ziehmlich keine und
der Fehler würde nur sehr selten auftreten.
Mir ist da noch eine Mögliche Fehlerquelle eingefallen: Bei einigen der
AVRs gibt es einen Fehler beim Timer, und es kann passieren das ein
Timer Interrupt verloren geht, wenn man zur falschen Zeit in das OCR
register schreibt. Habs nicht genau nachgelesen, nur so aus dem
Gedächnis.
Hi Ulrich,
stimmt, hab ich irgendwie nicht so richtig verstanden. Aber diese
Änbderung bringt es auch nicht:
TCCR2A |= (1<<CS21) | (1<<WGM21);
while (ASSR&0x01) ;//wait until OCR2UB reads 0, TCNT2 reads correctly
curr_TC = TCNT2;//take snapshot of timer 2 status NOW!
Hatte da vorher den OCR2A beschrieben, das ist ungünstig. Habe in
anderen Versionen auch schon mal das Timer IF Register gelsesen anstatt
TCNT2 auf 0 zu prüfen. Egal was ich versuche, das Problem bleibt.
Danke für den Tip erstmal.
Hi
Ich habe mal deine Geschwindigkeitsmessung nachgerechnet.... Also, wenn
du mit 64 Hz über eine Bewegung die Zeitimpulse mißt, also alle 15,2ms
dann ist deine Rotationsgeschwindigkeit 1/(imp*(1/64)) also
1/(imp*0,0152s)
Annahme, dein Rad hat 1 m Umfang und du hast bei einer Umdrehung 17
Impulse gezählt, dann ergibt das 3,77 m/s.
Hochgerechnet 13,574 Km/h.
nächste Annahme : du hast 18 Impulse gezählt ergibt eine
Umfangsgeschwindigkeit von 12,8Km/h.
Nun lassen wir das Rad mal langsam drehen.. also wesentlich mehr
Zeitinterrupts zählen. Angenommen 1000
Also (1/(1000*1/64))*60*60 ergibt 230,4 m/h
2. Rechnung mit 1001 Impulsen (1/(1001*1/64))*60*60 =230,1 m/h
Nun lassen wir es mal extrem schnell laufen, d. h. es gibt nur wenige
gezählte Zeitinterrupts z. 2
Also (1/(2*1/64))*60*60 ergibt 115,2 km/h
2.Rechnung mit 3 Impulsen (1/(3*1/64))*60*60 ergibt 76,8 km/h
Wenn du nun knapp um den nächsten Zeitimpuls drehst, kann die
Ungenauigkeit der Reed-Kontakte dazu führen, mal einen Zeitimpuls mehr
oder weniger zu sehen, je nachdem. Irgendwo multiplizierst du diese
Zeitimpulse auch noch mit 64, wofür auch immer. Kein Wunder, das dein
Fehler auch diese 64 irgendwie aufzeigt.....
Zu deinem Programm: Ich hab keine Ahnung von C, aber soviel ich sehe,
ist deine Rechnung auch falsch. Wenn du genauer werden möchtest, dann
löse mit ms auf und leite die anderen Ereignisse aus dieser ms ab. Dazu
wird der Timer mit entsprechendem Vorteiler und Überlauf
parametriert.Dazu kann ich hier das Timer-Tutorial empfehlen.
Hier mal beispielsweise den Unterschied aus ms-Interrupts
Also (1/(1000*0,001s))*60*60 ergibt 3,6 km/h
(1/(1001*0,001s))*60*60 ergibt 3,596 km/h
(1/(10*0,001s))*60*60 ergibt 360 km/h
(1/(11*0,001s))*60*60 ergibt 327,272km/h
Du siehst, 1 Interrupt mehr oder weniger fällt nicht so stark ins
Gewicht.
Diese Rechnung hab ich überhaupt nicht durchschaut....
new_round=0;
{
time = tmp_rev*64+curr_TC-oldTC;
loc_tmp= 2160;
loc_tmp= 72*loc_tmp;
loc_tmp/=time;
veloc=(loc_tmp+2)/5; //km per hour, rounding included
}
oldTC=curr_TC; //remember last Timer value
Vielleicht seh ich das aber auch nur falsch, weil ich deinen Code nicht
versteh.
Gruß oldmax
Hallo Oldmax,
ich weiß, der Code von anderen (und meine eigener nach ein paar Wochen)
ist immer schwer zu verstehen. Ich erkläre es gerne mal:
Ich betreibe ein LCD das mit 32Hz umschaltet, deshalb nehme ich den
Timer2 mit 64Hz. Der ist fest, kann ich nicht ändern. Ausserdem zählt er
meine Uhr weiter.
Die 64Hz sind aber nur die Überläufe, die Schrittweite ist 1/4096Hz also
etwas mehr als 240µs.
Ich zähle nicht allein die Überläufe (revolution) sondern lese auch den
TCNT2 aus. Damit bekomme ich eine schön hohe Auflösung.
Beispiel:
Reed schaltet, ich lese TCNT2=20 aus und revolution=10.
Nächste Umdrehung:
TCNT2 = 55, revolution = 10.
Zwischen den Reed Schaltpunkten habe ich also 10*64 +55-20 Timerticks
gehabt, das sind 675 Ticks zu 244µs. Auflösung ist 244µs, reicht mir
vollkommen aus.
64 weil jede revolution schon 64 Ticks hatte, 55 weil ich in diesem
Timerzyklus bis 55 gekommen bin und -20 weil ich letztes Mal bei erst
bei 20 angefangen habe.
Ich hoffe es ist klar geworden. Klar kann ich für diese Spielereien den
16 Bit Timer1 nehmen, aber den kann ich nicht asynchron betreiben wie
Timer2. Stichwort: Stromsparen.
Ich hab das in anderen Projekten auch schon mal so gemacht, geht auch
braucht aber mehr Strom. Es fällt ein Timertick nicht so ins Gewicht,
ein Überlauf zuviel oder zu wenig schon. Ich stimme zu, das löst aber
nicht mein Problem.
Zur Info: Es funktioniert ja richtig, die Geschwindigkeit wird genau
angezeigt, alles super.
Mein Problem sind die Ausreisser dann und wann, oder um genau zu sein:
Was verursacht die denn?? Wenn ich es verstanden habe kann ich es
bestimmt lösen.
Gruß
Thomas
Hi
Jetzt hab ich's verstanden... Na ja, bin ja auch schon etwas älter, da
rieselt's schon leicht. Aber ich bin noch lernfähig.
Ok, dann werd ich mal weiter denken... Ich bin immer noch davon
überzeugt, es liegt an der Multiplikation mit 64...
Gruß oldmax
Guten Morgen,
noch eine kurze Rückmeldung an MWS:
Das hatte ich schon alles versucht, offensichtlich kommt das Problem
nicht nur vor wenn die Interrupts zusammenfallen. Hat leider nicht
geholfen.
Ich hab den Testcode mal angehängt, so habe ich das Problem mal ohne das
ganze LCD Gerümpel nachgebildet.
Hat jemand eine Idee was da passiert? Ich feuere den externen Interrupt
mit etwa 13.6Hz. Auch bei anderen Frequenzen tritt das sporadisch auf.
Bin bis Freitag beruflich unterwegs und kann mich erst dann wieder
melden.
Gruß
Thomas
Und nochwas:
Ich hab mal die Ticks anders berechnet, nicht revolutions aufgezählt und
dann mit 64 multipliziert, sondern jeden Interrupt die Variable um 64
erhöht, das spart die Multiplikation.
Und plötzlich kommt das Problem nur noch SEHR vereinzelt vor, und dann
scheint mir der TC Null zu sein.
Sehe ich mir an wenn ich wieder Zeit habe, am Wochenende geht es weiter.
Bid die Tage,
Gruß
Thomas
> Hat jemand eine Idee was da passiert?
So wie ich das sehe hast Du da keine groben Schwankungen, sondern nur
einen Fehler von 1, gleichbedeutend der kleinsten Auflösung des Timers.
Das ist normal, wenn Timerfrequenz und Sampelfrequenz in keinem fest
verzahnten Zusammenhang steht. Die Genauigkeit würde besser, wenn der
Prescaler 1 würde und der Timer einfach durchläuft, also ohne Compare.
Den Rest wie gehabt, im Ovf Int die Runden zählen und ggf. anstehende
Ovf Ints in der PC Int behandeln.
Der Thread ist ja schon etwas älter, gibt es da inzwischen eine Lösung?
Ich vermute, dass es daran liegt, dass in der main mit Variablen
gerechnet wird, die größer als 8bit sind. Problemlösung müsste dann
sein, während der Rechnung die Interrupts abzuschalten.