Bedingung wird manchmal nicht wahr

Gast #589187
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 :-(
Gast #589202
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!
#589203
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"?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren