while beendet obwohl nicht "0"

Gast #2741341
Lesenswert?
• ▲
▼
Nabend.

Ich bin dabei mit eine Motorsteuerung zu bauen, welche über 
Hallsensoren, welche über 6Magnete angesteuert werden zählen kann in 
welcher Position die Welle sich befindet.

Leider habe ich beim Zählen (450Schritte Linkslauf) das Problem, das er 
teilweise (jedes 5-7te mal) nach geschätzt der Hälfe stehen bleibt.

Darauf hin habe ich das Signal der Hallsensoren auf dem Oszilloskop 
angeschaut und gesehen das vereinzelnt Spikes vorhanden sind, weswegen 
ich also eine Schleife eingebaut habe, welche nicht sofort zählt.


Nachdem ich nun 1Woche dabei bin habe ich mal Spaßeshalber aus:
1
while(CountPulses) {
2
}

den Befehl:
1
while(CountPulses) {
2
}
3
while(CountPulses) {
4
}

gemacht. Also einfach die Abfrage doppelt genommen und siehe da: Es 
funktioniert (50Durchläufe).

Kann mir jemand sagen woran das liegt?
Count Pulses ist eine volatile 16Bit Variable.

Pollen mache ich über Timer0 mit einem Teiler von 8:
1
ISR(TIMER0_OVF_vect) {
2
     uint8_t temp=PHall1;
3
     if(!((temp&Hall1)==((temp&Hall2)>>1))) {
4
          if(((Status&LetzteHall1)==(temp&Hall1))) {
5
               switch (Status&0xC0) {
6

7
                    case 0x80:
8
                         break;
9

10
                    case 0x40:
11
                         Status^= LetzteHall1;
12
                         Status+= 0x40;
13

14
                    default:
15
                         Status&= 0xCF;
16
                         Status+= 0x40;
17
                         break;
18

19
               }
20
          } else {
21
               switch (Status&0x30) {
22

23
                    case 0x20:
24
                         break;
25

26
                    case 0x10:
27
                         if((Status&Drehrichtung)) {
28
                              CountPulses++;
29
                         } else {
30
                              CountPulses--;
31
                         }
32
                         Status+= 0x10;
33
                         break;
34

35
                    default:
36
                         Status&= 0x3F;
37
                         Status+= 0x10;
38
                         break;
39

40
               }
41
          }
42
     } else {
43
          Status&= 0x3F;
44
     }
45
}
Angehängte Dateien:
#2741350
Lesenswert?
• ▲
▼
Michael D. schrieb:
> Leider habe ich beim Zählen (450Schritte Linkslauf) das Problem, das er
> teilweise (jedes 5-7te mal) nach geschätzt der Hälfe stehen bleibt.

Michael D. schrieb:
> Count Pulses ist eine volatile 16Bit Variable.

Das liegt daran, dass das Lesen in der Schleife nicht atomar ist. Daher 
kann beim Übergang von 256 nach 255 vorzeitig eine 0 erkannt werden.
Gast #2741353
Lesenswert?
• ▲
▼
Stefan Ernst schrieb:
> Das liegt daran, dass das Lesen in der Schleife nicht atomar ist. Daher
> kann beim Übergang von 256 nach 255 vorzeitig eine 0 erkannt werden.

Weiß zwar nicht wie das "atomar" gemeint ist, denke aber, das während 
des Lesevorganges die ISR aufgerufen wird und das Byte geändert.

Würde jetzt als Laie in der while() die Variable zwischen einem cli() 
und sei() kopieren sodass eine Kopie überprüft wird.

Oder gibt es da eine fertige Lösung?
#2741361
Lesenswert?
• ▲
▼
Michael D. schrieb:
> Weiß zwar nicht wie das "atomar" gemeint ist, denke aber, das während
> des Lesevorganges die ISR aufgerufen wird und das Byte geändert.

Es ist ja nicht nur ein Byte, sondern zwei. Und um festzustellen, ob die 
Variable 0 ist, müssen beide Bytes getestet werden. Und wenn nun genau 
zwischen diesen beiden Tests der Interrupt die Variable von 256 auf 255 
ändert, wird fälschlicherweise eine 0 erkannt.

Michael D. schrieb:
> Würde jetzt als Laie in der while() die Variable zwischen einem cli()
> und sei() kopieren sodass eine Kopie überprüft wird.

Ich würde es so machen:
1
#include <util/atomic.h>
2
...
3

4
    uint16_t tmp = 1;
5
    while (tmp) {
6
        ATOMIC_BLOCK(ATOMIC_FORCEON) {
7
            tmp = CountPulses;
8
        }    
9
    }

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.