Forum: PC-Programmierung Ansi C: state machine + at commandos


von *Ho* (Gast)


Lesenswert?

Guten Tag, für eine spezielle Anwendung bräuchte ich Hilfe.
Ich bin gerade dabei ein kleines Tool zu schreiben mit dem ich AT 
Kommandos via UART absetzen möchte. Die Gegenstelle anwortet dann mit 
einem String.
Nun ist es so das ich mehrere AT Kommandos per Uart versenden möchte.
Dies soll in einer State Machine realisiert werden. In einem UART 
Callback wird dann der empfangene String von der Gegenstelle 
ausgewertet.
Ich weiß nicht wie ich dies richtig realisieren kann.
1
void Uart Callback(...)
2
{
3
  ==> check receive message, start other state
4
}
5
6
int main()
7
{
8
9
   while(1)
10
   {
11
     stateMachine();
12
   }
13
}
14
15
void stateMachine()
16
{
17
    switch (state)
18
    {
19
    case AT_COMMAND1:
20
        ==> send at command1 via uart
21
22
        break;
23
24
    case AT_COMMAND2:
25
        ==> send at command2 via uart
26
        
27
        break;
28
29
    }
30
}

von DerEgon (Gast)


Lesenswert?

*Ho* schrieb:
> Nun ist es so das ich mehrere AT Kommandos per Uart versenden möchte.
> Dies soll in einer State Machine realisiert werden.

"Du möchtest" ... und "das soll".

Was jetzt? Und vor allem: Warum? Warum hast Du Dich für eine 
Statemachine entschieden?

von Stephan (Gast)


Lesenswert?

>spezielle Anwendung
Eine Hausaufgabe?

von *Ho* (Gast)


Lesenswert?

Warum eine Statemachine?
Das war sozusagen mein erster Gedanke soweis ordentlich sequenzell zu 
machen

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Muss es ANSI-C (C89) sein? Aktuelle C-Standards sind viel komfortabler 
und werden von fast allen Compilern unterstützt. ANSI-C ist 33 Jahre 
alt...

von *Ho* (Gast)


Lesenswert?

Welche Standard ist mir jetzt echt egal.

Das mit der Uart Callback und der statemachine läuft bei mir nicht 
richtig.
Irgendwas habe ich übersehen.
Die Statemachine soll dann erst weiterlaufen sobald der string korrekt 
empfangen wurde.

Beitrag #7098108 wurde vom Autor gelöscht.
von Wilhelm M. (wimalopaan)


Lesenswert?

Das mit der SM ist schon genau richtig. Du wirst sogar zwei brauchen, 
denn in Deinem UartCallback wird auch eine laufen, die die empfangenen 
Zeichen parsed, und damit die Antwort auswertet.

Der Ablauf ist ja etwa

1) Senden Cmd1
2) Warten auf OK/NOK (ggf. mit Ergebnis)
3) Sendem Cmd2
4) Waretn auf OK/NOK (ggf. mit Ergebnis)
...

D.h. Du musst zusätzliche Wartezustände einbauen. Der Übergang von einem 
Wartezustand zu nä. Zustand wird dadurch ausgelöst, dass die andere SM 
im UartCallback eine Antwort erkannt hat und damit einen Event sendet.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

*Ho* schrieb:
> Warum eine Statemachine?
> Das war sozusagen mein erster Gedanke soweis ordentlich sequenzell zu
> machen

Eine state machine ist sinnvoll, wenn sie Ereignisse und states 
verknüpft:

Für jeden state gibt es eine Prozedur, die auf das Ereignis (z.B. 
Zeichen empfangen) reagiert und dann einen neuen state setzt. Das ist 
bei dir aber nicht der Fall, du reagierst NUR auf states. Das ist 
überhaupt keine state machine. Ausserdem sendet deine Prozedur immer 
wieder das AT Kommando.

Normal wäre es wenn die state machine nach dem Absenden des Kommandos 
selbst den state zurücksetzen würde auf "empfangsbereit". Und in diesem 
state wartet die Prozedur auf eingehende messages.

Das vorgestellte Programm hat nur eine sehr entfernte Ähnlichkeit mit 
einer state machine.

Georg

von Nanana (Gast)


Lesenswert?

Niklas G. schrieb:
> Muss es ANSI-C (C89) sein? Aktuelle C-Standards sind viel
> komfortabler und werden von fast allen Compilern unterstützt. ANSI-C ist
> 33 Jahre alt...

Msvc... Hust hust

von db8fs (Gast)


Lesenswert?

Mal doch erstmal ein Diagramm, einmal was der Sender in welchem Zustand 
senden soll und einmal eins, welche Nachrichten der Empfänger überhaupt 
empfangen darf.

Der Einfachheit halber nimmste für den Sender halt an, dass beim 
Betreten eines Zustands irgendwas gesendet wird. Beim Empfänger dann 
erfolgt die Transition unter der Bedingung, das eine bestimmte Sequenz 
empfangen wird.

https://de.wikipedia.org/wiki/Zustandsdiagramm_(UML)

Soll heißen: was soll der sender machen, was der empfänger.

von Rolf M. (rmagnus)


Lesenswert?

Nanana schrieb:
> Msvc... Hust hust

Ist der nicht inzwischen auch "schon" bei C99 angekommen?

von Mox (Gast)


Lesenswert?


von Alex (Gast)


Lesenswert?

Moin,

Gibt hier doch einen super Artikel wie das geht:
https://www.mikrocontroller.net/articles/Statemachine

schönen Gruß,
Alex

von Wilhelm M. (wimalopaan)


Lesenswert?

Alex schrieb:
> Moin,
>
> Gibt hier doch einen super Artikel wie das geht:
> https://www.mikrocontroller.net/articles/Statemachine

Naja, der Artikel ist ganz gut, aber bei der softwaretechnischen 
Umsetzung leider etwas schwach in einigen Dingen.

Wer wirklich effektive FSMs in C++ machen will, sollte

https://github.com/boost-ext/sml

benutzen.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Wilhelm M. schrieb:
> Wer wirklich effektive FSMs in C++ machen will,

Ich bin großer Fan des State Pattern weil es einfach und Flexibel ist. 
Man braucht im Prinzip nichtmal eine Library dafür, man kann das mit 
einer Union oder std::variant umsetzen.

Ich habe mal eine Mini-Library geschrieben die ein bisschen die 
Schreibarbeit reduziert:

https://github.com/Erlkoenig90/OverlayFSM

Bin aber leider bisher nicht dazu gekommen sie zu dokumentieren...

von Rolf M. (rmagnus)


Lesenswert?

Wilhelm M. schrieb:
> Wer wirklich effektive FSMs in C++ machen will, sollte
>
> https://github.com/boost-ext/sml
>
> benutzen.

Hat allerdings wieder das gleiche Problem, das man in boost sehr oft 
findet - die ausufernde Operator-Abuse:
1
  return make_transition_table(
2
      *"established"_s + event<release>          / send_fin  = "fin wait 1"_s,
3
       "fin wait 1"_s  + event<ack> [ is_valid ]             = "fin wait 2"_s,
4
       "fin wait 2"_s  + event<fin> [ is_valid ] / send_ack  = "timed wait"_s,
5
       "timed wait"_s  + event<timeout>                      = X
6
  );

von A. S. (Gast)


Lesenswert?

*Ho* schrieb:
> Welche Standard ist mir jetzt echt egal.
> Das mit der Uart Callback und der statemachine läuft bei mir nicht
> richtig

Statemachine ist sehr allgemein.

Zum einen gibt es verschiedenste Ausführungen, zum anderen verschiedene 
Teilaspekte, für die Du welche verwenden kannst.

Man kann dann vollkommen aneinander vorbeireden.

Daher: nutzt Du sie blockierend (Anfänger, simpel, mit delays) oder wie 
SPS?

Welche SMs, wo?
 * Im Interrupt (Dekodierung der RX-Zeichen)?
 * In Loop
 * Beim kodieren des Telegramms?
 * Beim Senden (falls keine Tel-Puffer)

Wie koppelst Du Receive und statemachine? Über Flags? Über je einen 
state, in dem Du auf Antwort wartest?

Hast Du (brotlose) Timer für die Zeitüberwachung und Wiederholung?

Oftmals muss man die statemachine im Empfang "doppelt" nachbilden oder 
umgekehrt. Wwie man ein if verdoppeln muss, wenn man 2 unabhängige 
Bedingungen hat. Entweder reagiert man an 2 Stellen (States) auf 
"Telegramm 35" oder man wertet beim Empfang des Tel aus, ob der state 
gerade "hü" oder "hot" ist.

Jeder hat bei solchen Diskussionen "seinen" Favoriten um Kopf.

Daher bitte kurz Deine Struktur, Dein Timing, Deine Interaktion von SM 
und Receive, ob blockierend,

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.