Hi,
ich habe einen sehr einfachen Versuchsaufbau und einen sehr sehr simplen
Code und bekomme da einen Fehler.
Ich habe eine Inkrementalscheibe mit Gabellichtschranke und diese an
einem externen Interrupt angeschlossen. Zwischen zwei externen
Interrupts zähle ich wie oft der Timer0 überläuft in einer volatile
UNSINGED int oder long und bekomme hin und wieder wenn ich die
Inkrementalscheibe drehe negative Werte für die Variable. Wie zur Hölle
kann das sein?
(ATmega32 UART Code ausgeblendet)
Dirk D. schrieb:> printf("%d\n",counter256);
Gibt einen signed int aus, du hast aber einen unsigned long. Ändere
deine printf-Formatierung zu %lu
Merkwürdig das der Compiler keine Warnung schmeißt...
Was machst du eigentlich mit der Variable "counterUmdrehung3"? Die
scheint überflüssig!?
Ingo L. schrieb:> Was machst du eigentlich mit der Variable "counterUmdrehung3"? Die> scheint überflüssig!?
Ja noch. Habe ein komplexeres Programm und Schritt für Schritt den Code
vereinfacht um den Fehler zu finden.
Erstmal gibst Du mit
printf("%d\n",counter256);
eine signed in aus. Du hast aber eine unsigned int, also benutze %u.
Und dann ist es sinnvoll, auf Deine counter256 Variable vor Interrupts
geschützt zuzugreifen. Sonst kann z.B. sowas passieren:
counter256 hat den Wert 1ffh
main löscht High-Byte von counter256 -> Wert jetzt 0ffh
ISR-Einsprung
ISR incrementiert counter256 -> Wert jetzt 0x100h
ISR-Ende
main löscht Low-Byte von counter256 -> Wert jetzt 100h
Dasselbe kann Dir auch bei der printf-Ausgabe passieren: High-und
Low-Byte müssen an printf als Parameter übergeben werden, tritt
dazwischen ein ISR mit Überlauf auf, ist das Ergebnis falsch.
Gruß, Stefan
Stefan K. schrieb:> Erstmal gibst Du mit> printf("%d\n",counter256);> eine signed in aus. Du hast aber eine unsigned int, also benutze %u.>> Und dann ist es sinnvoll, auf Deine counter256 Variable vor Interrupts> geschützt zuzugreifen. Sonst kann z.B. sowas passieren:>> counter256 hat den Wert 1ffh> main löscht High-Byte von counter256 -> Wert jetzt 0ffh> ISR-Einsprung> ISR incrementiert counter256 -> Wert jetzt 0x100h> ISR-Ende> main löscht Low-Byte von counter256 -> Wert jetzt 100h>> Dasselbe kann Dir auch bei der printf-Ausgabe passieren: High-und> Low-Byte müssen an printf als Parameter übergeben werden, tritt> dazwischen ein ISR mit Überlauf auf, ist das Ergebnis falsch.>> Gruß, Stefan
Dirk D. schrieb:> Meinst du so?
fast, üblicherweise holt man sich nur kurz die Variable und gibt dann
den
Interupt wieder frei. Zeitaufwendigere Sachen wie printf kann man danach
in Ruhe machen
Stefan K. schrieb:> Ja, schon besser.> Noch genauer wird es so:
Vielen Dank! Die richtige Formatierung bei printf mit %lu oder %u hatte
den Fehler schon behoben. Allerdings glaube ich, dass durch die korrekte
Behandlung der Variablen in und um die ISR die du vorgeschlagen hast
mein Hauptfehler beseitigt oder verbessert wurde, nach dem ich
eigentlich auf der Suche war.
1
// gib den Zählerwert als unsigned long aus:
2
printf("%lu\n",myCounter);
3
counter256=0;
ist counter256 nicht an der Stelle schon Null, da er ja in der
ISR(INT1_vect) schon auf Null gesetzt wird?
Wenn ich meine Inkrementalscheibe mit einer konstanten Geschwindigkeit
angetrieben habe, habe ich ohne deine Korrekturen Messfehler erhalten.
Dann hatte ich in periodischen Abständen etwa solche Messergebnisse:
Terminal:
80
81
79
80
80
83
78
1
5
1
87
79
Also ein Abfallen der Werte, ohne dass sich die Antriebsgeschwindigkeit
geändert hätte. Nach deinen Korrekturen ist das Abfallen nicht mehr so
stark, aber immer noch vorhanden.
Terminal:
81
77
78
79
76
75
79
78
73
47
27
76
48
29
46
28
45
28
28
49
28
76
74
74
76
77
Dass die Werte nicht permanent auf einem konstanten Wert sind führe ich
auf einen nicht perfekten Rundlauf der Welle mit der Inkrementalscheibe
zurück. Aber das Abfallen der Werte kann ich mir immer noch nicht
erklären.
Dirk D. schrieb:> ist counter256 nicht an der Stelle schon Null, da er ja in der> ISR(INT1_vect) schon auf Null gesetzt wird?
das stimmt, aber er ist vermutlich nicht mehr null sondern wurde
zwischenzeitlich schon erhöht, das wird vermutlich auch deine zu kleine
Werte verursachen
Walter S. schrieb:> Dirk D. schrieb:>> ist counter256 nicht an der Stelle schon Null, da er ja in der>> ISR(INT1_vect) schon auf Null gesetzt wird?>> das stimmt, aber er ist vermutlich nicht mehr null sondern wurde> zwischenzeitlich schon erhöht, das wird vermutlich auch deine zu kleine> Werte verursachen
Ich bilde mir ein, dass es besser ist. Aber es tritt leider immer noch
auf :/
Sorry, das Löschen des counter256 hinter dem printf() ist natürlich ein
Fehler. Das kann da ersatzlos verschwinden. Das war wieder typisch
copy/paste ...
Viele Grüße, Stefan
lalala schrieb:> Kann auch die Anbindung der Scheibe an den Controller sein. Wie stellst> Du sicher, das mix einstreut? Schaltplan?
Wie meinst du das? Ich verwende das AVR-NET-IO Board und am INT1 Pin vom
ATmega32 liegt der Ausgang des Sensors an. Alle Kabel sind vernünftig
gelötet und mit Schrumpfschläuchen abisoliert. Ein Wackeln an den Kabeln
beeinflusst auch nicht das Messergebnis.
Ich kann dir auch einen Schaltplan erstellen, aber dafür hab ich kein
Programm zur Hand.
Dirk D. schrieb:> Ich kann dir auch einen Schaltplan erstellen, aber dafür hab ich kein> Programm zur Hand.
Eagle von Cadsoft kann da helfen. Die haben auch einen formschönen
Schaltplaneditor.
Dirk D. schrieb:> lalala schrieb:> Kann auch die Anbindung der Scheibe an den Controller sein. Wie stellst> Du sicher, das mix einstreut? Schaltplan?>> Wie meinst du das? Ich verwende das AVR-NET-IO Board und am INT1 Pin vom> ATmega32 liegt der Ausgang des Sensors an. Alle Kabel sind vernünftig> gelötet und mit Schrumpfschläuchen abisoliert. Ein Wackeln an den Kabeln> beeinflusst auch nicht das Messergebnis.>> Ich kann dir auch einen Schaltplan erstellen, aber dafür hab ich kein> Programm zur Hand.
Wackel nicht, aber was passiert wenn Du mal Dein Handy daneben legst
(und dann noch mal anrufst?)
Es war die Unwucht der Welle und das leichte Eiern der
Inkrementalscheibe. Hab das behoben und jetzt funktioniert es, wie es
soll.
Danke an alle die mir geholfen haben!