Forum: Mikrocontroller und Digitale Elektronik Möglichkeiten um Sequenzabarbeitung zu erhöhen


von Sebastian B. (mircobolle)


Lesenswert?

Hallo,

folgende Sache:

Mein System arbeitet eine im EEPROM gespeicherte Sequenz ab.

Ein Sequenz Schritt sieht z.b. so aus:

<ID>  <u16_value>
3     3218
"gebe an da ausgang 1 (id:3) den wert 3.218 V (3218) aus"

nun besteht die sequenz-abarbeitung aus folgenden schritten:

0. Display Anzeige initialisieren

1. Display partiell aktualisieren (aktueller schritt)
2. Schritt aus EEPROM laden
3. schritt ausführen

weiter mit 1 bis letzter schritt erreicht.

Eigentlich recht simpel. Das Problem ist allerdings die Geschwindigkeit!
Die Display-Aktualisierung dauert ca. 2 ms (!) weil der schritt in einen 
string umgerechnet werden muss!

Zur Verbesserung aktualisiere ich die Anzeige nur alle 10 schritte.
ein anderes problem ist das deterministische verhalten.

Der ganze "prozess" laueft in einer state-machine wobei jeder schritt 
ein zeitfenster von 2 ms hat.

jede optimierung die also nur alle 10 oder 100 schritte passieren kann 
ist für das deterministische verhalten wiederum schlecht.

Das Problem ist also determinismus gegenüber performance...

natürlich ist der golgende mittel-weg der richtige, aber der ist zu 
langsam ;-)

ein Ansatz:
eeprom schritte blockweise lesen, dann würde aber in der sequenz immer 
ein punkt erreicht werden, der länger braucht als die anderen...?

Habt ihr da eine Idee wie man das ganze elegant optimieren könnte??

Vielen Dank für die Tipps!

MFG
(und schönen Feierabend ;-) )

von 11833 (Gast)


Lesenswert?

wenn du es mit einem microcontroller machst, implementiere deine 
statemachine in einer timer-interrupt routine, die in regelmäßigen 
abständen aufgerufen wird.
das display-update machst du im main-loop.
dann wird das display-update durch den timer-interrupt unterbrochen, und 
die abarbeitung deiner "eigentlichen" aufgabe ist garantiert.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

>Der ganze "prozess" laueft in einer state-machine wobei jeder schritt
>ein zeitfenster von 2 ms hat.
So schnell kannst du gar nicht schauen. Also ist so schnelles Updaten 
der Anzeige gar nicht nötig.

Du hast noch den falschen Programmierstil.
Ändere den mal (wie bereits vorgeschlagen):
Die nebenläufigen Tätigkeiten (also das Userinterface) laufen in der 
Main-Loop. Zeitkritische Aufgaben, also deine Hauptarbeit (Schritt 2 und 
3) musst du zügig und zeitgenau ausführen --> Interrupt. Ob die Anzeige, 
die in der Main-Loop aktualisiert wird, da 100ms hinterherhinkt, ist 
absolut uninteressant.

von Matthias L. (Gast)


Lesenswert?

Ja. Du brauchst eine zweite Schrittkette für das Display. Und eine 
übergebende Funktion.

Dein Schritt 1 ist nur ein Funktionsaufruf, zb so:
1
func_Display ( neuer anzuzeigender Wert)
Dieser Aufruf dauert nur kurz, denn diese Funktion schreibt die Werte 
nur in irgendeinen (µC internen FIFO-Puffer)

Die Abarbeitung erfolgt dann mittels der zweiten Schrittkette:

0) Init                   |
                         \|/  Init fertig
1) warten                     |
                             \|/ ist was im FIFO drin
2) schreiben in Display    |
                          \|/ DIsplay fertig geschrieben
                       zurück zu 1)

So löse ich alles, was zulange dauert. Das nenne ich dann einen Handler.

von jl (Gast)


Lesenswert?

2ms für eine Stringumwandlung finde ich arg lang.

Schau dir mal die Funktion an, oder schreibe sie selber.
Gerade bei sprintf(...) ist ein riesen overhead drin für alle möglichen 
Parameter. Da ist es oft einfacher selber eine schnelle inttostr zu 
schreiben und eventuelle Texte anzufügen.


JL

von Sebastian B. (mircobolle)


Lesenswert?

hi!

Danke für eure Antworten.

diese sequenz-abarbeitung habe ich in einer art "task"

alle meine "tasks" laufen in der rtc interrupt routine, die mit 1 ms 
getriggert ist. Leider habe ich somit auch keine Prioritäten, auch 
werden die Prozesse untereinander nicht unterbrochen.

aber ihr habt mich auf die idee gebracht.. "langsame" tasks wie die 
display-aktualisierung in die main auszulagern.

diese möglichkeit hatte ich noch nicht bedacht.

Ich habe ein modul das nennt sich "system-manager" der schaltet "taks" 
je nach System-Zustand zu oder weg.

Das Laden von EEPROM Blöcken habe ich mir gedacht könnte ich asynchron 
zu meinem Task machen.

Auftrag ans EEPROM Modul übergeben, dieser läuft getriggert durch den 
I²C Interrupt. Somit wär das auch entkoppelt.

danke schon mal für die tipps, werde mir das morgen genauer anschauen!

bis denn!

von Sebastian B. (mircobolle)


Lesenswert?

So ich habe jetzt noch etwas über die ganze Sache nachgedacht..

auf der einen seite will ich ein paar Prozesse "managen" aber auf der 
anderen seite ein determinstisches verhalten garantieren.

Meine momentane Sequenz-Abarbeitung läuft schon sehr deterministisch, 
jeder schritt läuft mit genau 10 ms.

ich denke mal ein Echtzeit Betriebssystem in C zu implementieren ist gar 
nicht so ohne.

Aber eine grundsätzliche Frage hätte ich dazu:

Zuerst brauch ich eine Task Status Definition:

tyedef enum

Ich lege mir z.b. eine Struktur an

typdef enum os_state_etag{
   idle   = 0,
   run    = 1,
   wait   = 2
} os_state_e;

typedef struct os_task_stag{
   u8         u8_priority;
   u8         u8_exec_counter;
   void       (*func_pointer) (void);
   os_state_e e_state;

} os_task_s;

das ganze kommt dann in ein arry mit 10 "Task"

os_task_s[10];

wenn nun mein RTC ISR kommt könnte ich
den Task mit der höchsten Priorität und dem Zustand "wait" suchen
und diesen aufrufen

{
...

( * os_taks_s[TASK_9].func_pointer ) ();

...
}


Jetzt eure Meinung:
- So ein Suchen in einer Interrupt Routine, ist sowas aufwendig, oder 
erzeugt es soviel overhead dass das ganze eigentlich keinen Mehrwert 
mehr hat.

es könnten dann aufruge verhungern...
ausserdem ist das ganze ja dann nicht mehr besonders "echtzeitfähig"... 
ausser eben diese Taks die hoch-prior sind ;-)

naja, war nur mal so ne Idee.. ich denke nciht, dass ich es umsetzen 
werden.. aktuell läuft es ja, nur noch nicht schnell genug :-)

thx

von Na sowas (Gast)


Lesenswert?

Nur an einem umpassenden System kleben zu bleiben weil es nichts taugt 
ist etwas mager. Wenn etwas nicht passt muss man es auch hiterfragen. 
Einen Schritt der nur 10ms dauert muss man nicht anzeigen, den sieht man 
eh nicht. Allenfalls muss man debugmode/Einzelschritt und normalen Mode 
unterscheiden. Wenn ich anzeigen will, dass etwas geht, kann ich auch 
alle alle 100ms eine Zahl incrementieren. Ober eine einzelnen Punkt 
anzeigen.

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.