Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen
Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.
Hinweis kann nach Kenntnisnahme deaktiviert werden!
Sehr gut, läuft die letzten Tage im ständigen Test und das zufriedenstellend. Aber, wir schweifen ab. Babette ist übrigens nicht der Grund für den Glühweinkonsum, der gehört zur Lebensfreude.
Dim Buffer As String * 255 ' gegebenenfalls Buffer anpassen
Dim A As Byte
Print "mit Komma"
Do
' Input beendet das Einlesen, wenn es auf ein CR trifft
If A < 5 Then
Input Buffer , Noecho ' Datensatz einlesen bis CR
Else
If A > 9 Then
Input Buffer Noecho
Else
Input Buffer
End If
End If
Print Str(a) + "*" + Buffer
Incr A
If A > 14 Then A = 1
nop
Loop
Alles anzeigen
und nun ist die Verwirrung komplett. Nur bei Noecho ohne Komma gibt er ein Echo heraus sonst nicht auch nicht ohne noecho.
Sollte es dann nicht besser Echo,Makeecho oder doecho heißen und nicht Noecho?
macht wohl nur Sinn, wenn man auch ein Echo senden will.
Wenn es gänzlich aus sein soll, kann man das abschalten mit:
BASCOM-Quellcode
Echo off
Ich habe noch vernommen, dass die Daten auf SD gespeichert werden sollen und möglichst wenig platz verbraucht werden soll.
Mein Tip wäre:
Keine Strings zu speichern, sondern Werte.
Für Fließkomma (Zählerstand) sollte Single reichen (verbraucht 4 Byte) und für die ZählerNr. z.B. Long (verbraucht 4 Byte).
Für den Gesamtzählerstand evtl. auch ein Double (8 Byte)
Ein Datensatz wäre dann
Zählernr: 4 Byte (Long)
Zählerstand: 8 Byte (Double)
Leistung 1 bis 3 je 4 Byte (Single)
Leistung (L1 bis L3): 4 Byte (Single)
Hier mal eine Alternative, wie die Daten per Interrupt eingelesen werden können.
Die Werte werden direkt den entsprechenden Variablen zugewiesen.
In der Hauptschleife müssen nur noch, wenn ein bestimmter Zustand erreicht ist (State=ST_END), die Daten weiter veratrbeitet werden.
Danach den State wieder auf Anfang setzen, um das nächste Datenpaket zu erhalten (State=ST_WAIT_BEGIN).
Einmalig vorne Echo Off verwenden, das Input fällt weg.
Vorteil dieser Methode:
- Wenig RAM Verbrauch im Gegensatz zur String-Buffer mit 255 Byte Länge.
- Datenpakete werden im Hintergrund empfangen
- Einfache Verarbeitung
- Übersichtlicher Code
Nachteil:
- Die ISR ist etwas aufwendiger, aber Trotzdem effektiv.
- Etwas redundanter Code in der ISR (dafür übersichtlich und nachvollziehbar)
Man könnte die Prüfung (in der ISR), ob die Klammer auf ist und das Flag setzen, auch in eine Funktion auslagern.
Ich hab mir das jetzt aber gespart.
Das ganze soll ein Lösungsansatz sein. Der Code könnte eigentlich sogar schon funktionieren, wenn ich kein Bug eingebaut habe.
Habs nicht ausprobiert.
In dem Sinne noch einen schönen Advent!
Gruß Mitch
BASCOM-Quellcode
' Ein anderer Ansatz die Daten einzulesen
' ISR verwendet eine einfache Statemachine, um in den ankommenden Daten
Ja, so wird's gemacht, eine Sache fehlt aber noch, die Stackwerte.
Sind keine im Programm angegeben, werden die aus den Optionen hinterlegten benutzt, die für serielle Sachen und Interrupts zu knapp bemessen sind.
Der M32 hat genug RAM, dass folgende Werte aureichen sollten:
$hwstack = 80
$swstack = 64
$framesize = 80 Stack-Werte richtig setzen
danke an alle fürs Feedback. Komme heute leider nicht zum testen, da der Weihnachtsmarkt nach mir ruft.
Sobald ich das getestet habe, gebe ich hier ein Rückmeldung.
Danke Micht für das Programmbeispiel der Auswertung serieller Inputs per ISR und State Machine...werde ich als Vorlage für eigene Experimente speichern. Ich verwende für solche seriellen Eingaben zwar auch isr aber die herangehensweise mit state machine ist ist für mich noch ziemlich ungewohnt. Da muss ich noch viel lernen (man ist ja schließlich nicht zu alt um Neues zu lernen). Überhaupt ist die Verwendung der state machine bei der programmierung etwas komplexerer Anwendung unerlässlich, sonst verliert man den Überblick und sucht sich einen Wolf wenn es nicht so klappt wie es soll.
State machine = Zaubertrank des Programmieres.
Danke nochmals für die Anregung.
Gruß Chris
Einen schönen 2. Advent an Alle
Ich hatte früher auch keine Ahnung von State-Maschinen.
Habe viel im Internet recherchiert, kam aber nur auf theoretische, mathematische Abhandlungen, die viel zu kompliziert waren.
So ein Beispiel ist Wikipedia.
Die kommen gleich mit UML-Diagrammen und andere Varianten samt kryprischer Mathematik.
Das habe ich nie kapiert. Ich bin Realschüler und kein Informatiker, Bachelor oder Ingenieur.
Ich suchte lange und irgendwann hats dann mal bei mir geklickt.
Verwirrend ist, dass mal von FSM (engl. Finite State Machine) und mal vom Zustandsautomat (endlicher Zustandsautomat) gesprochen wurde.
Im Grunde ist es aber simpel.
Eine Statemachine ist charakterisiert sich durch eine Variable, die einen Zustand (engl. State) repräsentiert.
Dann wird Code abhängig von dem Zustand ausgeführt.
Das erreicht man in Bascom besonders einfach durch eine solche Struktur:
BASCOM-Quellcode
Dim State asByte ' Zustand
Do
SelectCase State
Case Zustand1
Case Zustand2
Case Zustand3
...
EndSelect
Loop
Es ist empfohlen Zustände (States) durch Konstanten zu definieren. So kann man die Zustände erweitern, ohne in der Struktur die Case xx Werte zu ändern.
Das sieht dann etwa so aus:
BASCOM-Quellcode
Dim State asByte ' Zustand
Const Zustand1 =0 ' vernünftige Bezeichnungen verwenden, die nachvollziehbar sind!
Const Zustand2 =1
Const Zustand3 =2
Do
SelectCase State
Case Zustand1
Case Zustand2
Case Zustand3
...
EndSelect
Loop
Alles anzeigen
Diese Struktur kann im einfachsten Fall in der Hauptschleife eingebaut werden.
Ein Zustand bezieht sich ja immer irgendwie auf ein Objekt. Im obigen Beispiel z.B. auf den Datemempfang von Uart0.
Angenommen, von einen weiteren Port müssten Daten Empfangen werden, dann können da andere Zustände herrschen.
Dann kann man 2 State-Maschinen oder auch mehrere parallel laufen lassen.
Dazu lagert man die State-Verarbeitungs-Routinen in Subs aus. Je Sub eine Select Case Struktur.
So können mehrere parallele Objekte verarbeitet werden.
BASCOM-Quellcode
Dim State1 asByte ' Zustände des Automaten 1
Const Zustand1 =0 ' vernünftige Bezeichnungen verwenden, die nachvollziehbar sind!
Const Zustand2 =1
Const Zustand3 =2
Dim State2 asByte ' Zustände des Automaten 2
Const Zustand1 =0 ' vernünftige Bezeichnungen verwenden, die nachvollziehbar sind!
Const Zustand2 =1
Const Zustand3 =2
Do
Call Automat1() ' Quasi parallelle Abarbeitung zweier Objekte
Call Automat2()
Loop
Sub Automat1()
SelectCase State
Case Zustand1
Case Zustand2
Case Zustand3
...
EndSelect
EndSub
Sub Automat2()
SelectCase State
Case Zustand1
Case Zustand2
Case Zustand3
...
EndSelect
EndSub
Alles anzeigen
Ich will hier keine Abhandlung oder ein Tutorial über Statemachines verfassen, aber was vielleicht noch wichtig ist:
Was sind States (Zustände) und wie legt man die Fest?
Hier redefiniert sich das Internet auch immer wieder neu.
Einfach gesagt ist ein State, ein Zustand, in dem sich der Automat länger (relativ zu sehen) befindet.
Ein Zustand ändert sich bei bestimmten Ereignissen.
Man denke da an einen Getränkeautomat. Was macht der?
Er wartet, bis Geld eingeworfen wird. Das ist ein Zustand, der länger dauert. Ein Ereignis wäre dann, wenn man eine Münze einwirft.
Dann prüft der Automat, ob genug Gelt für eine Getränkeauswahl eingeworfen wurde.
Ist dies nicht der Fall, verbleibt der Automat im Zustand, in dem auf Geld gewartet wird.
Ist das der Fall, geht der Automat in den Zustand Getränkeauswahl über.
Mögliche Ereignisse sind nun die Tasten, die das gewünschte Getränk repräsentieren oder die Abbruchtaste.
Und so geht das immer weiter.
Jeder Zustand ist für eine relative Dauer aktiv. Der Zustand ändert sich in der Regel durch Ereignisse, die auch Timeouts sein können.
Dann wechselt der Automat in einen anderen Zustand. Das geht endlos so weiter.
Da man in der Regel eine begrenzte Anzahl an States verwendet, nennt man das Endlicher Automat. Oder englisch Finite Statemachine (abgekürzt FSM).
Was noch kurz wichtig ist.
Wenn man in einen Zustand ganz frisch rein kommt, nennt man das Entry. Oder auch Einsprung. Es macht oft Sinn, dann eine einmalige Aktion auszulösen. Eben nur, wenn man ganz neu in den Zustand wechselt. Das nennt man dann Entry-Bedingung. Danneben muss es auch Code in den States geben, die ein Wechsel des Zustands bewirken. Diese sind die Events und nennt man Exit-Bedingungen.
Das ist Codetechnisch auch recht simpel:
BASCOM-Quellcode
SelectCase State
Case Zustand1
' Entry-Bedingung
If ZustandNeu =1then
' Code, der einmal ausgeführt werden soll
ZustandNeu =0
EndIf
' Hier Code, der immer ausgeführt werden soll
...
' Exit-Bedingung(en)
If Bedingung then
State = Zustand2 ' Zustandswechsel
ZustandNeu =1 ' Sicherstellen, dass Entry-Bedingung ausgeführt wird
EndIf
Case Zustand2
' Entry-Bedingung
If ZustandNeu =1then
' Code, der einmal ausgeführt werden soll
ZustandNeu =0
EndIf
' Hier Code, der immer ausgeführt werden soll
...
' Exit-Bedingung(en)
If Bedingung=True then
State = Zustand1 ' Zustandswechsel
ZustandNeu =1 ' Sicherstellen, dass Entry-Bedingung ausgeführt wird
EndIf
EndSelect
Alles anzeigen
Ich benutze dieses System mit wachsender Begeisterung. Ist einfach zu implementieren und wirkungsvoll.
Ich habe hierzu allerdings eine kleine Include-Datei geschrieben,
die mir die Arbeit mit den Flags setzen und löschen erleichtert.
So gibts in der Include-Datei im wesentlichen folgende Routinen
SetState(nächster State as Byte) ' Setzt den nächsten State und Flag ZustandNeu
GetState() as Byte ' gibt den aktuellen State zurück (für Select Case GetState() )
IsStateChanged() as Byte ' Abfrage Entry-Bedingung, ob der Code ausgeführt werden soll
Mit diesen einfachen Routinen kommt man schon recht weit.