INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.

Antwort schreiben 
 
Themabewertung:
  • 0 Bewertungen - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Seltsamer Fehler bei Vergleichsoperation
19.01.2017, 22:00
Beitrag #1
Seltsamer Fehler bei Vergleichsoperation
Hallo,

Code:
while (irqCounter < 2000) {
}
Serial.println(irqCounter);

void Irq1()
{
  irqCounter++;
}
irqCounter ist volatile uint16_t
Irq1 wird von steigender Flanke an Pin 3 ausgelöst (Arduino UNO)
an Pin 3 liegt ein Taktsignal von extern (ca. 3kHz)

Ich hätte erwartet dass das Programm in der while-Schleife so lange "hängen" bleibt wie irqCounter < 2000 ist.
Die Ausgabe sollte also immer >= 2000 sein.

Serial.println(irqCounter); sagt aber
1792
2000
1792
1792
2000
2000
2000
2000
2000
2000
wenn ich 10 Durchläufe mache.

Bei 1792 ist das niederwertige Byte 0x0, das geht also scheinbar verloren.

Wenn ich in der while-Schleife nur bis 1000 zähle ist die Fehlerhafte Ausgabe 768.
Bei 768 fehlt auch das niederwertige Byte um auf 1000 zu kommen.

Ob überhaupt und wie oft und an welchen Stellen der 10 Durchläufe ein fehlerhafter Abbruch der while-Schleife auftritt ist scheinbar zufällig.

Hat jemand eine Vermutung warum die while-Schleife zu früh abgebrochen wird oder liegt der Hund sonstwo begraben?

Gruß
Arne

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
19.01.2017, 22:30
Beitrag #2
RE: Seltsamer Fehler bei Vergleichsoperation
(19.01.2017 22:00)ardu_arne schrieb:  Hallo,

Code:
while (irqCounter < 2000) {
}
Serial.println(irqCounter);

void Irq1()
{
  irqCounter++;
}
irqCounter ist volatile uint16_t
Irq1 wird von steigender Flanke an Pin 3 ausgelöst (Arduino UNO)
an Pin 3 liegt ein Taktsignal von extern (ca. 3kHz)

Ich hätte erwartet dass das Programm in der while-Schleife so lange "hängen" bleibt wie irqCounter < 2000 ist.
Die Ausgabe sollte also immer >= 2000 sein.

Serial.println(irqCounter); sagt aber
1792
2000
1792
1792
2000
2000
2000
2000
2000
2000
wenn ich 10 Durchläufe mache.

Bei 1792 ist das niederwertige Byte 0x0, das geht also scheinbar verloren.

Wenn ich in der while-Schleife nur bis 1000 zähle ist die Fehlerhafte Ausgabe 768.
Bei 768 fehlt auch das niederwertige Byte um auf 1000 zu kommen.

Ob überhaupt und wie oft und an welchen Stellen der 10 Durchläufe ein fehlerhafter Abbruch der while-Schleife auftritt ist scheinbar zufällig.

Hat jemand eine Vermutung warum die while-Schleife zu früh abgebrochen wird oder liegt der Hund sonstwo begraben?

Gruß
Arne
Wenn Du außerhalb der Interruptfunktion (Irq1?) auf die Variable irqCounter zugreifst, musst Du vorher die Interrupts abschalten und danach wieder einschalten.
Das geht in der while() so nicht. Es kann (und wird) Dir passieren, dass mitten im Lesen, die Variable von der ISR verändert wird.

Also sowas (Pseudocode)
int wert; // Type wie irqCounter
interrrupt aus
wert = irqCounter;
interrupt an
wert verarbeiten

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
19.01.2017, 22:43
Beitrag #3
RE: Seltsamer Fehler bei Vergleichsoperation
Danke Tommy,
ich habe zwar auch cli() und sei() (eigentlich übertrieben) verwendet, aber vermutlich an den falschen Stellen. Den Teil hatte ich aber im Post weggelassen weil ich dort den Fehler nicht vermutet habe.

Deine Erklärung leuchtet mir ein.
Werde testen und berichten.

Gruß
Arne

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
20.01.2017, 08:22
Beitrag #4
RE: Seltsamer Fehler bei Vergleichsoperation
(19.01.2017 22:00)ardu_arne schrieb:  Hallo,

Code:
while (irqCounter < 2000) {
}
Serial.println(irqCounter);

void Irq1()
{
  irqCounter++;
}
irqCounter ist volatile uint16_t
Irq1 wird von steigender Flanke an Pin 3 ausgelöst (Arduino UNO)
an Pin 3 liegt ein Taktsignal von extern (ca. 3kHz)

Ich hätte erwartet dass das Programm in der while-Schleife so lange "hängen" bleibt wie irqCounter < 2000 ist.
Die Ausgabe sollte also immer >= 2000 sein.

Serial.println(irqCounter); sagt aber
1792
2000
1792
1792
2000
2000
2000
2000
2000
2000
wenn ich 10 Durchläufe mache.

Bei 1792 ist das niederwertige Byte 0x0, das geht also scheinbar verloren.

Wenn ich in der while-Schleife nur bis 1000 zähle ist die Fehlerhafte Ausgabe 768.
Bei 768 fehlt auch das niederwertige Byte um auf 1000 zu kommen.

Ob überhaupt und wie oft und an welchen Stellen der 10 Durchläufe ein fehlerhafter Abbruch der while-Schleife auftritt ist scheinbar zufällig.

Hat jemand eine Vermutung warum die while-Schleife zu früh abgebrochen wird oder liegt der Hund sonstwo begraben?

Gruß
Arne

Hi Arne, sorry, aber in deiner While-schleife passiert meiner Meinung nach gar nichts, weil Geschwungene Klammer auf und gleich wieder zu, oder hab ich da was falsch interpretiert?
lg, Claus
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
20.01.2017, 12:01
Beitrag #5
RE: Seltsamer Fehler bei Vergleichsoperation
(20.01.2017 08:22)Claus_M schrieb:  ...
Hi Arne, sorry, aber in deiner While-schleife passiert meiner Meinung nach gar nichts, weil Geschwungene Klammer auf und gleich wieder zu, oder hab ich da was falsch interpretiert?
lg, Claus

Hi Claus, das hast du alles richtig interpretiert!

Vor der while-Schleife merke ich mir Zeit und setze "irqCounter" auf 0.
Dann werden Interrupts freigegeben und "irqCounter" wird in der Interruptroutine "Irq1()" hochgezählt.
Während dessen soll das Programm in der while-Schleife hängen bleiben solange "irqCounter" kleiner 2000 ist.
Wenn "irqCounter" dann >= 2000 ist wird die while-Schleife verlassen. Dann messe ich wieder die Zeit und verrechne die mit der Zeit als ich "irqCounter" auf 0 gesetzt hatte. Dann weiß ich wie lange es gedauert hat um von 0 auf 2000 zu zählen.
So war mein Plan und in der while-Schleife ist dann auch wirklich nichts zu tun außer Zeit tot zu schlagen.
Das Problem war dass die while-Schleife manchmal schon verlassen wurde wenn "irqCounter" erst bei 1792 angekommen war.

Ich habe es jetzt etwas anders gelöst und es funktioniert.
Im Programm setze ich jetzt eine Variable "startwert" auf 2000, eine Variable "fertig" auf false und merke mir die aktuelle Zeit micros().
Dann werden Interrupts freigegeben und in der Interruptroutine "Irq1()" wird "startwert" nach unten gezählt. Wenn "startwert" 0 erreicht hat wird "fertig" auf true gesetzt.
Im Programm frage ich dann ab ob "fertig" auf true gesetzt ist und nehme dann erneut die Zeit. So kann ich dann auch sehen wie lange es gedauert hat bis 2000 Impulse am Interruptpin angekommen sind.

Code:
void Irq1()
{
  startwert--;
  if (startwert == 0)  fertig = true;
}

Tommy56 hatte in seiner Antwort das eigentliche Problem in meinem ersten Lösungsansatz richtig erkannt. Der Controller (UNO) ist ein 8 Bit "Erbsenzähler". Der kann also gleichzeitig immer nur mit einem Byte arbeiten. Die Variable "irqCounter" war aber eine Integer Variable die aus zwei Byte besteht. Der Controller verarbeitet diese beiden Byte aber nacheinander. Wenn der Controller dann erst ein Byte verarbeitet hat und es kommt dann zu einem Interrupt kam es zu dem o.g. Fehler.

Gruß
Arne

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
20.01.2017, 13:49
Beitrag #6
RE: Seltsamer Fehler bei Vergleichsoperation
(20.01.2017 12:01)ardu_arne schrieb:  
(20.01.2017 08:22)Claus_M schrieb:  ...
Hi Arne, sorry, aber in deiner While-schleife passiert meiner Meinung nach gar nichts, weil Geschwungene Klammer auf und gleich wieder zu, oder hab ich da was falsch interpretiert?
lg, Claus

Hi Claus, das hast du alles richtig interpretiert!

Vor der while-Schleife merke ich mir Zeit und setze "irqCounter" auf 0.
Dann werden Interrupts freigegeben und "irqCounter" wird in der Interruptroutine "Irq1()" hochgezählt.
Während dessen soll das Programm in der while-Schleife hängen bleiben solange "irqCounter" kleiner 2000 ist.
Wenn "irqCounter" dann >= 2000 ist wird die while-Schleife verlassen. Dann messe ich wieder die Zeit und verrechne die mit der Zeit als ich "irqCounter" auf 0 gesetzt hatte. Dann weiß ich wie lange es gedauert hat um von 0 auf 2000 zu zählen.
So war mein Plan und in der while-Schleife ist dann auch wirklich nichts zu tun außer Zeit tot zu schlagen.
Das Problem war dass die while-Schleife manchmal schon verlassen wurde wenn "irqCounter" erst bei 1792 angekommen war.

Ich habe es jetzt etwas anders gelöst und es funktioniert.
Im Programm setze ich jetzt eine Variable "startwert" auf 2000, eine Variable "fertig" auf false und merke mir die aktuelle Zeit micros().
Dann werden Interrupts freigegeben und in der Interruptroutine "Irq1()" wird "startwert" nach unten gezählt. Wenn "startwert" 0 erreicht hat wird "fertig" auf true gesetzt.
Im Programm frage ich dann ab ob "fertig" auf true gesetzt ist und nehme dann erneut die Zeit. So kann ich dann auch sehen wie lange es gedauert hat bis 2000 Impulse am Interruptpin angekommen sind.

Code:
void Irq1()
{
  startwert--;
  if (startwert == 0)  fertig = true;
}

Tommy56 hatte in seiner Antwort das eigentliche Problem in meinem ersten Lösungsansatz richtig erkannt. Der Controller (UNO) ist ein 8 Bit "Erbsenzähler". Der kann also gleichzeitig immer nur mit einem Byte arbeiten. Die Variable "irqCounter" war aber eine Integer Variable die aus zwei Byte besteht. Der Controller verarbeitet diese beiden Byte aber nacheinander. Wenn der Controller dann erst ein Byte verarbeitet hat und es kommt dann zu einem Interrupt kam es zu dem o.g. Fehler.

Gruß
Arne

Wow, das ist schon sehr fortgeschritten alles.... Da muss man mal draufkommen....

LG, Claus
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
20.01.2017, 14:16
Beitrag #7
RE: Seltsamer Fehler bei Vergleichsoperation
(20.01.2017 12:01)ardu_arne schrieb:  Ich habe es jetzt etwas anders gelöst und es funktioniert.
Im Programm setze ich jetzt eine Variable "startwert" auf 2000, eine Variable "fertig" auf false und merke mir die aktuelle Zeit micros().
Dann werden Interrupts freigegeben und in der Interruptroutine "Irq1()" wird "startwert" nach unten gezählt. Wenn "startwert" 0 erreicht hat wird "fertig" auf true gesetzt.
Im Programm frage ich dann ab ob "fertig" auf true gesetzt ist und nehme dann erneut die Zeit. So kann ich dann auch sehen wie lange es gedauert hat bis 2000 Impulse am Interruptpin angekommen sind.

Code:
void Irq1()
{
  startwert--;
  if (startwert == 0)  fertig = true;
}
Fertig ist als boolean 1 Byte lang und der Zugriff darauf atomar.
Sehr gut gemacht.

Gruß Tommy

"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
20.01.2017, 15:41
Beitrag #8
RE: Seltsamer Fehler bei Vergleichsoperation
(20.01.2017 14:16)Tommy56 schrieb:  ...
Fertig ist als boolean 1 Byte lang und der Zugriff darauf atomar.
Sehr gut gemacht.

Gruß Tommy

So ist es.
"fertig" ist volatile bool deklariert.

Jetzt funktioniert es auch wieder mit der kurzen while-Schleife.
Code:
...
  fertig = false;
  unsigned long dauer = micros();
  while (!fertig) {  }
  dauer = micros() - dauer;
  ...
Code:
void Irq1()
{
  startwert--;
  if (startwert == 0)  fertig = true;
}

Etwas kryptisch programmiert, aber für kryptischen C-Code gibt es sogar Meisterschaften. Big Grin

Gruß
Arne

Gruß Arne
Mit zunehmender Anzahl qualifizierter Informationen bei einer Fragestellung, erhöht sich zwangsläufig die Gefahr auf eine zielführende Antwort.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren
Antwort schreiben 


Möglicherweise verwandte Themen...
Thema: Verfasser Antworten: Ansichten: Letzter Beitrag
  Undefined reference-Fehler beim Kompilieren MdE 9 172 24.03.2020 21:39
Letzter Beitrag: Tommy56
  Stepper Motor mit zwei Taster bedienen / Fehler ohne Fehlermeldung Milano 6 222 21.03.2020 16:06
Letzter Beitrag: MicroBahner
  Fehler bei Kompilieren ak68 6 218 21.03.2020 13:12
Letzter Beitrag: Tommy56
  Arduino Taster - Welcher Fehler? lil.chem 4 352 10.02.2020 22:39
Letzter Beitrag: Franz54
  Compiler Fehler Meldung TKK-Arduino 40 1.568 09.02.2020 14:28
Letzter Beitrag: TKK-Arduino
  Nextion Fehler bei Button Abfrage wenn ich zusätzlich Text sende MarkZero0815 24 1.082 28.01.2020 08:23
Letzter Beitrag: hotsystems
  Fehler beim Kompilieren für das Board ... Kurt Wallander 20 1.447 13.11.2019 21:55
Letzter Beitrag: Tommy56
  DCF77 Fehler beim Kompilieren Xwill 6 1.825 11.11.2019 19:55
Letzter Beitrag: Kurt Wallander
Photo RGB-LED faden [Fehler im Code] Botographic 4 731 02.09.2019 14:42
Letzter Beitrag: Botographic
  Fehler beim Hochladen auf Atmega 328 delay 17 1.846 30.07.2019 12:33
Letzter Beitrag: Tommy56

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste