Forum: Compiler & IDEs Bedingung wird manchmal nicht wahr


von ichmalwieder (Gast)


Lesenswert?

hallo, ich hoffe ihr könnt mir helfen.. :-)

ein tiny 13 mit 9.6 MHz steuert einen Schrittmotor an, dieser soll 
zwischen zwei positionen hin- und herfahren. das klappt soweit, 
allerdings: den richtungswechsel macht er 3 mal, das vierte mal erkennt 
er nicht und läuft immer weiter. warum?

1
volatile uint8_t dir=0, speed = 128;
2
volatile uint16_t position = 32000, stop_l=31000, stop_r=33000;
3
4
5
ISR(TIM0_COMPA_vect)
6
{
7
  const uint8_t steps[4] = {STEP_PATTERN};
8
  static uint8_t step;                                
9
  OCR0A = TCNT0 + speed;                              
10
  
11
  if(dir)
12
  {
13
    if (step < 3)
14
      step++;
15
    else 
16
      step=0;
17
      
18
    position++;
19
  }
20
  else
21
  {
22
    if (step > 0)
23
      step--;
24
    else 
25
      step = 3;
26
      
27
    position--;
28
  }
29
30
  STEPPER_PORT = (STEPPER_PORT & ~STEP_MASK) | steps[step];  
31
  
32
}

es gibt ausserdem den overflow interrupt, in dem aber nichts mit diesen 
variablen geschieht. der timer läuft mit prescaler 256

in der main ist folgendes:
1
while(1)
2
  { 
3
    sleep_mode();
4
    
5
    if(switch_closed(1<<KEY))
6
    {
7
      dir = !dir;
8
    }
9
    
10
    cli();
11
    if(position == stop_l || position == stop_r)
12
    {
13
      dir = !dir;
14
    }
15
    sei(); 
16
    
17
    
18
    
19
  }

es macht keinen unterschied, ob hier die interrupts ausgeschaltet 
werden.
manuelle richtungswechsel werden immer erkannt.

mit stop_r=32999 erkennt er schon den zweiten wechsel nicht.

ich verstehe nicht, wieso diese überprüfung fehlschlägt :-(

von ichmalwieder (Gast)


Lesenswert?

wenn ich die bedingung auf

if(position <= stop_l || position >= stop_r)

ändere, funktioniert es natürlich. das heisst, der moment, in dem die 
bedingung war erkannt würde kommt nicht, weil die prüfung davor und 
danach stattfindet.

ahh, vielleicht in dem fall, dass der overflow-interrupt den sleep-mode 
beendet, die überprüfung stattfindet, und der schrittmotor-interrupt 
dann zweimal hintereinander auftritt. schon wird der entscheidende punkt 
überschritten.

das ist ja fies!

von Johannes M. (johnny-m)


Lesenswert?

Ich überschaue jetzt grad auf die Schnelle nicht, was da alles 
schieflaufen kann, aber die Abfrage für den Drehrichtungswechsel würde 
ich allein aus Sicherheitsgründen eher so schreiben:
1
if(position <= stop_l || position >= stop_r)
2
    {
3
      dir = !dir;
4
    }
Abfragen auf exakte Gleichheit sind meist etwas riskant...

Was ist das mit dem "switch_closed"?

von Johannes M. (johnny-m)


Lesenswert?

Och, kuck mal da...

von ichmalwieder (Gast)


Lesenswert?

Hi Johannes,

danke für deinen Beitrag. Allerdings sollte es schon schrittgenau sein.. 
muss dann eben mit in die ISR.

Das switch_closed() ist aus den Entprellroutinen von P. Dannegger

von Daniel Held (Gast)


Lesenswert?

Wahrscheinlich funkt ein Interrupt dazwischen.
Bei dem Entprellen der Tasten werden außerdem die Interrupts 
deaktiviert.. und wenns dann mal zusammentrifft is Schluß.

von ichmalwieder (Gast)


Lesenswert?

Hi Daniel, die Ursache für das Problem habe ich schon gefunden, steht 
weiter oben.. Trotzdem danke für Deinen Hinweis!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.