Hallo!!
Ich befürchte das wird mal wieder so ein Posting, welches
keiner liest, weil es viel zu umfangreich und lang ist :-).
Aber es gab ja trotzdem auch oft schon sehr interessantes
Feedback!
Seit einigen Jahren bereits bastel ich nun im Hobbybereich mit
Microcontrollern auch in Zusammenhang mit C als Programmiersprache.
Mangels theoretischer Basis war mein Vorgehen dabei meist
recht blauäugig. Sicher macht man sich anfänglich ein paar
Gedanken, wie man ein Stück Software strukturieren könnte.
Aber im wesentlichen hacke ich dann doch eher drauf los.
Dabei vergisst man die Hälfte, pfriemelt es dann zwar noch irgendwie
mit rein, aber schön wird das meistens nicht. Die Struktur ist
dahin, die Übersicht auch und selbst nur mittelmässig komplexe
Projekte will man nach einem Jahr eigentlich nicht mehr
anfassen, weil es keinen Spass macht in dem Codewust noch
zu arbeiten.
Sicher, man kommentiert ja brav, aber das Big-Picture fehlt
trotzdem oft und bis man sich das aus den Kommentaren wieder
erarbeitet hat....
Stichwort: Softwaredesign
Das eine oder andere UML Diagramm hat man ja schon gesehen.
Nun kommt UML meinem Verständnis nach vor allem aus der OO
Welt. Mangels Verwendung objektorientierter Sprachen habe ich
dem bislang nicht viel Beachtung geschenkt.
Trotzdem muss es doch auch in funktionalen Sprachen (nennt man
das dann so? Was genau ist eigentlich eine funktionale Sprache?)
formale Methoden geben, um Modelle für das Verhalten von
Software zu entwickeln und zu visualisieren.
Aus der Assemblerzeit kennt man die Flowcharts. Das ist ja nun
etwas, was sehr nahe am Code ist. Also auch sehr nahe an der
Implementierung. Ich denke, dass man das da auch bewusst will.
Bei der Objektorientierung könnte ich mir das in gewisser Weise
ähnlich vorstellen, wenn man eine objektorientierte Sprache
verwendet, die Ausdrucksmittel anbietet, um z.B. Elemente der
UML sehr leicht umzusetzen.
Bei der reinen C Programmierung sind mir entsprechende Verfahren
zur Modellierung irgendwie nicht wirklich geläufig.
Ok, da gibts da noch die Nassi-Shneiderman Diagramme. In der Literatur
findet man gelegentlich den Hinweis dieser Diagrammtyp hätte im Rahmen
der Verwendung von strukurierten Programmiersprachen (C) die
Flowcharts aus der Assemblerzeit abgelöst.
Mir scheint aber eher so, als hätte dieser Diagrammtyp eher
theoretische Bedeutung. Meine Versuche damit etwas sinnvolles
anzufangen waren bisher auch mehr erfolglos.
Vielleicht liegt das aber auch am besonderen Charakter den
(zumindest meine) Microcontrollerprojekte meistens haben.
Hier z.B. eine "black-box", die eigentlich nichts anderes macht
als auf 4 Eingänge zu reagieren und ein paar Ausgänge zu steuern.
Ok, ist noch bischen PWM dabei, Interrupts usw. usw...
Aber vor allem handelt es sich nicht einfach um eine kombinatorische
Logik, die Eingänge mit Ausgängen verbindet, sondern die "box" hat
auch ein "Gedächtnis" und das Verhalten hängt von der Vorgeschichte
ab. Ausserdem muss die Box auf verschiedene Dinge unabhängig und
quasi gleichzeitig reagieren.
Man hat ja schon mal was von Zustandsautomaten gehört und ich hatte
schon vor einer Weile die Ahnung, dass sich das eignen könnte, um
das Verhalten zu modellieren. Dabei habe ich dann auch ein paar
Tools entdeckt, mit denen man das am Computer entwerfen kann.
Moore und Mealy lassen grüßen. Die Tools schienen mir dabei recht
... naja, "hardwarenah". Wie ich inzwischen vermute, lag das daran,
dass die Zielgruppe auch eher Richtung FPGA und co. ausgerichtet
ist als die gewöhnliche Softwareentwicklung.
Bei meinem eher ziellosen Studium der Literatur und diverser
Webseiten musste ich feststellen, dass man das was ich in meiner
"black-box" haben will, wohl als reaktives (echtzeit) System
bezeichnet und dass das eigentlich eine eigene Disziplin ist.
In diesem Dunstkreis sind mir dann die Artikel von David Harel
mit seiner Statechart Notation begegnet. Mir wurde klar, dass sich
so ein Großteil meiner Probleme modellieren und darstellen lassen
können müsste. Also wieder auf die Suche nach einem Tool mit dem
sich Statecharts bearbeiten lassen. Es gibt neben Statemate noch
einige andere kommerzielle Tools, die aber entweder viel zu teuer
oder in ihrer kostenlosen Version unbrauchbar sind.
Schließlich musste ich feststellen, dass in der UML ebenfalls ein
Statemachine-Diagramm enthalten ist. Ich habe also schließlich
mit allerlei UML tools experimentiert.
Woran liegt es eigentlich, dass dergleichen zu 99% in JAVA
geschrieben ist? Ok, es gibt noch umbrello, aber der Schwerpunkt
scheint dort nicht gerade auf den Statecharts zu liegen und
schien mir für meine Zwecke unbrauchbar.
Ich habe dann recht viel Zeit damit verbracht UML tools auszuprobieren:
papyrus, argouml, visualparadigm, poseidon usw usw....
Momentan bin ich bei jude hängen geblieben. Vermutlich deshalb,
weil es allerlei constraints, die offensichtlich im Rahmen der UML
spezifiziert sind, eher schwach durchsetzt. Aufgrund der Tatsache,
dass ich die Diagramme nicht wirklich nutzen will, um objektorientierte
Programme zu schreiben, schien mir das zweckmäßig. Außerdem gibt
es eine brauchbare kostenlose Version.
Nach anfänglicher Begeisterung muss ich aber feststellen, dass sich
nicht jedes Problem als Statemachine darstellen lässt. Zumindest nicht
gut und auch nicht schön.
Wo ich nun schon mal dabei war, hab ich mir einige andere Diagrammtypen
aus der UML angesehen, z.B. das Activity Diagramm. Das scheint mir
schon auch geeignet, um Teilbereiche des Verhaltens zu modellieren und
zu visualisieren. Bei genauerer Betrachung ist das aber ja eigentlich
nichts anderes als ein Flowchart. Und das wiederum scheint bei
der stukturierten Programmierung eher verpönt. Ich sehe aber
den Grund ehrlich gesagt nicht wirklich.
Schon vor einer Weile bin ich dazu übergegangen, mir die Kommunikation
unterschiedlicher Programmteile als Nachrichten vorzustellen, die
ausgetauscht werden. Wie ich nun sehe, bietet auch hier die UML
mit den Sequenz- und Kommunikationsdiagrammen Möglichkeiten, um
das Verhalten darzustellen.
Es bleibt aber das Problem, dass ich es bei C nicht mit einer
objektorientierten Programmiersprache zu tun habe. In der UML ist
es ja eher so, dass Objekte Nachrichten miteinander austauschen.
Bislang hatte ich nur nach Diagrammen gesucht, mit deren Hilfe ich
meine Software eher dokumentieren als modellieren kann.
Aber mir dämmert, dass vielleicht der umgekehrte Weg der
richtige sein könnte. Schliesslich bieten ja die meisten UML Tools
auch die Möglichkeit automatischer Codegenerierung. Natürlich wieder
nur für OO-Sprachen.
Mal vorausgesetzt, dass ich das zu Fuß mache, spricht denn etwas
gegen die Verwendung von UML Diagrammen? Gibt es etwas besseres
für nicht objektorientierte Sprachen?
Wenn ich schöne UML Bildchen male, ohne mir über die Implementierung
Gedanken zu machen, mag das in C++ ganz gut funktionieren, in C
aber nur bedingt. Sicher kann man auch in C objektähnliches
Verhalten nachbilden, aber sehr oft fallen mir dann bei der
tatsächlichen Implementierung wesentlich effizientere Möglichkeiten
ein, die dann aber nicht immer noch viel mit dem ursprünglichen
Modell zu tun haben. Und von denen ich auch gar nicht wüsste, wie ich
sie mit den mir bekannten Methoden modellieren sollte.
Wenn der Resourcenverbrauch keine Rolle spielt, sollte man darauf
vielleicht keine Rücksicht nehmen, aber in einem Microcontroller
ist eben Ram und Flash nicht unbegrenzt.
Gibt es hier andere, bessere formale Methoden, oder ist das einfach
eine Frage der Programmier (und modellier-) Erfahrung?
Also lange Rede, kurzer Sinn:
Wie macht man sowas und bin ich völlig auf dem Holzweg?
so, jetzt langt's erst mal :-).
viele Grüße,
Klaus
Ich habe es leider schon viel zu oft erlebt, dass Entwickler versuchen
die Nachteile von schlampiger Programmierarbeit mit allerleit Tools und
Konzepten auszugeleichen. Das endet dann oft in Projekten die mit
allerlei TamTam und den interessantesten Werkzeugen und Strategien
aufgezogen und irgendwann erst recht schlampig runtergehackt werden, um
auch mal fertig zu werden.
Ordentlichen und wartbaren Code zu schreiben erfordert in erster Linie
Disziplin und Fleiss. Da gehoert eben Dokumentation dazu, die erklaert
und nicht nur irgendwelchen formalen Kriterien entspricht. Und vor allem
gehoert dazu, dass die Dokumentation mitgewartet wird und dem aktuellen
Stand entspricht. Beim schreiben von Dokumentation geht es nicht darum,
in moeglichst kurzen Worten alle relevanten Parameter erwaehnt zu haben,
sondern darum dem Naechsten zu erklaeren, worum es geht. Das kann
Fliesstext oft sogar besser als abstrakte Diagramme.
Schau dich doch mal hier um, in wie vielen Codebeispielen Variablen x,
y, z oder i heissen - und wehe, jemand meckert. Und wie stolz viele
sind, wenn sie die coolste/kuerzeste/kryptischste Loesung fuer ein
Problem gefunden haben. Dass die komplexesten Vorrangregeln von C stets
parat sind und konsequent klammerfrei gearbeitet wird. Als Tutor fuer
Erstsemester hatte ich die tollsten Debatten ueber Codeformatierung -
dabei haben wir niemandem einen Stil vorgeschrieben, wir haben lediglich
verlankt, dass ein Stil konsequent umgesetzt wird. Die Standardantwort
ist "Wieso, es compiliert doch".
Ich habe einen C-Code gesehen, der ganz doll nach Entwurfsmuster
entwickelt war. Ergebnis unter anderem: Eine Callback-Funktion, die
nichts anderes macht als eine Callback-Funktion in einem anderen Modul
aufzurufen...
Merke: Tolle Diagramme nützen nix, wenn die technische Ausführung nicht
mit gesundem Menschenverstand durchgeführt wird :-)
Im Grunde genommen gilt doch für Embedded Software: Achte auf die
Laufzeit und auf den Speicherverbrauch, baue die Software modular auf
(Stichwort wiederverwendbare Funktionen), und dann passt das auch in der
Regel.
Manche Diagramme aus der UML kann man tatsächlich auch für prozedurale
Programmierung verwenden, zum Beispiel das Sequenzdiagramm, um einen
zeitlichen Ablauf sinnvoll zu dokumentieren. Aber ALLES in UML-Diagramme
packen zu wollen? Hör auf mich und lass den Quatsch. ;-)
Hallo Klaus,
ich muss dir voll recht geben.
Für Mikrocontrolleranwendungen ist es sehr schwer den Formalismus der
UML korrekt einzusetzen.
Zu aller erst empfehle ich dir folgendes Buch:
Agile Softwareentwicklung für Embedded Real-Time Systems mit der UML
Hervorragendes Buch, dass die wichtigsten UML Diagramme in Bezug zu
Embedded Systems erläutert.
Für mich persönlich sind die folgenden UML Diagramme die wichtigsten für
die Spezifikation/Design von Embedded Systems:
- Zustandsdiagramm (State Chart)
- Sequenzdiagramm
- Komponentendiagramm
- Timing Diagramme (auch UML gehört aber nicht zum Standard Paket)
- Aktivitätsdiagramme
In diesem Buch wird auch Bezug genommen zu Pattern.
Das sind Entwurfsmuster von Softwaresystemen für spezielle
Problemstellungen.
Ich habe immer viel mit Zustandsautomaten gearbeitet. Aber der Ablauf
darin ist mir mit der Zeit zu "linear" bzw. "unflexibel" geworden. Dann
habe ich angefangen Prozesse in Unterprozesse aufzuteilen und diese über
definierte Schnittstellen kommunzieren zu lassen, natürlich asychron, da
sonst eine Aufsplittung wenig Sinn macht. Hier kommen die
Sequenzdiagramme zum Einsatz.
Um nun einen Überblick über alle Module zu behalten und um zu wissen,
welches Modul von welchem Modul abhängig ist, bietet sich das
Kommunikationsdiagramm an.
für den eigentlichen Funktionsablauf bietet sich das Aktivitätsdiagramm
an, hier muss man sich davon lösen in Funktionen zu denken. Die
"Funktion" des Moduls soll hier im Vordergrund stehen. So können hier
auch so Dinge wie ein Warten auf einen Interrupt, oder ein
Synchronisationspunkt eingezeichnet werden.
Ich wünsche dir noch viel Erfolg und Spaß mit der UML :-)
MFG
Peter Stegemann schrieb:
> Ich habe es leider schon viel zu oft erlebt, dass Entwickler versuchen> die Nachteile von schlampiger Programmierarbeit mit allerleit Tools und> Konzepten auszugeleichen. Das endet dann oft in Projekten die mit> allerlei TamTam und den interessantesten Werkzeugen und Strategien> aufgezogen und irgendwann erst recht schlampig runtergehackt werden, um> auch mal fertig zu werden.
Ganz auf der gleichen Schiene hab ich auch schon erlebt, das das Tool
regelrecht zum Hauptzweck wurde. Völlig egal, ob hinten ein lauffähiges
Projekt rauskommt, hauptsache wir haben ein neues Tool :-)
Zurück zum Kern.
Für mich kann ich sagen, dass ich sehr von der objektorientierten
Programmierung und ihren Denkweisen profitiert habe. Ich würde sagen,
ich war vor meiner OO Zeit schon ganz gut unterwegs, aber mit OO hab ich
nochmal einen enormen Sprung nach vorne gemacht. Nicht falsch verstehen:
Ich spreche hier nicht von tatsächlicher Codeumsetzung, sondern von der
Gedankenwelt, wie man mit OO ein Projekt aufzieht, wie man abstrakte
Modelle baut, in die das Problem eingebettet werden kann, etc.
Durch das modellieren von Klassen und ihren Beziehungen, durch die
Denkweise des "ein Funktionsaufruf ist ein Befehl an ein Objekt, etwas
zu tun", gewöhnt man sich einen Arbeitsweise und auch eine
Softwarearchitektur an, die einem auch in C sehr zu gute kommt. Es
schärft sich einfach der Blick für Modulbauweise, welche Funktion gehört
logisch wo dazu, welche Aufgabe wird von wem wie delegiert, etc.
@Karl heinz Buchegger
dito! Aus der OO Welt kann man sehr viele IDEEN in die "Mikrocontroller
Welt" übertragen.
Ein Professor von mir halt mal gesagt:
"UML bietet die Möglichkeit von verschiedenen Blinkwinkeln auf ein und
dasselbe Objekt zu schauen."
Es ist wie bei einem Architekt der ein Haus baut, da gibt es Diagramme
die zeigen aus der Vogelperspektive die Wandstärke, in welche Richtung
die Türen aufgehen, die Anzahl der Zimmer..
und Diagramme die zeigen wo Strom Wasser Abwasser Leitungen führen.
Es gibt die Aussansicht, Innenansicht etc.
So ist das auch mit UML Diagrammen, mit einem
Aktivitätsdiagramm kann man das gleiche Modul wie mit einem
Sequenzdiagramm beschreiben.. es bietet aber einen anderen Fokus. Z.b.
betrachtet man sich beim einen den funktionalen Ablauf und beim anderen
die zeitliche Abfolge wann ein Modul an ein anderes Modul eine Nachricht
schickt.
So schnell so viele Antworten, das ist ja toll! :-)
Also ich denke, dass das alles meine (vor)Ahnung ganz gut bestätigt.
Ich sehe ein Designtool als Werkzeug, das natürlich nicht zum
Selbstzweck werden soll. Ich hab auch kein Problem damit, mal zu Papier
und Bleistift zu greifen. Recht oft finde ich das sowieso kreativer :-).
Aber es hat natürlich auch was, wenn man nicht immer den Radiergummi
braucht.
Designpattern... das ist auch so ein Stichwort. Mir ist eigentlich gar
nicht ganz klar, was man darunter versteht. Gelegentlich hat man im
Forum schon Beispielimplementierungen von Statemachines gesehen, die
naja, sagen wir mal allgemein verwendbar sein sollten. Könnte man das
dann als Entwurfsmuster auffassen? Es scheint ja eine ganze Reihe
solcher "well-known design patterns" zu geben. Sollte man sich das mal
angucken? Sebastian hat da ja schon Literatur vorgeschlagen. Mir ist
schon klar, dass man solche Patterns nicht auf biegen und brechen
umsetzen kann und muss (Marks Beispiel mit den Callback Funktionen).
@Karl Heinz: Vermutlich funktioniert der objektorientierte Denkansatz
deshalb so gut, weil Modell und Realität recht gut korrespondieren.
Die Frage ist, wie gut man das dann bei der Implementierung umsetzen
kann. Hier hängt es wohl wirklich viel von der Erfahrung des
Programmierers ab und man kann sich nicht blind auf irgendwelche Design
Patterns stützen.
Aber ein Blick darauf kann ja vielleicht mal nicht schaden....
@Peter: Tja, naja, das hat natürlich auch was mit sportlichem Ehrgeiz zu
tun. Wenn's jemand Spaß macht....
Tatsächlich könnte es ja berechtigt sein, eine kompakte Lösung
vorzuziehen, wenn der Compiler daraus auch ein kleineres Binary macht.
Aber deswegen muss man den Code sicher nicht unleserlich formulieren.
Mich würde schon auch mal interessieren, wie verständlich mein Code
eigentlich für Aussenstehende ist. Aber wenn man immer nur im stillen
Kämmerlein etwas vor sich hin bastelt und nicht irgendwie in einem Team
arbeitet, ist das mit dem Feedback oft etwas schwierig.
Na, mal sehen.
Vielen Dank erstmal für eure Anmerkungen!
Viele Grüße,
Klaus
@Klaus
Das Buch konzentriert sich mehr auf den Umgang mit UML für Embedded
Systems. Entwurfsmuster werden hier nur am Rande erwähnt.
>Designpattern... das ist auch so ein Stichwort. Mir ist eigentlich gar>nicht ganz klar, was man darunter versteht. Gelegentlich hat man im>Forum schon Beispielimplementierungen von Statemachines gesehen, die>naja, sagen wir mal allgemein verwendbar sein sollten. Könnte man das>dann als Entwurfsmuster auffassen? Es scheint ja eine ganze Reihe>solcher "well-known design patterns" zu geben.
Naja, eine State-Machine als solches ist genau genommen kein
Entwurfsmuster. Mir fällt hier als Beispiel das bekannte "Observer"
Pattern oder auch Beobachter Pattern ein.
Dies beschreibt ein Entwurfsmuster wie man "Änderungen an einem Objekt
bei anderen Objekt bekannt macht"
Schau mal nach "Model View Controller" das ist DAS klassische
Architektur Muster für komplexe Softwaresysteme.
Die meisten Entwurfsmuster die ich kenne haben aber etwas mit
Objektorientierung und Polymorphie zu tun. Die Grundidee dieser Pattern
lässt sich aber auch auf Sprachen wie C portieren.
Mit generischen Funktionspointern etc. aber gerade auf ressourcen
begrenzten Systemen ist sowas mit Vorsicht zu genießen.
Gut Nacht ;)
sebastian schrieb:
> @Klaus>> Das Buch konzentriert sich mehr auf den Umgang mit UML für Embedded> Systems. Entwurfsmuster werden hier nur am Rande erwähnt.
Das Buch ist inzwischen nicht mehr im Handel, man kann es aber auf der
Homepage der Sophist Group (www.sophist.de) downloaden, wenn man sich
registriert. Zum Lesen bin ich noch nicht gekommen, bin aber schon ganz
gespannt :-).
> Schau mal nach "Model View Controller" das ist DAS klassische> Architektur Muster für komplexe Softwaresysteme.
Hm, hab' grade mal den Wiki Artikel gelesen.
Sicher kann man das nicht jedem Projekt "überstülpen", oder?
Ich habe schon öfters mal was mit Postgress gebastelt und dabei wohl das
Model-View-Controller Entwurfsmuster verwendet, ohne es zu kennen :-).
Aber wenn ich grade über meine bisherigen embedded Projekte nachdenke,
kann ich mir nicht recht vorstellen viel damit anfangen zu können.
Aber vielleicht liegt das ja an mir und nicht an dem Muster :-).
Wenn ich da noch etwas weiter klicke zu den Behavioral Patterns sieht
das schon anders aus! Sicher ist es auch nicht zweckmässig solche Muster
mit Gewalt umzusetzen, aber ich könnte mir schon vorstellen, dass es
recht hilfreich sein könnte, diese Ideen im Hinterkopf zu behalten. Man
ist sich vielleicht oft viel bewusster was man eigentlich programmiert.
viele Grüße!
Klaus
Klaus W. schrieb:
>> Schau mal nach "Model View Controller" das ist DAS klassische>> Architektur Muster für komplexe Softwaresysteme.>> Sicher kann man das nicht jedem Projekt "überstülpen", oder?
'Jedes' im mathematischen Sinne für 'Für Alle' ist eine schwerwiegende
Behauptung. Aber abgesehen davon: Bisher ging das eigentlich immer. Die
MFC ist im wesentlichen darauf aufgebaut, auch wenn der Teil Controller
da stiefmütterlich behandelt wird, da die Bandbreite in diesem Teil
einfach zu gross ist und Controller oftmals eng mit dem View
zusammenarbeiten müssen.
Das 'Kochrezept' des MVC ist doch:
trenne Daten, Datenhaltung und Datenmanipulation streng von der Anzeige
der Daten und das wiederrum von den Werkzeugen, die du deinem Benutzer
zur Manipulation der Daten in die Hand gibst. Und du kriegst ein
flexibles System, das gut in alle Richtungen erweiterbar ist. Sowohl was
Erweiterung des Datenmodells als auch verschiedene Anzeigevariationen
angeht. Wenn man will, kann man Modell-View alleine auch als eine
Variation des Observer-Patterns auffassen.
Für mich 'leider', hat sich aber der Trend in der Windows Programmierung
gewandelt, hin zu Forms-basierter Programmierung ohne die Vorgabe eines
Model-View Frameworks. Dementsprechend verwoben und wartungsunfreundlich
sind dann auch zeitgenössische Programme von Leuten, die sich die
strenge Modell-View Architektur nicht zu eigen gemacht haben. Ich sitz
auch schon seit einiger Zeit an so einem geerbtem Qt-Programm. Da werden
Dialog-Elemente an den unmöglichsten Stellen gefüllt oder abgefragt.
Dialoglogik ist über 15 Klassen verstreut. Selbst ein simples 'Cancel'
in einem Dialog stellt sich als schwierig heraus, weil der Dialog auf
den Original-Daten arbeitet, anstatt auf einer Arbeitskopie der Daten
für den Dialog. Arbeitskopie geht wieder nicht, weil Datenhaltung und
Anzeige so ineinander verwoben sind, dass eine Kopie mangels fehlender
Widget Pointer sofort abschmiert, etc. Eine 2-te, andere, Ansicht (also
einen View) auf die Daten einzubauen ist momentan ein Ding der
Unmöglichkeit, weil die Ansichten nicht synchron updaten würden, etc.
> Ich habe schon öfters mal was mit Postgress gebastelt und dabei wohl das> Model-View-Controller Entwurfsmuster verwendet, ohne es zu kennen :-).
Kann gut sein.
> Aber wenn ich grade über meine bisherigen embedded Projekte nachdenke,> kann ich mir nicht recht vorstellen viel damit anfangen zu können.
Na denk zb mal an die üblichen Ratschläge, wie ISR zu behandeln sind. In
einer ISR werden maximal ein paar Datenfelder manipuliert. Die
eigentliche Anzeige oder Ausgabe kommt in die Hauptschleife.
Mit ein wenig guten Willen kann man die Hauptschleife (oder zumindest
einen Teil davon) als den View ansehen, während die ISR Teil des Model
ist.
>Das 'Kochrezept' des MVC ist doch:>trenne Daten, Datenhaltung und Datenmanipulation streng von der Anzeige>der Daten und das wiederrum von den Werkzeugen, die du deinem Benutzer>zur Manipulation der Daten in die Hand gibst. Und du kriegst ein>flexibles System, das gut in alle Richtungen erweiterbar ist. Sowohl was>Erweiterung des Datenmodells als auch verschiedene Anzeigevariationen>angeht. Wenn man will, kann man Modell-View alleine auch als eine>Variation des Observer-Patterns auffassen.
Ja, Model und View werden tatsächlich oft mit dem Observer Pattern
realisiert. Richtig, aber im Grund ist der Gedanke dahinter, die
konsequente Trennung zwischen Darstellung und Daten und Steuerung.
Und der Gewinn dadurch ist eine flexible, wartbare und erweiterbasre
Software. Also das Gegenteil von dem, was im Programmspeicher der
meisten Mikrocontroller Anwednungen rum liegt. ;-)
Ein gutes Beispiel wäre das Menü in einem LCD Display. Viele bauen so
viel Komplexität in die Menü-STEUERUNG, dass in fast das ganze System um
die Ohren fliegt, wenn sie die Eingabemethode ändern odern einen weitern
Menü Punkt hinzufügen wollen. Ja, auch ich schließe mich da nicht aus.
:-) Aber der Mensch lernt ja bekanntermassen nur durch Schmerz. :)
>Für mich 'leider', hat sich aber der Trend in der Windows Programmierung>gewandelt, hin zu Forms-basierter Programmierung ohne die Vorgabe eines>Model-View Frameworks. Dementsprechend verwoben und wartungsunfreundlich>sind dann auch zeitgenössische Programme von Leuten, die sich die>strenge Modell-View Architektur nicht zu eigen gemacht haben.
Amen, Bruder! ;-) Ja, die meisten Klick-Drop Entwicklungsumgebungen wie
Delphi etc. sind mittlerweile so einfach zu bedienen, dass zu weilen
grausamer Code hinter den Benutzeroberflächen ruht. Oben hui- hinten
pfui!
>Ich sitz>auch schon seit einiger Zeit an so einem geerbtem Qt-Programm. Da werden>Dialog-Elemente an den unmöglichsten Stellen gefüllt oder abgefragt.>Dialoglogik ist über 15 Klassen verstreut. Selbst ein simples 'Cancel'>in einem Dialog stellt sich als schwierig heraus, weil der Dialog auf>den Original-Daten arbeitet, anstatt auf einer Arbeitskopie der Daten>für den Dialog. Arbeitskopie geht wieder nicht, weil Datenhaltung und>Anzeige so ineinander verwoben sind, dass eine Kopie mangels fehlender>Widget Pointer sofort abschmiert, etc. Eine 2-te, andere, Ansicht (also>einen View) auf die Daten einzubauen ist momentan ein Ding der>Unmöglichkeit, weil die Ansichten nicht synchron updaten würden, etc.
Ohja, mit Qt habe ich auch schon Erfahrungen gemacht. zu Beginn war ich
sehr angetan von dem Signal-Slot konzept, welches man auch als Pattern
bezeichnen kann. Also für alle die es nicht kennen: Über ein Objekt
werden Signal (Sender) und Slot (Empfänger) miteinander verküpft. So
wird z.b. eine bestimmte funktion augerufen, wenn ein bestimmtes Event
(z.B.) Button.clicked() auftritt.
So kann man auch sehr schön mehrere Funktionen durch ein Event auslösen.
So wird die Kopplung gering gehalten und man hält die Architektur
flexibel.
MFG
>Das Buch ist inzwischen nicht mehr im Handel, man kann es aber auf der>Homepage der Sophist Group (www.sophist.de) downloaden, wenn man sich>registriert. Zum Lesen bin ich noch nicht gekommen, bin aber schon ganz>gespannt :-).
In welchem Format kann man sich das Buch downloaden?
Kannst du mir evtl. das PDF davon schicken?
> Was genau ist eigentlich eine funktionale Sprache?
Och, das ist ganz einfach:
In einer (strengen) funktionalen Sprache gibt es keine Variablen und
keine iterativen Schleifen und Funktionen haben exakt einen Parameter
und geben exakt ein Wert zurück. Ausserdem sind Funktionen
First-Class-Objekte und als "Nebeneffekt" gibt es Funktionen höhere
Ordnung, d.h. Funktionen die als Ergebnis wiederrum eine Funktion haben.
Und ja, damit kann man Programme schreiben, und das auch noch sehr
elegant. Aber das alles hier zu erklären führt zu weit.
Zurück zu Deinem Problem:
> Die Struktur ist dahin, die Übersicht auch und selbst nur> mittelmässig komplexe Projekte will man nach einem Jahr eigentlich> nicht mehr anfassen, weil es keinen Spass macht in dem Codewust> noch zu arbeiten.
Ich vermute, Dein Problem ist ein "Disziplin-Problem" oder eine falsche
Sichtweise auf das Programieren.
Anstatt hier alles wiederzukauen, was schlaue Menschen schon
niedergeschrieben haben, möchte ich Dir folgendes Buch empfehlen:
http://www.amazon.de/Pragmatische-Programmierer-Andrew-Hunt/dp/3446223096
UML und strukturierte Sprachen widerspricht sich wohl in einigen
Aspekten. Man kann somit nicht alles aus der UML benutzen. Ich versuche
hier auch die Quadratur des Kreises in der Firma und werde wohl nur
Sequenzdiagramme und Statecharts nehmen. Geholfen hat mir dieses Buch
"Practical UML Statecharts in C/C++: Event-Driven Programming for
Embedded Systems"
ISBN 0750687061
Hauptaugenmerk wird in der 2.Auflage auf C gelegt, die erste soll mehr
C++ lastig sein.
Ansonsten lege ich bei meinen Projekten (privat und beruflich) Wert auf:
- einen durchgängig identischen Programmierstil
- bei uC Anwendungen auf ein BSP, das von der Hauptanwendung
(ab)gekapselt ist
Je weiter man "nach oben" kommt - also die Hauptanwendung - desto
verwurschtelter wird es meist... ist meine Ansicht.
Das BSP in der Firma habe ich noch ohne UML entwickelt, für Bootloader
und Hauptapplikation möchte ich aber unbedingt die Kenntnisse o.g.
Buches anwenden. Schulungen im Bereich UML & C & Microcontroller sind
nach meinen Recherchen sehr dünn bis überhaupt nciht vorhanden. Da wird
einem viel blabla um die Ohren gehauen von den Marketingspezis der
Schulungsanbieter.
Das o.g. kostet so ~35,-EUR - also nicht die Welt. Ist halt auf englisch
und man muss sich durch das Papier halt an einigen Wochenenden
durchbeissen. Dafür ist es das erste, das ich gefunden habe, das auf
meine Belange eingeht.
Hab gerade durch den letzten Post noch dieses Buch entdeckt:
Modellierung von eingebetteten Systemen mit UML und SysML (Taschenbuch)
Klingt auch recht viel versprechend.
sebastian schrieb:
> Hab gerade durch den letzten Post noch dieses Buch entdeckt:> Modellierung von eingebetteten Systemen mit UML und SysML (Taschenbuch)>> Klingt auch recht viel versprechend.
Ja, das liegt hier bei mir auch schon auf dem Schreibtisch. Jetzt
bräuchte ich nur noch Zeit zum Lesen. Das andere Buch scheint mir auf
den ersten Blick fast interessanter. Mal gucken!
Das pdf kann ich Dir schon schicken, aber eine kurze Email an
buch@sophist.de genügt auch! Die sind recht umgänglich.
@ Karl Heinz:
> Na denk zb mal an die üblichen Ratschläge, wie ISR zu behandeln sind. In> einer ISR werden maximal ein paar Datenfelder manipuliert. Die> eigentliche Anzeige oder Ausgabe kommt in die Hauptschleife.> Mit ein wenig guten Willen kann man die Hauptschleife (oder zumindest> einen Teil davon) als den View ansehen, während die ISR Teil des Model> ist.
Hm, also das muss ich mir jetzt erst noch etwas durch den Kopf gehen
lassen. Ich hätte die ISR wohl eher dem Controller zugeordnet.
Aber ich werde jetzt erst mal etwas Literatur studieren, bevor ich mit
meinem Viertelwissen versuche etwas zu verstehen :-).
@Sonnentau:
>In einer (strengen) funktionalen Sprache gibt es keine Variablen und>keine iterativen Schleifen und Funktionen haben exakt einen Parameter>und geben exakt ein Wert zurück. Ausserdem sind Funktionen
Hm, das heißt also, dass C keine funktionale Sprache ist.
Viele Grüße,
Klaus
Klaus W. schrieb:
> Hm, das heißt also, dass C keine funktionale Sprache ist.
Rüchtüg.
Zu funktionalen Sprachen fällt mir im Moment nur LISP, Haskell und Gofer
ein (wobei Gofer ein Haskell-Derivat ist).
Mark Brandis schrieb:
> Klaus W. schrieb:>> Hm, das heißt also, dass C keine funktionale Sprache ist.>> Rüchtüg.>> Zu funktionalen Sprachen fällt mir im Moment nur LISP, Haskell und Gofer> ein (wobei Gofer ein Haskell-Derivat ist).
Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter
Programmierung alles als funktionale Programmiersprache bezeichnet wird,
was nicht objektorientiert ist.
Naja...
Klaus W. schrieb:
> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter> Programmierung alles als funktionale Programmiersprache bezeichnet wird,> was nicht objektorientiert ist.
Was dann gemeint ist, ist "prozedural". Da die Prozeduren in C
Funktionen heissen, liegt das Missverstaendnis nahe.
> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter> Programmierung alles als funktionale Programmiersprache bezeichnet wird,> was nicht objektorientiert ist.
Liegt IMHO daran, dass (viele) OO-Jungs nicht über ihren Tellerrand
blicken (können) und der irrigen Meinung sind, sie hätten die Spitze der
Programmier-Paradigmen erklommen.
Das lustige ist aber, dass die Probleme die OO versucht zu lösen, in der
funktionalen Welt überhaupt nicht existieren. Und das ist (nicht nur)
für die OO-Jungs hart.
Puuh, also das ist alles ganz schön kompliziert.
"Agile Softwareentwicklung für Embedded Real-Time Systems mit der UML"
habe ich jetzt zum Großteil gelesen. Natürlich müsste man das richtig
durcharbeiten, aber ich weiss zumindest schon mal was drinsteht.
Wenn ich die Zusammenhänge richtig verstehe, beschäftigt sich das
Buch in erster Linie mit der Verwendung der UML und setzt dabei
schon entsprechendes Vorwissen über die UML selbst voraus.
Dabei geht es also mehr um den Entwicklungsprozess als um die UML
selbst.
Ich muss allerdings gestehen, dass ich durchaus noch meine
Schwierigkeiten habe diese Bereiche gegeneinander abzugrenzen.
Zum Teil finden sich recht interessante Themen, allerdings kann ich
nur ansatzweise sehen, wie ich die Erkenntnisse nutzbringend für
mich einsetzen könnte.
Aber es bleiben für mich auch noch viele Fragen offen.
Ist. z.B. die Gegenüberstellung von essenziellen Klassen und
technologiegetriebenen Klassen gleichzusetzen mit fachlichen
und technologischen Klassen?
Designpatterns werden wie bereits erwähnt auch gestreift.
Es findet sich übrigens ein interessanter Link:
http://www.hillside.net/patterns
Die Abbildung der diversen Techniken in konkreten C-Code ist mir
immer noch zum großen Teil recht rätselhaft. Auch wenn
Herr Buchegger schon ein paar Hinweise gegeben hat.
Vielleicht ist das aber auch alles einfach ein Nummer zu groß
für meine Miniprojekte?
Also ich würde das ganze ja gerne nochmal von einer anderen
Seite betrachten. Vielleicht kann dazu einer der Experten auch noch
ein paar Anmerkungen machen:
Eine meiner Anwendungen, die ich im Anfangsposting schon erwähnt hatte,
die fertiggestellt ist und sich bewährt hat, macht folgendes:
Im Auto eines Bekannten (Kfz-Bastelfreak) soll ein Sack voll LEDs
durch verschiedene Ereignisse ( Zentralverriegelung, Zündungsstellung,
Helligkeit, Türkontakte usw..) in geeigneter Weise gesteuert werden.
Es gibt noch ein paar Testmodi, da z.B. die Polarität und Timing
mancher Signale im Voraus nicht bekannt war und zugeöhrige
Konfigurationsmöglichkeiten über ein paar Taster, Config im EEPROM,
Power Management usw.
Das ganze läuft aus historischen Gründen auf einem attiny26, da die
Hardware schon einige Jahre existiert und auch nicht modifiziert werden
sollte.
Das klingt erstmal ziemlich primitiv. Der Code wirkt aber auf den ersten
Blick recht umfangreich und ich frage mich, ob das an irgendwelchen
grundsätzlichen Designfehlern oder auch der konkreten Implementierung
liegt.
Die Auswertung der Eingangssignale wird mit Statemachines
durchgeführt, die auch die Entprellung beinhalten. Die Statemachines
rekonstruieren auch Zustände, die sich nur durch die zeitliche
Historie ergeben. Dieser Teil generiert Nachrichten, die an die
eigentliche "Geschäftslogik" gesendet werden, die wiederum aus
verschiedenen Statemachines besteht. Diese generieren ebenfalls
Nachrichten, welche dann vom Ausgabeteil verarbeitet werden.
Soweit war das auch mein ursprünglicher Gedanke vor der eigentlichen
Implementierung.
Nun ist es aber so, dass die ganzen Statemachines quasi parallel
und voneinander unabhängig, also sozusagen nebenläufig sein müssen.
Der Ausgabeteil läuft mehr oder weniger vollständig im Interrupt, weil
die meisten Kanäle per (software) PWM dimmbar sein sollen und das ganze
relativ zeitkritisch ist, damit es nicht flimmert.
Sonstige zeitabhhängige Ereignisse und (software) timer z.B. innerhalb
der Statemachines laufen in main() und erhalten dazu alle 10ms
ein Signal von einem weiteren Timer Interrupt, das entsprechend
ausgewertet wird. Dadurch werden auch viele volatile Variablen
vermieden auf die der Zugriff recht uneffizient wäre.
Die (logische) Nebenläufigkeit dieser "Tasks" (Prozesse? Objekte?)
(ja, ich bin da in der Terminologie leider recht unsicher) habe ich
so realisiert, dass es einfach eine große main-while(1) loop gibt,
in der diese Tasks zyklisch ausgeführt werden. Dabei habe ich darauf
geachtet, dass es keine Warteschleifen o.ä. in diesen Tasks gibt.
Manche der Tasks werden aber nur in festen Zeitrastern aufgerufen, wie
z.B. die Tastaturentprellung, Abfrage der A/D Wandler usw. Die
Statemachines sind also quasi z.B. mit 10ms oder 1s getaktet. So spare
ich mir zusätzliche Timer innerhalb dieser Statemachines.
Die Statemachines der "Geschäftslogik" werden einfach mit der
verbleibenden Rechenzeit jedesmal ausgeführt, sowie die äussere
while(1) loop ausgeführt wird, obwohl dies eigentlich gar nicht
nötig wäre.
Grundsätzlich scheint mir das ganze irgendwie recht umständlich.
Ich frage mich immer ob es wirklich so kompliziert sein muss ein
paar LEDs in Abhängigkeit von ein paar Eingangssignalen zu steuern.
Die ganzen "Tasks", also im wesentlichen Statemachines sind alle
als Dauerwurst in der while(1) Schleife enthalten und arbeiten mit
lokalen Variablen aus main(). Es wäre viel schöner, jede
Statemachine als Funktion zu programmieren, ihre Zustände in
statischen Variablen zu kapseln und die Nachrichten als Über-
und Rückgabewerte zu übergeben.
Ich habe diese Strategie trotzdem aufgegeben, weil ich mit dem
Flash im tiny26 recht schnell an die Grenze gekommen bin und
Funktionsaufrufe und static Variablen teurer sind als
den Code einfach der Reihe nach hinzuschreiben.
Das ist ein wenig unbefriedigend. Ich verstehe aber auch immer wieder
nicht wirklich was der Compiler daraus macht. Ich hatte gehofft,
dass static inline funktionen zu ähnlich kurzem Code führen
müssten, wenn sie nur einmal verwendet werden und nur
der Übersicht halber vorhanden sind.
Es scheint z.T. auch daran zu liegen, dass die static Variablen
grundsätzlich irgendwo im Speicher und nicht auf dem Stack liegen?
Vielleicht wird das dann mit der Registerverwendung über
Funktionsgrenzen hinweg nicht mehr so gut optimiert?
Oder sag' ich's nur dem Compiler nicht richtig?
Das ganze bleibt trotzdem vergleichsweise übersichtlich, weil
die "Tasks" einfach sequenziell der reihe nach abgearbeitet werden.
Vielleicht ist das in dem Fall dann auch einfach ok so?
Ich frage mich aber auch, wie es zu bewerkstelligen wäre,
wenn ich dem Controller nun noch eine andere Aufgabe geben möchte.
Von mir aus Primzahlen berechnen, die er immer dann ausführen soll,
wenn sonst nichts zu tun ist. Also statt die übrige Rechenzeit
in den Statemachines für die aktuelle Geschäftslogik zu verbraten.
Ich müsste dann den neuen "Task" auch so gestalten, dass der
Algorithmus in Häppchen zerteilt wird, die klein genug sind,
dass die geforderten Antwortzeiten der anderen Tasks auf
ihre Nachrichten gewährleistet bleiben.
Also HALLO? Es kann ja wohl nicht sein, dass ich ein Betriebssystem
mit Scheduler brauche um ein paar LEDs zu steuern!?!?!?
Alternativ hatte ich schon die Idee meine ganze bisherige Applikation
selbst in einen Interrupt zu verlegen, der dann die an sich
nebensächliche Primzahlenberechnung (als Beispiel) in main()
unterbricht. Dieser Interrupt müsste dann aber selbst wieder durch den
sehr hoch priorisierten Interrupt für die PWM Ausgabe zu unterbrechen
sein.
Vermutlich schlagen jetzt wieder einige Leute die Hände über dem Kopf
zusammen falls überhaupt so weit gelesen.....
Dieser beispielhafte Primzahltask hat irgendwie einen anderen
Charakter als alle anderen. Die anderen Tasks reagieren immer nur auf
Nachrichten. Von der Bearbeitung weiss ich, dass sie wesentlich
kürzer dauert als die kürzeste geforderte Antwortzeit von anderen Tasks.
Der Primzahltask dauert aber quasi ewig.
Es scheint ja schon irgendwie wichtig zu sein, sich über all diese
Dinge und Eigenschaften beim Design eines Systems im klaren zu sein.
Glücklicherweise hat das in meinem Fall recht gut funktioniert, aber
es hätte ja auch anders sein können.
Daher meine Suche nach irgendwelchen Modellierungsmöglichkeiten, die
solche Schwierigkeiten im Vorfeld zum Ausdruck bringen können. Vor
allem, wenn es mal etwas komplexer wird, als ein paar LEDs zu steuern
und man nicht einfach ein persönliches Modell im Kopf haben kann.
Nunja, es bleibt schwierig :-).
gute Nacht und viele Grüße,
Klaus
Hey Klaus,
ok, so langsam verstehe ich deine Problematik. Wenn es um solche
"Architektur Techniken" geht, dann ist wohl das Buch über agile
Softwareentwicklung mit der UML eher ein schlechter Tipp gewesen, da es
in diesem Buch, wie du schon geschrieben hast, eher um Prozesse und die
Anwendung der UML in verschiedenen Entwicklungsphasen geht.
Zu deinem konkreten Problem:
Ja, das was du hier brauchst ist ein Task-Management.
Das klingt im ersten Moment vielleicht aufgebläht und übertrieben, aber
im Grund musst dieses Task-Management nicht viel machen:
Beispiel:
1
#define TASK_PERIODE_1 10 // alle 10 ms
2
#define TASK_PERIODE_2 50 // alle 50 ms
3
#define TASK_PERIODE_3 100 // alle 100 ms
In einem 1 ms Interrupt wird dann das "Task-Management" vorgenommen:
Fuer jeden Task gibt es hier einen Counter, wird ein Periodenwert
erreicht, dann wird ein Task-Flask gesetzt. Hier sollte natürlich darauf
geachtet werden, dass keine Tasks aufeinander fallen. Sowas lässt sich
mit einem Zeit-Diagramm und Deadlines für jeden Task gut darstellen.
Nun werden in der main() nur die Flags fuer die Tasks ausgewertet:
1
intmain(void)
2
{
3
if(TASK_MANAGEMENGT_Task_1.enabled==true)
4
{
5
Task_1();
6
TASK_MANAGEMENGT_Task_1.enabled=false;
7
}
8
9
// ...
10
11
if(TASK_MANAGEMENT_No_Task_enabled==true)
12
{
13
Primzahlenberechnung();//Aus deinem Beispiel, dieser "Task" sollte sehr kurz sein um die anderen Tasks nicht zu beeinflussen...
14
}
15
return0;
16
}
Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das
Prinzip veranschaulichen. du kannst auch so dinge wie deadlines,
Task-Aufsplittung einbauen...
Zu deinen anderen Fragen:
Ja, jede Statemachine sollte Kern eines Moduls und des Tasks sein.
Statemachines bieten sich hier gut an, da sie nicht komplette in einem
Task Durchlauf durchlaufen werden müssen, sondern so von "Zustand zu
Zustand" gedachte werden kann.
Ja, static variablen werden wie globale Variablen behandelt und für sie
wird Speicher im RAM belegt (kannst du dir im map file anschauen) lokale
Variablen (also ohne static) werden auf den Stack gepushed.
Ich weiß nicht, aber vielleicht gibt es ja schon einen Beitrag in der
Artikelsammlung oder Codesammlung zu einem einfachen 8 Bit Controller
Task Management, welches man auch auf einem ATtiny einsetzen könnte.
Schönen Sonntag :)
Sebastian
Hallo Sebastian!
Vielen Dank für Deine Antwort!
sebastian schrieb:
> Softwareentwicklung mit der UML eher ein schlechter Tipp gewesen, da es> in diesem Buch, wie du schon geschrieben hast, eher um Prozesse und die> Anwendung der UML in verschiedenen Entwicklungsphasen geht.
Schlechter Tipp nicht direkt. Ich finde es schon sehr interessant. Nur
jetzt aktuell bringt es mich tatsächlich nicht sehr viel weiter.
> In einem 1 ms Interrupt wird dann das "Task-Management" vorgenommen:> Fuer jeden Task gibt es hier einen Counter, wird ein Periodenwert> erreicht, dann wird ein Task-Flask gesetzt. Hier sollte natürlich darauf> geachtet werden, dass keine Tasks aufeinander fallen. Sowas lässt sich> mit einem Zeit-Diagramm und Deadlines für jeden Task gut darstellen.
So ungefähr habe ich das tatsächlich auch gemacht. Nur dass bei mir die
maximale Auflösung 10ms beträgt. Das reicht in meinem Fall. Außerdem
gibt es nur diesen einen 10ms Interrupt und eine Art Scheduling Task,
der in Deinem Beispiel die "TASK_MANAGEMENGT_Task_x.enabled" Flags
generieren würde.
Die Zähler decrementiere ich stattdessen. Ich könnte mir denken, dass
der assembler code um auf 0 zu prüfen kürzer ist als auf einen konkreten
Wert? Hab' das aber noch nicht nachgesehen.
Was meinst Du damit, dass keine Tasks aufeinander fallen sollten? Es
würde doch nichts passieren, wenn das Taskmanagement mehrere Tasks
gleichzeitig aktiviert. Sie werden dann halt einfach in der Reihenfolge
der Implementierung abgearbeitet, oder?
> Primzahlenberechnung(); //Aus deinem Beispiel, dieser "Task" sollte> sehr kurz sein um die anderen Tasks nicht zu beeinflussen...
Tja und das ist eben unschön. Es wäre viel praktischer, wenn dieser Task
automatisch unterbrochen werden würde. Ich könnte natürlich prüfen, ob
ein anderer Task aktiviert wurde (per Interrupt) und dann die
Primzahlenberechnung unterbrechen. Aber auch das müsste man in den
Primzahlalgorithmus einbauen.
> Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das> Prinzip veranschaulichen. du kannst auch so dinge wie deadlines,> Task-Aufsplittung einbauen...
Bei mir gibts eher so Taskzusammenfassungen :-). Aber auch nur um das
Binary kürzer zu bekommen.
Was meinst du mit Deadlines?
> Ich weiß nicht, aber vielleicht gibt es ja schon einen Beitrag in der> Artikelsammlung oder Codesammlung zu einem einfachen 8 Bit Controller> Task Management, welches man auch auf einem ATtiny einsetzen könnte.
Gibt's! Allerdings konnte ich nichts finden, was effizient genug gewesen
wäre, um es so 1:1 formal anwenden zu können.
Aber wenn nun niemand eine ganz andere Idee vorschlägt wie man sowas
macht, bin ich ja schon ganz zufrieden :-).
Schönen Feiertag!
Klaus
>Vielen Dank für Deine Antwort!
Kein Problem :-)
>So ungefähr habe ich das tatsächlich auch gemacht. Nur dass bei mir die>maximale Auflösung 10ms beträgt. Das reicht in meinem Fall. Außerdem>gibt es nur diesen einen 10ms Interrupt und eine Art Scheduling Task,>der in Deinem Beispiel die "TASK_MANAGEMENGT_Task_x.enabled" Flags>generieren würde.>Die Zähler decrementiere ich stattdessen. Ich könnte mir denken, dass>der assembler code um auf 0 zu prüfen kürzer ist als auf einen konkreten>Wert? Hab' das aber noch nicht nachgesehen.
Da hast du natürlich Recht! "JUMP IF ZERO" ist natürlich gänger als
"JUMP IF XY".
>Was meinst Du damit, dass keine Tasks aufeinander fallen sollten? Es>würde doch nichts passieren, wenn das Taskmanagement mehrere Tasks>gleichzeitig aktiviert. Sie werden dann halt einfach in der Reihenfolge>der Implementierung abgearbeitet, oder?
Einfaches Beispiel:
Du hast einen Task 1, der alle 10 ms ausgeführt wird.
Und einen Task 2, der alle 100 ms ausgeführt werden soll.
Die Ausführungszeit von Task 1 ist 50 us und die von Task 2 100 us.
So nun lassen wir beide loslaufen, bei T=0 (sagen wir du hast einen 10
ms "Basis Takt")
Bei T=10, wird Task 2 zum ersten mal ausgeführt und Task 1 zum 10, mal.
Nun wird aber in deinem Task Management Task 2 z.b. vor Task 1
ausgeführt (rein theoretisch) dann wir dann Task 1 bei T=10 erst 100 us
später ausgeführt als die anderen 9 mal zuvor. So ergibt sich ein Jitter
bei Task 1 den du dir zum Beispiel auf dem Oszi ansehen kannst. Das muss
nicht kritisch, kann aber unter Umständen zu unschönen Nebeneffekten
führen.
>> Primzahlenberechnung(); //Aus deinem Beispiel, dieser "Task" sollte>> sehr kurz sein um die anderen Tasks nicht zu beeinflussen...>Tja und das ist eben unschön. Es wäre viel praktischer, wenn dieser Task>automatisch unterbrochen werden würde. Ich könnte natürlich prüfen, ob>ein anderer Task aktiviert wurde (per Interrupt) und dann die>Primzahlenberechnung unterbrechen. Aber auch das müsste man in den>Primzahlalgorithmus einbauen.
Mhm, nur eine Idee:
Der Task Primzahelnberechnung wird in einem anderen Timer Task
ausgeführt. Nun normalerweise ist es ja so, dass ein Interrupt keinen
anderen unterbrechen kann. Wenn du zu Beginn des "Primzahlen Timers" nun
das Interrupt System wieder aktivierst, dann kann dein "Task Management"
jederzeit deine Primzahlenberechnung unterbrechen.
Hier musst du aber sehr sorgfältig vorgehen, damit hier keine
Inkosistenzen oder Deadlocks entsehen. Evtl. brauchst du Semaphoren,
wenn beide Interrupt Routinen auf gemeinsamen Speicher zugreifen.
>> Das ganze ist jetzt nicht sehr ausgearbeitet, aber es soll nur das>> Prinzip veranschaulichen. du kannst auch so dinge wie deadlines,>> Task-Aufsplittung einbauen...>Bei mir gibts eher so Taskzusammenfassungen :-). Aber auch nur um das>Binary kürzer zu bekommen.>Was meinst du mit Deadlines?
Deadline ist die Zeit bis ein bestimmter Task spätestens ausgeführt
werden soll! Z.b. hast du Task 1 der kommt alle 10 ms, dauert 50 us und
soll spätestens nach der Aufforderung (alle 10ms) nach 100 us ausgeführt
werden. Damit erlaubst du Task 1 einen Jitter von 50 us.
>Schönen Feiertag!>Klaus
Wünsch ich dir auch,
Sebastian
sebastian schrieb:
> später ausgeführt als die anderen 9 mal zuvor. So ergibt sich ein Jitter> bei Task 1 den du dir zum Beispiel auf dem Oszi ansehen kannst. Das muss> nicht kritisch, kann aber unter Umständen zu unschönen Nebeneffekten> führen.
Ja, das ist klar, bei mir aber völlig irrelevant. Aber ist schon klar,
dass es Fälle geben kann, wo das eine Rolle spielt.
> Mhm, nur eine Idee:>> Der Task Primzahelnberechnung wird in einem anderen Timer Task> ausgeführt. Nun normalerweise ist es ja so, dass ein Interrupt keinen> anderen unterbrechen kann. Wenn du zu Beginn des "Primzahlen Timers" nun> das Interrupt System wieder aktivierst, dann kann dein "Task Management"> jederzeit deine Primzahlenberechnung unterbrechen.
Hm, also ich hatte eher gedacht praktisch die ganze (zeitkritische)
Applikation in einem Interrupt laufen zu lassen (und das wäre dann halt
99% des Codes) und die Primzahlberechnung in main(). Aber diese ISR
müsste dann auch wieder Interrupts zulassen, weil die PWM Erzeugung ja
NOCH zeitkritischer ist. Also ziemlich haarig und von solchen Dingen
wird ja generell immer abgeraten. - Außer man weiss genau was man tut.
Weiß ich das?
Naja, ist ja eh nur hypothetisch. Ich werde mir nächstes mal Gedanken
machen wenn so ein Problem real ansteht :-).
> Hier musst du aber sehr sorgfältig vorgehen, damit hier keine> Inkosistenzen oder Deadlocks entsehen. Evtl. brauchst du Semaphoren,> wenn beide Interrupt Routinen auf gemeinsamen Speicher zugreifen.
Hmmm... weil der Compiler Code erzeugt, der nichts davon weiss dass ein
Interrupt eine ISR unterbrechen kann?
> Deadline ist die Zeit bis ein bestimmter Task spätestens ausgeführt> werden soll! Z.b. hast du Task 1 der kommt alle 10 ms, dauert 50 us und> soll spätestens nach der Aufforderung (alle 10ms) nach 100 us ausgeführt> werden. Damit erlaubst du Task 1 einen Jitter von 50 us.
Ah, verstehe....
Nochmal grundsätzlich zur Nebenläufigkeit:
Wenn man so UML Klassendiagramme sieht, erweckt das bei mir häufig den
Eindruck dass Objekte in der OO Welt grundsätzlich nebenläufig wären.
Die generieren da munter irgendwelche Nachrichten.... Ich habe vor
langer Zeit nur mal so interessehalber ein paar Klassen in C++ gebastelt
und instanziiert oder wie man da sagt und habe also praktisch wirklich
keine Ahnung. Aber so ein Objekt macht doch von sich aus erstmal genauso
nichts wie eine Funktion, wenn es nicht gefragt wird, oder sehe ich das
falsch?
viele Grüße!
Klaus
> Aber so ein Objekt macht doch von sich aus erstmal genauso> nichts wie eine Funktion, wenn es nicht gefragt wird, oder> sehe ich das falsch?
Das siehst Du vollkommen richtig.
Wenn ich mir so Deine Probleme durchlese, bekomme ich den Eindruck, Du
gehst irgendwie zu kompliziert an die Aufgabe ran.
Auch wenn es "Mode" ist, wenn man 17 Abstraktiosschichten übereinander
legt, lösen sich die Probleme nicht magisch von selbst. Irgendwo muss im
Programm gearbeitet werden, irgendwo werden die Hände schmutzig. Sprich:
Ein Programm wird nicht elegant, wenn man die Verantwortung von einer
Abstraktion zur nächsten schiebt.
Konkretes Beispiel:
> Manche der Tasks werden aber nur in festen Zeitrastern aufgerufen,> wie z.B. die Tastaturentprellung, Abfrage der A/D Wandler usw.
Dafür brauchst Du keine Tasks, sondern Du verwendest Hardware.
Z.b. der AD-Wandler kann autonom mit einer festen Samplingrate laufen.
Immer wenn der einen neuen Wert hat, setzt er ein Bit. Dieses Bit kannst
Du zu beliebigen Zeitpunkten abfragen, z.B. so:
1
voidcheck_ad()
2
{
3
if(!bit_in_ad_wandler_gesetzt())
4
return;
5
6
...
7
}
Oder die Entprellerei. Du entscheidest Dich einfach für eine
Sampling-Rate für die Tasten, und machst das in einem Timer-Interrupt.
Wenn Du nur auf Taster-Downs reagieren musst, hast Du zwei Variablen.
Die eine zeigt immer den entprellten Zustand der Taster an. In der
anderen werden die entsprechenden Bits nur dann gesetzt (vom Interrupt),
wenn sich der Zustand einer Taste von 0 auf 1 gewechselt hat.
Dann kannst Du jederzeit abfragen, ob ein Taster gedrückt wurde
(Key-Down-Event) und das Bit dann löschen, wenn Du den Event bearbeitet
hast. Also etwa so:
1
voidcheck_foobar_key()
2
{
3
if(!(key_event&0x01))
4
return;
5
6
key_event&=~0x01;
7
8
...
9
}
Das kannst Du dann auch mit verschiedene Zuständen kombinieren, so dass
in bestimmten Situationen die Tasten unterschiedliche Funktionen haben
etc.
Wie gesagt: Nicht die Aufgaben zwischen dutzenden Abstraktionsschichten
hin und her schieben, sondern Aufgaben da lösen, wo sie auftreten.
Der Witz an der Sache: Wozu Software und Abstraktionen schreiben, wenn
die Hardware Dir Deine Probleme löst.
Später, wenn Du viel Erfahrungen gesammelt hast, wirst Du ein besseres
Gespür bekommen, wann und was wie abstrahiert werden kann, soll oder
muss.
Aber am Anfang gilt:
Frühe Optimierung ist tödlich!
Hallo!
Baumschüler schrieb:
> Wenn ich mir so Deine Probleme durchlese, bekomme ich den Eindruck, Du> gehst irgendwie zu kompliziert an die Aufgabe ran.
Naja, wie erwähnt, sind die Probleme eigentlich schon gelöst und das
Ding funktioniert. Aber es kann ja nicht schaden mal etwas über den
Tellerrand zu blicken :-).
> Auch wenn es "Mode" ist, wenn man 17 Abstraktiosschichten übereinander> legt, lösen sich die Probleme nicht magisch von selbst. Irgendwo muss im> Programm gearbeitet werden, irgendwo werden die Hände schmutzig. Sprich:> Ein Programm wird nicht elegant, wenn man die Verantwortung von einer> Abstraktion zur nächsten schiebt.
Da hast Du recht. Aber auf der anderen Seite sollte es doch auch nicht
schaden, sich über die Struktur der Applikation im klaren zu sein.
Alleine das Abstraktionsmittel der Statemachine fand ich dabei sehr
hilfreich. Die Tastaturentprellung war etwas komplizierter, weil ich
auch so Dinge auswerte wie "zwei kurze Tastenanschläge hintereinander",
"zwei Tasten gemeinsam lange gedrückt" usw.
Die Frage war für mich einfach ob es neben den Statecharts noch andere
hilfreiche Abstraktionen gibt, die man sich zu nutze machen könnte.
Klar, muss natürlich alles mit Mass und Ziel passieren und ein Diagramm
macht noch kein Programm....
Genau genommen ist das Diagramm ja auch nur die visuelle Darstellung des
Modells welches ich sowieso irgendwie im Kopf haben muss, um sowas zu
programmieren.
Ich stelle mir schon vor dass es einen weiter bringen könnte, sich diese
Zusammenhänge bewusst zu machen.
> Konkretes Beispiel:> Dafür brauchst Du keine Tasks, sondern Du verwendest Hardware.>> Z.b. der AD-Wandler kann autonom mit einer festen Samplingrate laufen.> Immer wenn der einen neuen Wert hat, setzt er ein Bit. Dieses Bit kannst> Du zu beliebigen Zeitpunkten abfragen, z.B. so:
Ja, das tut er natürlich auch. Auf die Wandlung zu warten kann ich mir
nicht leisten :-). Mich interessiert der Wert sowieso nur alle 1s. Bis
dahin ist die Wandlung längst fertig und ich frage das Bit nur
sicherheitshalber ab.
> Oder die Entprellerei. Du entscheidest Dich einfach für eine> Sampling-Rate für die Tasten, und machst das in einem Timer-Interrupt.
Naja, das ist nicht ganz so einfach. Wie sicher schon irgendwo erwähnt
habe ich neben der Tastenentprellung noch allerlei andere Statemachines
die quasi parallel laufen. Da bräuchte ich ja 20 Timer und Interrupts.
Also ich muss das schon noch etwas "verteilen" :-).
>
1
>voidcheck_foobar_key()
2
>{
3
>if(!(key_event&0x01))
4
>return;
5
>
6
>key_event&=~0x01;
7
>
8
>...
9
>}
10
>
Ja, so ungefähr mache ich das auch. Nur dass ich im allgemeinen keine
einzelnen Bits verwende. Ich stelle mir vor dass die Bitmaskiererei in
Assembler auch wieder ein paar Instruktionen länger dauert. An RAM bin
ich nicht knapp und "key_event = 0" geht vermutlich schneller?
(Hab konkret nicht nachgeguckt)
> Das kannst Du dann auch mit verschiedene Zuständen kombinieren, so dass> in bestimmten Situationen die Tasten unterschiedliche Funktionen haben> etc.
Ja, es gibt eine Statemachine die den Hauptbetriebsmodus (Test, Config,
Demo, Operation usw..) festlegt. Je nach dem bewirken die Tasten
natürlich auch unterschiedliche Dinge.
> Wie gesagt: Nicht die Aufgaben zwischen dutzenden Abstraktionsschichten> hin und her schieben, sondern Aufgaben da lösen, wo sie auftreten.
Naja, ich würde sagen auf der untersten Abstraktionsebene.
> Später, wenn Du viel Erfahrungen gesammelt hast, wirst Du ein besseres> Gespür bekommen, wann und was wie abstrahiert werden kann, soll oder> muss.
Ja, daran arbeite ich gerade :-).
> Aber am Anfang gilt:>> Frühe Optimierung ist tödlich!
Hm, Optimierung in welcher hinsicht?
Viele Grüße,
Klaus
HEy Klaus,
mein letzter Post war Schwachsinn:
"Primzahlen in einem eigenen Timer Interrupt und Task Management wieder
in einem eigenen"
--> Hier würde zwar das task MANAGEMENT zum Zuge kommen, aber die
eigentliche Task Ausführung würde permanent vom Primzahelninterrupt
unterbrochen. Also Schwachsinn, bitte vergessen :)
Aber die Tasks in der Timer ISR auszuführen ist auch nicht gut.
Du musst darauf achten wie du deine "Primzahlenroutine" gestaltest, d.h.
wenn die Routine so gestaltest ist, dass sie nur eine Iteration
durchläuft und ggf. noch einen Status zurück liefert ...
bool dummy_task (void);
// --> Rueckgabewert 0: Task beendet
// --> 1: Wait: Wenn moeglich moechte Task nocheinmal
ausgefuehrt werden..
sebastian schrieb:
> --> Hier würde zwar das task MANAGEMENT zum Zuge kommen, aber die> eigentliche Task Ausführung würde permanent vom Primzahelninterrupt> unterbrochen.
Ja, eben :-). Müsste ja eher umgekehrt sein.
> Aber die Tasks in der Timer ISR auszuführen ist auch nicht gut.
Warum eigentlich?
Ok, es ist zwar relativ viel code, aber es wird ja in jedem Interrupt
immer nur ein winziger Bruchteil davon ausgeführt. Und die Zeit zwischen
den Interrupts ist eine Ewigkeit im Vergleich zur Ausführungsdauer der
ISR.
Einzig unschön wäre, dass der Interrupt für die software PWM diese ISR
wieder unterbrechen müsste.
> Du musst darauf achten wie du deine "Primzahlenroutine" gestaltest, d.h.> wenn die Routine so gestaltest ist, dass sie nur eine Iteration> durchläuft und ggf. noch einen Status zurück liefert ...
Ja, das ist klar.
Viele Grüße,
Klaus
PS: Ich lese grade "Modellierung von eingebetteten Systemen mit UML und
SysML" von Andreas Korff. Damit kann ich grade wesentlich mehr anfangen
als mit dem anderen von Dir vorgeschlagenen Buch. - Was natürlich nicht
heisst dass das schlecht wäre. - Naja, hatten wir ja schon :-).
>Ok, es ist zwar relativ viel code, aber es wird ja in jedem Interrupt>immer nur ein winziger Bruchteil davon ausgeführt. Und die Zeit zwischen>den Interrupts ist eine Ewigkeit im Vergleich zur Ausführungsdauer der>ISR.>Einzig unschön wäre, dass der Interrupt für die software PWM diese ISR>wieder unterbrechen müsste.
Läuft die Soft PWM in einem Task in deinem Task Management?
Wieviele Timer Interrupts verwendest du denn für dein Task Management?
Mach es doch so:
Die 'High Priority Tasks" realisierst du direkt in der Timer ISR, also
die Tasks die relativ kurze Ausführungszeiten haben, aber immer
deterministisch ausgeführt werden sollen.
Die 'Low Priority Tasks" führst du in main() aus, bei diesen spielt dann
ein Jitter von ein paar us/ ms keine Rolle.
Du musst natürlich wieder auf Überlappungen, Ausführungszeiten
aufpassen.
Der Soft PWM Task wäre ein High Priority Task.
Die Primzahlenberechnung ein Low Priority Task, da diese von den High
P. Tasks unterbrochen werden darf.
Mfg
PS: Das Buch klingt interessant, das schaue ich mir auch mal an :)
Kannst ja gerne mal deine Erfahrungen mit dem Buch posten.
Klaus W. schrieb:
> Wie macht man sowas und bin ich völlig auf dem Holzweg?
Eigentlich ist der Thread ja schon ein bisschen alt, aber weil er genau
mein Thema trifft, wollte ich noch einen Beitrag anhängen.
Ich habe mich das gleiche nämlich auch gefragt und Astade ist meine
Antwort auf die Frage.
Ich mache schon seit über 20 Jahren Software für Embedded Systeme
(professionell, das heißt ich verdiene mein Geld damit). Für mich ist
das Zustandsdiagramm der einzige Weg, wirklich gute Software zu machen.
Das heißt Software, die wirklich auf alle Eventualitäten reagiert.
Leider braucht es dazu die Diagramme (Bilder) sonst verliert man den
Überblick. Die letzten Jahre mache ich das mit Astade, wo ich auch zu
den Autoren gehöre.
Astade hat inzwischen einen Zustand erreicht, wo ich es guten Gewissens
für Mikrocontroller empfehlen kann.
Es generiert effektiven C Code aus grafischen Zustandsdiagrammen und hat
ein eingebautes Trace Framework, das alle Aktivitäten des Programms
grafisch in Sequenzdiagrammen darstellen kann.
Hallo Thomas!
Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen"
Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis
bewährt?
Also seit meinem ursprünglichen Post habe ich (hoffe ich) schon allerlei
neue Erfahrungen sammeln können.
Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu
modellieren. Aber eben auch nicht immer.
Insbesondere muss man unterscheiden, ob die States natürlicherweise in
einer Funktion enthalten sind (z.B. in einem Übertragungsprotokoll) oder
ob sie künstlich eingeführt wurden, um das kooperative Multitasking zu
ermöglichen. States aus dem ersten Fall lassen sich durchaus auch für
den zweiten Fall verwenden.
Ich habe aber die Erfahrung gemacht, dass man sich mit der Modellierung
recht schwer tut, wenn man sich diesen Unterschied nicht bewusst macht.
So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges
UML Werkzeug, sondern legt den Schwerpunkt auf automatische
Codeerzeugung bzw. Simulation der Zustandsautomaten?
Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir
das schon als große Hilfe vorstellen. Weil das Modell dann mit der
Softwareimplementierung konsistent bleibt.
Wenn es hingegen um künstliche States wegen dem Multitasking geht,
scheint mir sowas in der Art wie Adam Dunkels Protothreads die bessere
Wahl zu sein. Aber da muss ich auch erst noch etwas mehr Praxiserfahrung
sammeln.
Grundsätzlich tue ich mich nach wie vor noch recht schwer ein
Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in
Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor
dem Problem den einen oder anderen Trick anwenden zu müssen, um
Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden
zu können, wodurch die Programmstruktur nicht immer schöner und
übersichtlicher wird. Das dann wiederum in einer Modellsprache
abzubilden, die womöglich wieder automatisch Code erzeugen soll,
erscheint mir vorsichtig formuliert unmöglich.
Vielleicht habe ich nur immer noch die falsche Herangehensweise.
Aber möglicherweise kommt ja noch die große Erleuchtung :-).
viele Grüße!
Klaus
texmex schrieb:
> Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen"> Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis> bewährt?
Ich arbeite auch in der Embedded Softwareentwicklung und wir verwenden
im Moment das freite Tool UMLet um UML Diagramme zu zeichnen.
> Also seit meinem ursprünglichen Post habe ich (hoffe ich) schon allerlei> neue Erfahrungen sammeln können.
Ich bin auch der Sebastian aus dem ursprünglichen Post ;-)
> Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu> modellieren. Aber eben auch nicht immer.
SW-Systeme allein mit Statecharts zu beschreiben ist unmöglich.
In unserem aktuellen SRS (Software Requirements Specification) sind auf
oberster Ebene die Komponentendiagramme. Anforderungen, Teilnehmer und
Akteure werden danach gut mit Use-Case Diagrammen beschrieben. Wie die
Module miteinander interagieren, wird mit Sequenzdiagrammen beschrieben.
Zustände innerhalb der Module werden mit Aktivitätsdiagrammen
(Verhalten, Abläufe) und mit State Charts beschrieben (Zustände)
Wohl gemerkt, alles "embedded" auf einem 8-bit Controller. Für alle die
so etwas nur mit 32 Bit Controllern und C++, C# in Verbindung bringen
können ...
> Insbesondere muss man unterscheiden, ob die States natürlicherweise in> einer Funktion enthalten sind (z.B. in einem Übertragungsprotokoll) oder> ob sie künstlich eingeführt wurden, um das kooperative Multitasking zu> ermöglichen. States aus dem ersten Fall lassen sich durchaus auch für> den zweiten Fall verwenden.
Was meinst du mit "natürlichen" Task und "künstlichen" ? Kann mir
darunter gerade wenig vorstellen.
> Ich habe aber die Erfahrung gemacht, dass man sich mit der Modellierung> recht schwer tut, wenn man sich diesen Unterschied nicht bewusst macht.>> So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges> UML Werkzeug, sondern legt den Schwerpunkt auf automatische> Codeerzeugung bzw. Simulation der Zustandsautomaten?>> Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir> das schon als große Hilfe vorstellen. Weil das Modell dann mit der> Softwareimplementierung konsistent bleibt.>> Wenn es hingegen um künstliche States wegen dem Multitasking geht,> scheint mir sowas in der Art wie Adam Dunkels Protothreads die bessere> Wahl zu sein. Aber da muss ich auch erst noch etwas mehr Praxiserfahrung> sammeln.>> Grundsätzlich tue ich mich nach wie vor noch recht schwer ein> Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in> Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor> dem Problem den einen oder anderen Trick anwenden zu müssen, um> Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden> zu können, wodurch die Programmstruktur nicht immer schöner und> übersichtlicher wird. Das dann wiederum in einer Modellsprache> abzubilden, die womöglich wieder automatisch Code erzeugen soll,> erscheint mir vorsichtig formuliert unmöglich.
Die Qualität und die Tiefe der Beschreibung hängt natürlich auch davon
ab für wenn die Beschreibung gedacht ist. Gerade wenn man in einem Team
arbeitet ist eine gute Beschreibung unerlässlich - hier zeigen sich
schnell die Schwächen eines schlecht dokumentierten Systems. ...
>> Vielleicht habe ich nur immer noch die falsche Herangehensweise.>> Aber möglicherweise kommt ja noch die große Erleuchtung :-).>>> viele Grüße!> Klaus
viele grüße,
sebastian
texmex schrieb:
> Ich hab' mir das Astade mal angeguckt. Die Idee mit den "dynamischen"> Diagrammen finde ich ganz witzig. Aber ob sich das in der Praxis> bewährt?
Ja, tut es. Ich entwickle seit 5 Jahren quasi "alles" mit Astade. Auch
Astade selbst ist vollständig mit Astade entwickelt.
Leider sind die Tutorials und die Website noch nicht vollständig genug,
um das alleine vom ansehen her zu beurteilen. Aber Du hast meine Aussage
und wenn Du dich etwas näher damit befassen willst, helfe ich Dir gerne
jederzeit über die Anfangsschwierigkeiten.
> Sicher sind Statemachines oft ein gutes Mittel, um Abläufe zu> modellieren. Aber eben auch nicht immer.
Ein sehr wertvolles Hilfsmittel (eigentlich noch wertvoller als die
generierten Statecharts) sind die automatisch generierten
Sequenzdiagramme in Astade. Astade instrumentiert den erzeugten Code mit
Macros und man kann dann, ein entsprechendes Makefile vorausgesetzt, ein
Sequenzdiagramm vom laufenden Code bekommen.
> So wie ich sehe, versteht sich Astade nicht unbedingt als vollwertiges> UML Werkzeug, sondern legt den Schwerpunkt auf automatische> Codeerzeugung bzw. Simulation der Zustandsautomaten?
Astade versteht sich als IDE zur Softwareentwicklung, die UML soweit
unterstützt, wie es für den Entwickler hilfreich ist.
Von der Astade Oberfläche aus wird Code generiert, der Editor
aufgerufen, compiliert, ins Taget geladen und der Debugger gestartet.
> Sofern das zur Modellbildung eines Algorithmus dienen soll, kann ich mir> das schon als große Hilfe vorstellen. Weil das Modell dann mit der> Softwareimplementierung konsistent bleibt.
So ist es.
> Grundsätzlich tue ich mich nach wie vor noch recht schwer ein> Softwaresystem komplett als UML Modell darzustellen. Sicher ist es in> Teilbereichen sehr hilfreich. Andererseits stehe ich immer wieder vor> dem Problem den einen oder anderen Trick anwenden zu müssen, um> Anforderungen hinsichtlich Echtzeit, Latenz, Jitter usw. gerecht werden> zu können, wodurch die Programmstruktur nicht immer schöner und> übersichtlicher wird. Das dann wiederum in einer Modellsprache> abzubilden, die womöglich wieder automatisch Code erzeugen soll,> erscheint mir vorsichtig formuliert unmöglich.
Ist es nicht. Astade sieht viele Möglichkeiten vor, "Handcodierten" code
neben dem Model zu haben. Das ist schon deshalb wichtig, weil Du auch
"alten" Code verwenden willst, oder ein Beispiel aus dem Web, oder eine
Library, oder Code Stücke, die der Hersteller mitliefert, oder oder oder
...
Dort ist dann auch Platz für alle Arten von "Tricks". Natürlich macht
das nur Sinn, wenn Deine Software nicht ausschließlich aus Tricks
besteht ;-)
> Aber möglicherweise kommt ja noch die große Erleuchtung :-).
Wenn Du mal Zeit und Lust hast, Astade auszuprobieren, biete ich Dir
meine Unterstützung an. Hier im Forum bin ich nicht immer gut zu
erreichen, aber über die Astade Website erreichst Du mich auch.
> Leider sind die Tutorials und die Website noch nicht vollständig genug,> um das alleine vom ansehen her zu beurteilen. Aber Du hast meine Aussage> und wenn Du dich etwas näher damit befassen willst, helfe ich Dir gerne> jederzeit über die Anfangsschwierigkeiten.
Tja, also so ein mini-howto, mit ein paar codebeispielen wäre sicher
ganz interessant.
Das Script zum compilieren ist auch etwas undurchsichtig. Ich habe schon
bemerkt dass "install" als Option an die Makefiles weitergereicht wird.
Aber ich find's etwas blöd dass die Executables alle in ~/bin und die
Librarys aber systemweit installiert werden (wollen).
> Ein sehr wertvolles Hilfsmittel (eigentlich noch wertvoller als die> generierten Statecharts) sind die automatisch generierten> Sequenzdiagramme in Astade. Astade instrumentiert den erzeugten Code mit> Macros und man kann dann, ein entsprechendes Makefile vorausgesetzt, ein> Sequenzdiagramm vom laufenden Code bekommen.
Hm, das klingt eigentlich schon ganz interessant.
> Dort ist dann auch Platz für alle Arten von "Tricks". Natürlich macht> das nur Sinn, wenn Deine Software nicht ausschließlich aus Tricks> besteht ;-)
Ja, versteht sich :-).
> Wenn Du mal Zeit und Lust hast, Astade auszuprobieren, biete ich Dir> meine Unterstützung an. Hier im Forum bin ich nicht immer gut zu> erreichen, aber über die Astade Website erreichst Du mich auch.
Das Angebot nehme ich zwar gerne an, aber vielleicht wäre es trotzdem
effizienter, wenn Du die Mühe erstmal in noch etwas docu investierst?
Dann hätten andere auch noch mehr davon?
Ich werde mir das ganze selbst nochmal angucken bei Gelegenheit.
Viele Grüße,
Klaus
Klaus W. schrieb:
> Das Angebot nehme ich zwar gerne an, aber vielleicht wäre es trotzdem> effizienter, wenn Du die Mühe erstmal in noch etwas docu investierst?> Dann hätten andere auch noch mehr davon?
Im Grunde habe ich mich da schon bemüht. Hier gibt es tutorials:
http://astade.de/doku2d49.html?id=tutorial:index
Das ganze ist als wiki gestaltet. Es ist aber wirklich sehr schwer, den
richtigen Level für ein Tutorial zu finden (zumindest kommt mir das so
vor).
Auch kann ich mir schwer vorstellen, was die Leute wissen wollen.
Ich habe jetzt einen Workshop ausgearbeitet, um speziell die
Mikrocontroller Programmierung mit Astade zu erklären.
http://consulting.astade.de/workshop.htm
Der Workshop findet am 15.04.2010 das erste mal statt. Danach habe ich
möglicherweise genug Erfahrung (im Erklären) um eine Tutorial für
Mikrocontroller Programmierung mit Astade zu machen.
Wenn Du was Ausprobieren willst und ich Dich hier im Forum unterstützen
kann, dann würde mir das auch helfen. Es würde Helfen, zu bestimmen,
welchen Inhalt ein Tutorial haben muss.
Hallo Klaus!
Habe ehrlich gesagt nicht alle Antworten hier auf Deine Frage gelesen,
allerdings immerhin Deine Frage komplett. (-; ^^
Vielleicht hast Du schon alles gefunden was Du brauchst, allerdings
scheint mir vom ersten Eindruck ( so eben nach dem Lesen des Threads
hier entdeckt ) Drakon ( http://drakon-editor.sourceforge.net/cpp/c.html
) eine gute Lösung zur Visualisierung von C - Programmen zu sein.
Insbesondere wie for-Schleifen dargestellt werden, fand ich sehr
ansprechend.
Habe aber selbst bislang keine praktische Erfahrung damit, wollte es nur
als weitere Alternative, gerade im Vergleich zu "einfachen" ( und damit
meiner Meinung nach schnell unübersichtlich werdenden )
Programmablaufplänen oder komplexen (?) UML-Diagrammen nennen.
Weitere Links dazu:
- http://drakon-editor.sourceforge.net/
- https://en.wikipedia.org/wiki/DRAKON
Viele Grüße
Christian
spess53 schrieb:> Nach vier Jahren sollte sich das Thema wohl erledigt haben.
Hmm, ach, so würde ich das nicht sagen.
Erledigt ist so ein Thema wahrscheinlich nie ganz :-).
> Mir scheint aber schon manchmal so als ob im Umfeld objektorientierter> Programmierung alles als funktionale Programmiersprache bezeichnet wird,> was nicht objektorientiert ist.
Meine vereinfachte Vorstellung einer funktionalen Programmiersprache ist
folgende: Sie ist die Beschreibung eines Schaltplans. So wie VHDL oder
Veriolog.
Es gibt seit ein paar Monaten eine sehr interessante Alternative:
www.eclipse.org/etrice
Es handelt sich um ein ROOM-Tool.
ROOM = Realtime Object Oriented Modelling
Infos und Links:
http://de.wikipedia.org/wiki/Real_Time_Object_Oriented_Modeling
ROOM wurde speziell für embedded Echtzeitsysteme entwickelt. Die Methode
stammt aus der Telekom.
ROOM wurde zu großen Teilen in die UML2 übernommen.
eTrice erzeugt den kompletten C-Applikationscode fürs Target.
Falls die benutzte IDE eine Eclipse basierte IDE (Kepler oder Luna)ist,
sollte das Tool einfach über "help->Insall New Software" integriebar
sein.
Für LPCXpresso habe ich das ausprobiert, funktioniert tadellos.
Ansonsten geht auch eine Stand-Allone Installation.
Viel Spaß
Thomas