Code wird nicht Richtig ausgeführt

OP #6186702
Lesenswert?

Hallo,

wie dem Betreff schon zu entnehmen ist habe ich ein Problem beim 
ausführen meines Programmcodes aber hier erstmal ein paar Daten worum es 
sich handelt.

Mikrocontroller: Atmega328PB
Programmieradapter: AVR-Dragon
Programmierumgebung: Atmel Studio 7

Beim Programmcode handelt sich es um eine Statemachine die durch ein 
Flag welches in der Mainloop geprüft wird ob es gesetzt ist aufgerufen 
wird. Das Flag wird in einem Timerinterrupt alle 50ms gesetzt. 
Angestoßen wird das ganze dadurch das die Variable "State" auf 
"Ausfahren" gesetzt wird. Nachdem alles im case Ausfahren abgearbeitet 
ist sollte es beim nächsten mal wenn die Statemachine aufgerufen wird in 
den Ausgefahren case springen was aber nicht passiert. Um der ganzen 
Sache auf den Grund zu gehen habe ich angefangen das ganze zu Debuggen. 
Beim Debuggen habe ich festgestellt dass wenn ich einen Breakpoint im 
Ausfahren case erstelle das Programm beim nächsten mal aufrufen der 
Statemachine in den Ausgefahren case springt. Ohne Breakpoint wird der 
Programmcode dann wieder nicht richtig ausgeführt egal ob im Debugmodus 
oder normal Programmiert. Woran könnte das liegen ?

Mit freundlichen Grüßen.
Lukas W.
1
switch(State)
2
{
3
  case Warten:
4
  break;
5
        
6
  case Ausfahren:
7
    motor_up();
8
    State = Ausgefahren;
9
  break;
10
        
11
  case Ausgefahren:
12
    if(getHall_up())
13
    {
14
      motor_stop();
15
      State = Warten;
16
    }
17
  break;
18
}
Gast #6186713
Lesenswert?

Lukas W. schrieb:
> Ohne Breakpoint wird der
> Programmcode dann wieder nicht richtig ausgeführt egal ob im Debugmodus
> oder normal Programmiert. Woran könnte das liegen ?

"Wilde Sprünge" deuten erst mal auf einen vom Compiler optimierten
Code hin den man grundsätzlich nicht richtig debuggen kann.

YMMV

Auch in der Make-Version "Debug" kann der Compiler zum Optimieren
aufgerufen worden sein. Prüfe daher erst ob dein Build ohne
Compiler-Optimierung eingestellt wurde.
Gast #6187043
Lesenswert?

Lukas W. schrieb:

> Ohne Breakpoint wird der Programmcode dann wieder
> nicht richtig ausgeführt egal ob im Debugmodus
> oder normal Programmiert. Woran könnte das liegen ?

Daran, dass Dein (Denk-)Modell nicht stimmt.

Die Zustände der Mechanik und die Zustände des steuernden
Automaten sind erstmal nicht identisch: Wenn die Mechanik
betriebsmäßig ZWEI Zustände kennt, z.B. "Eingefahren" und
"Ausgefahren", muss der steuernde Automat VIER Zustände
kennen: "Eingefahren", "Ausfahren", "Ausgefahren" und
"Einfahren". Das liegt einfach daran, dass der steuernde
Automat wesentlich schneller ist als die gesteuerte
Mechanik, so dass "Übergänge" der Mechanik in "Zustände"
des steuernden Automaten abgebildet werden müssen.


Die nächste Falle lauert schon: Mit vier Endlagenschaltern
können zwar vier verschiedene Zustände codiert werden --
von diesen sind aber nur drei betriebsmäßig zulässig:
- "00" = "Aktor in Bewegung",
- "10" = "vordere Endlage",
- "01" = "hintere Endlage",
- "11" = unzulässig (--> Fehler).

Man braucht also zur korrekten Behandlung erstens einen
Timeout und muss zweitens die Vorgeschichte berücksichtigen,
um softwaremäßig "Einfahren" und "Ausfahren" unterscheiden
zu können.

Ungefähr darauf wollte Dirk wohl mit seiner kurzen Frage
hinweisen, nehme ich an.
Beitrag #6187056 wurde von einem Moderator gelöscht.
OP #6187233
Lesenswert?

Danke für die Antworten. Die Statemachine war schonmal weiter ausgebaut 
ich wollte die Statemachine zum finden des Fehlers nur so klein wie 
möglich halten damit das ganze übersichtlicher ist und es selbst so 
schon nicht funktioniert. Der Motor braucht länger als 50ms zum 
Ausfahren bzw bis er den Hallsensor erreicht, was kein Problem 
darstellen sollte da die Statemachine solange immer wieder in den 
Ausgefahren case springen sollte und prüfen sollte ob der Motor am 
Hallsensor angekommen ist. Der Motor ist auch nicht schnell genug um dem 
Hallsensor in 50ms überfahren zu können. Hier nochmal etwas mehr code 
ich hoffe das macht das ganze verständlicher. resetSerCommand() am ende 
setzt das Serielle Komando zurück was verhindert das befehle doppelt 
ausgeführt werden.
1
enum States
2
{
3
  Warten = 0,
4
  Ausfahren,
5
  Ausgefahren,
6
  Einfahren,
7
  Eingefahren,
8
};
9

10
volatile int State = 0;
11

12
int main(void)
13
{
14
  init_all();
15
  FILE str_uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
16
  stdout = &str_uart;
17
    while (1) 
18
    {
19
    if(getTimeSliceFlag() == 1)
20
    {
21
      resetTimeSliceFlag();
22
      switch(getSerCommand())
23
      {
24
        case 1:        //ausfahren
25
          State = Ausfahren;
26
        break;
27
        
28
        case 2:        //einfahren
29
          motor_down();
30
        break;
31
        
32
        case 3:        //Motor halt
33
          motor_stop();
34
        break;
35
        
36
        case 4:        //Hallschalter auslesen
37
          if(getHall_up() == 1)
38
          {
39
            printf("oberer Hallschalter\r\n");
40
          }
41
          
42
          if(getHall_down() == 1)
43
          {
44
            printf("unterer Hallschalter\r\n");
45
          }
46
        break;
47
        
48
      }
49
      
50
      switch(State)
51
      {
52
        case Ausfahren:
53
          motor_up();
54
          State = Ausgefahren;
55
        break;
56
        
57
        case Ausgefahren:
58
          if(getHall_up())
59
          {
60
            motor_stop();
61
            State = Warten;
62
          }
63
        break;
64
      }
65
      resetSerCommand();
66
    }
67
    }
68
}
#6187279
Lesenswert?

Lukas W. schrieb:
> if(getTimeSliceFlag() == 1)

Sicher dass das Flag auch dort wieder gelöscht wird?!

Lukas W. schrieb:
> resetSerCommand() am ende
> setzt das Serielle Komando zurück was verhindert das befehle doppelt
> ausgeführt werden.

Das ist Mist (die wahrscheinliche Fehlerquelle). Bau das in die 
Statemachine ein! (Setzt das doch sicher eh nur auf "case 4:"!?


So wie ich das sehe, sollte das zweite Switch außerhalb der If Bedingung 
liegen. Also ständig ausgeführt werden....
Bzw. ich würde die Main, also die Switch Blöcke ungebremst laufen lassen 
und nur die Sensor/etc.-Abfrage, in den 50ms Task-Slot (IF-Block 
außerhalb der Switches) legen.
OP #6187287
Lesenswert?

Dirk B. schrieb:
> Die ISR spielt doch auch an State rum.
> Die solltest du also auch zeigen.
1
void resetTimeSliceFlag(void)
2
{
3
  TimeSliceFlag = 0;
4
}
5

6
int getTimeSliceFlag(void)
7
{
8
  return TimeSliceFlag;
9
}
10

11
ISR(TIMER0_COMPA_vect)
12
{
13
  static int counter = 0;
14
  if(counter == 50)
15
  {
16
    TimeSliceFlag = 1;
17
    counter = 0;
18
  }
19
  else
20
  {
21
    counter++;
22
  }
23
}
OP #6187304
Lesenswert?

Teo D. schrieb:
> Lukas W. schrieb:
>> if(getTimeSliceFlag() == 1)
>
> Sicher dass das Flag auch dort wieder gelöscht wird?!

Zwei zeilen darunter wird es gelöscht. Das Timing habe ich mit einem 
Oszi gemessen indem ich einen Ausgang toggeln lassen habe.

> Das ist Mist (die wahrscheinliche Fehlerquelle). Bau das in die
> Statemachine ein! (Setzt das doch sicher eh nur auf "case 4:"!?
Was soll case 4: mit meinem Problem zutun haben case 4: wird nur 
aufgerufen wenn ich befehl 4 per seriellen Komando ausführen will
#6187327
Lesenswert?

Lukas W. schrieb:
>> Das ist Mist (die wahrscheinliche Fehlerquelle). Bau das in die
>> Statemachine ein! (Setzt das doch sicher eh nur auf "case 4:"!?
> Was soll case 4: mit meinem Problem zutun haben case 4: wird nur
> aufgerufen wenn ich befehl 4 per seriellen Komando ausführen will

Lukas W. schrieb:
> resetSerCommand() am ende
> setzt das Serielle Komando zurück was verhindert das befehle doppelt
> ausgeführt werden.

Wie funst das den dann, bzw. was wird den anstelle ausgefürt?
OP #6187369
Lesenswert?

Ich schicke den Befehl 3 (case 3: des ersten Switch) per serielle 
Schnittstelle was soweit funktionert. In dem case 3 des ersten Switch 
wird der State der Statemachine gleich Ausfahren gesetzt was den Motor 
Startet und den State auf Ausgefahren setzt. Der Motor dreht sich aber 
die Statemachine kommt beim nächsten mal ausführen der Statemachine 
nicht in den  Ausgefahren State wo es den Motor stoppen sollte wenn er 
den Hallschalter erreicht sondern springt in den Warten state was 
eigentlich nicht passieren darf solange der Motor nicht am Hallsensor 
angekommen ist.
OP #6187597
Lesenswert?

Also nach Stundenlangen Kopfzerbrechen habe ich den Fehler jetzt 
gefunden. Der Fehler lag nicht in der Software sondern in der Hardware. 
Das Labornetzteil das ich verwende konnte den hohen Anlaufstrom des 
Motors nicht bewältigen was zur folge hatte das die Versorgungsspannung 
etwas auf der Mikrocontroller Seite zusammengebrochen ist und dieser das 
Programm dann anscheinend von neuem gestartet hat oder irgend einen 
anderen mist gemacht hat. Vielen dank an alle die versucht haben mir bei 
meinem Problem zu helfen.

Mit freundlichen Grüßen.
Lukas W.
Gast #6187819
Lesenswert?

Lukas W. schrieb:

> Also nach Stundenlangen Kopfzerbrechen habe ich den Fehler jetzt
> gefunden. Der Fehler lag nicht in der Software sondern in der Hardware.
> Das Labornetzteil das ich verwende konnte den hohen Anlaufstrom des
> Motors nicht bewältigen was zur folge hatte das die Versorgungsspannung
> etwas auf der Mikrocontroller Seite zusammengebrochen ist und dieser das
> Programm dann anscheinend von neuem gestartet hat

Selbst wenn das wirklich so gewesen wäre, hätte ein gutes Programm 
auch dann (also nach einem unerwarteten Reset mit kompletten 
Informationsverlust) noch keinen völligen Mist gemacht...

Für sowas sieht man natürlich einen initialen "Unknown"-Status vor, wenn 
es keine beschaffbare Information über eine bestehende Aktivität des 
Aktors gibt. Den braucht man sowieso, denn mindestens beim allerersten 
Start des Programms kann diese Situation eintreten, wenn der Aktor 
(warum auch immer) schon was tut.
Der Status endet, wenn entweder einer der Endlagensensoren was meldet 
oder eine Maximalzeit vergangen ist (die für den vollen Weg nötige + 
etliche % Sicherheit). Dann wechselt man entweder nach in einen der 
beiden Endlagen-Stati (wenn halt der entsprechende Sensor sich gemeldet 
hat) oder nach "kaputt". Denn das kann nur bedeuten, dass der Aktor 
einen erteilten Befehl nicht bis zum Ende ausführen konnte oder halt en 
Sensor defekt ist. In jedem Fall: kaputt.

Sprich: die hast noch viel zu lernen...

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