Hallo! Ich bin gerade etwas ratlos und deshalb wende ich mich an das Forum. Ich weiß nicht wie ich weitermachen soll. Folgendes: Wir bauen in der Firma ein ziemlich komplexes Gerät. Es hat wie alle Geräte sehr klein angefangen. Doch es wurde ständig erweitert. Es beinhaltet Schrittmotoren, diverse Taster für Klappen, die man öffnen kann, einen Ein-,Ausschalter, ein Display, Temperatursensoren, Sensoren für Helligkeit, diverse Mosfets zum Schalten von Geräten, USB-Verbindung zum Computer und UART-Kommunikationen innerhalb des Gerätes. Leider darf ich nicht mehr verraten. Wir benutzen hierfür einen ATMEGA128. Man kann sich vorstellen, dass das Programm, welches diese ganzen Steueraufgaben übernehmen muss relativ komplex ist, noch dazu dann, wenn sehr viele verschiedene Komponenten in verschiedenen Statuszuständen des Gerätes verschiedene Reaktionen auslösen können. Manche Komponenten (z.B. Taster oder andere Sensoren) müssen hierbei höhere Prioritäten haben als andere. Dann muss der µP ständig auf Anfragen des PC's antworten können und auf diese vielen Ereignisse richtig reagieren. Hier kann man erkennen, dass das Programm sich ständig verändert und wächst. Dadurch war es nicht möglich von Anfang an ein entsprechendes Programmkonzept zu entwickeln. Aus diesem Grund können manche Erweiterungen nur noch relativ umständlich eingebaut werden. Dann leidet aber wieder die Übersichtlichkeit des Programmes. Diese Übersicht zu behalten war ab einem gewissen Zeitpunkt nicht mehr möglich, besonders deshalb nicht, weil man dann mal wieder ein paar Monate lang an anderen Projekten arbeitete. Auch die Aufgabenstellungen, die vorher genügten müssen ausgebaut werden. Dadurch sind manche Konzepte, die im Programm realisiert sind nicht mehr anwendbar und müssen neu erdacht werden. So wie das Gerät jetzt aufgebaut ist funktioniert es mit der Software einwandfrei. Das Problem ist jetzt die Übersicht wiederzufinden, nämlich das Konzept soweit zu vereinfachen und zu verändern, dass Erweiterungen wieder einfacher möglich sind. Ich programmiere mit CodeVision AVR (C) und bis jetzt ist jedes Programm im Kopf entstanden und daraus nach und nach immer mehr Code enstanden. Bis jetzt hat das recht gut funktioniert, da sich die Programme im Rahmen gehalten haben. Aber das ist jetzt nicht mehr der Fall. Gibt es hierfür irgendwelche Werkzeuge, um solche Programmkonzepte planen zu können, um die Übersicht zu behalten? Oder wie soll man in diesem Fall am besten vorgehen? Das Proramm völlig neu zu schreiben wäre, so glaube ich, zu aufwändig. Es sind auch manchmal Ideen realisiert, die im Programmcode nicht mehr als solches erkennbar sind. Ein Kompromiss wäre die Veränderung des Programmes. Es enthält einige Funktionen, die man so lassen kann. Die Namen der Variablen könnte man etwas besser wählen. Habt hier hierfür Vorschläge? Ich danke euch für jede Antwort. Wie machen die richtigen Profil solche Programmkonzepte? Tschüss Martin
Hallo Martin, für Programmkonzepte werden umfangreiche Dokumentationen erstellt. Diese setzen sich meist aus Flussdiagrammen etc. zusammen. Im Softwarebereich für PC Programme hat sich hier die UML durchgesetzt. (UML = Unified Modeling Language). Diese kann arbeitet vor allem mit Klassen (welche bei uC nicht verwendet werden - zumindest nicht in dieser Größenordnung). Ein Programm, mit dem man viele Ablaufdiagramme erstellen kann (auch UML) wäre zum Beispiel Microsoft Visio. Viele Grüße Steffen
Hallo, such' mal nach Poseidon UML. Das ist ein freies UML-Tool. Zumindest die Community Edition. UML lässt sich auch relativ gut auf uCs anwenden um den Überblick zu wahren. Besonders die Statemachines sind ganz interessant wenn man Steuerungsaufgaben erledigen muss. Das wichtigste ist allerdings die Doku! Viele Grüße, Ralf
Hallo Martin, ich bin mir nicht sicher, ob bei Deiner Problematik eine noch so gute Doku weiterhilft. Nach zwei oder drei Erweiterungen ist sie veraltet. Meine Projekte setzen sich aus etwa hundert Dateien zusammen. Ich verwende einen vernünftigen Editor (UltraEdit) dazu das Tool CTAG, zum suchen von Funktionen in anderen Dateien dann einen vernünftigen Compiler (GCC) als Programiersprache C++ und kein C eine Versionsverwaltung (CVS) ist auch ganz hilfreich warum diese Kombination? Editor und CTAG zum navigieren in vielen gleichzeitig geöffneten Dateien GCC wegen den gut zu steuernden Fehlermeldungen und Warnungen C++ wegen der Kapselung Es sind alles relativ einfache Tools, die Übersicht kommt nur aus einer sinvollen Organisation der Quellcodes. Dateinamen und Verwendung von Verzeichnissen. Allgemeine Regeln: keine globalen Variablen alles was zusammen gehört, in ein Modul möglichst klare Regeln, um einzelne Steuerungen zu starten und zu beenden. Sinnvolle Funktions- und Variablennamen soviele lokale Variablen wie möglich alle Warnungen einschalten und auch beachten(Warnungen als Fehler werten) zu jedem Modul eine kurze Beschreibung zu jeder Funktion eine kurze Beschreibung zu jeder globalen Variablen eine kurze Beschreibung wenn möglich new und delete vermeiden verwende einen möglichst einfachen Programierstil, der Kompiler optimiert für dich. Bei Deiner Programmgrösse ist eine Überarbeitung der Programmstuktur nie auszuschliessen. Bei einer langen Entwicklungsphase kommt es zu einschneidenen Änderungen und auch zu einer eigenen Weiterentwicklung. Die alte Erfahrung: Hinterher ist man immer schlauer. Aber bei Dir ist hinterher auch schon wieder vorher. Also nutze Deine Weiterentwicklung. Auch wenn es erst mal viel Arbeit macht. Solltest Du ein Tool finden, das Dir weiterhilft, teile es mir bitte mit. Oryx
Hm - irgendwie kommt mir das bekannt vor. So ein Projekt habe ich momentan auch am Bein, so halbjährlich kommen neue Ideen und man muß dann den eigentlich lauffähigen Code "verschlimmbessern". Zunächst einmal das Wichtigste: Der Kunde / dafür Verantwortliche muß dahin gedrängt werden, sich endlich einmal zu entscheiden, was das Gerät wirklich können soll. Es ist immer schwieriger, in einem bestehenden Code eine neue Funktion zu implementieren, als dies von vornherein zu planen. Der Hinweis auf die Mehrkosten ist meistens eine "Entscheidungshilfe". Sollte dies nicht möglich sein, hast Du mein ganzes Mitgefühl ;-) Ansonsten gibts nur, wie schon erwähnt, folgendes zu beachten: - Gute Dokumentation - Gute Dokumentation - Wichtig: Gute Dokumentation. Flußdiagramme und ein Kommentar : Codeverhältnis von min. 3:1 sind zwar bei der Erstellung aufwendig, aber gerade dann, wenn man selbst (oder jemand anders) sich in dieses Projekt (wieder) hineinarbeiten muß, spart man diese zusätzlich investierte Zeit vielfach wieder ein.
Hallo Martin, irgendwie kämpft jeder mit dem Problem, dass das Programm und die Ideen im Kopf schneller wachsen als die Dokumentation. Ich bemühe mich zwar zumindest die Prototypen im Header entsprechend zu kommentieren, wenn es aber dann eilt, bleibt die Doku manchmal doch wieder auf der Strecke. :-( Ich verwende das Tool doxygen (www.doxygen.org, GNU-Lizenz). Damit kann man aus dem Sourcecode eine prima HTML-Doku seines Projekts erzeugen. Man benötigt dazu lediglich ein Paar Schlüsselwörter im Kommentar. So hat man immer auf Knopfdruck eine aktuelle Dokumentation zur Verfügung. (Vorausgesetzt die Kommentare im SRC-Code sind aktuell!) Darüber hinaus kann ich mich Oryx nur anschließen mit der Einschränkung, dass man auch mit C objektorientiert und gekapselt programmieren kann. (Kapselung ist überhaupt kein Thema bei C, bei Vererbung wirds schon etwas problematischer.) Als UML Tool möchte ich ArgoUML (http://argouml.tigris.org) einsetzen. Hab allerdings noch kaum Erfahrungen damit. Prinzipiell ist zu UML-Tools zu sagen, dass sie ihr volles Potential erst ausschöpfen, wenn man damit sowohl aus dem Modell Code erzeugen kann und evtl. eigenen Code auch in das Modell übernehmen kann. Diese Tools kosten allerdings dann meist auch eine Menge Geld. Verwendet man UML nur als reines Dokumentationswerkzeug, hat man häufig das Problem, dass Modell und Implementierung nicht übereinstimmen. Hermann
Hallo, was vielleicht auch noch ganz gut ist, ist das Programm Source Insight. Mit diesem Programm kann man einmal codieren und zum anderen kann man sich auch ganze Aufrufbäume anzeigen lassen um zu sehen, wie alle Funktionen zusammenhängen. Bei den Erweiterungen ist es natürlich klar, dass damit ein Mehraufwand verbunden ist. Auf der anderen Seite merkt man dann auch, ob das Systemdesign passt oder nicht. Das heißt am besten immer erst mal viele Gedanken an einem guten und flexiblen Konzept verwenden. Dann hat man später immer weniger Probleme wenn Änderungen dazukommen, was ja eigentlich normal ist. Welcher Kunde weiß denn schon vorher was er will ;-) Datenkapselung/Modularisierung und definierte Schnittstellen helfen hier schon sehr weiter. Viele Grüße, Ralf
Hallo, kennt jemand ein gutes und freies UML-Tool, das auch ANSI-C Code erzeugen kann?
Hallo, meine Erfahrung ist, dass der von den Tools erzeugte Code recht aufwendig ist. Ich halte das ganze also eher für PC-Software für richtig anwendbar. Gibt's da andere Erfahrungen? Ralf
Wichtig für eine gute Erweiterbarkeit ist eigentlich nur, daß alle Tasks kooperativ geschrieben sind. D.h. sie dürfen: - keine Rechenzeit mit Warteschleifen vernichten - nicht zuviel am Stück machen - keine Ressourcen exklusiv belegen - möglichst wenige globale Variablen belegen. Und für die Ressourcen (Timer, ADC) sind separate Treiber zu erstellen, die die Verwendung durch mehreren Tasks gestatten. Z.B. statt eine Timer zu stoppen läuft er ständig durch und die Funktion, die eine Zeitverzögerung benötigt macht das über die Differenzzeit. Sind viele verschiedene zeitgesteuerte Prozesse gleichzeitig nötig, lohnt sich auch der Einsatz eines Schedulers. Und auch extra Treiber für Tastenentprellung, LCD-Ausgabe und andere zentrale Dinge. Dann ist es eigentlich ganz leicht ein bestehendes Programm fast beliebig zu erweitern. Peter
Ich habe mal eine Fortbildung zu dem Thema besucht ("agile Embedded-Programmierung" oder so). Fazit: Objektorientierung und UML mit code generation lohnen sich heute auch im µC-Bereich. Der Overhead ist gar nicht so gewaltig gegenüber dem eines typischen gewachsenen Code-Chaos mit einer Krücke hier und einer Krücke da. Im Zweifelsfall lieber den nächst-größeren Controller nehmen (bei Dir natürlich blöd, weil Du schon beim Flaggschiff der Baureihe angelangt bist und somit die Plattform wechseln müßtest). Meine Erfahrungen damit: tolle Sache für ein neues Projekt, aber in der Praxis müßte man bei fast null anfangen, um ein gewachsenes Projekt damit zu entwirren. Die Zeit hat/bekommt man im Normalfall nicht, weil dringend noch zeitaufwendige Änderungen am alten Code zu machen sind -- ein Teufelskreis. Wie mit dem Holzfäller, der keine Zeit hat, seine Axt zu schärfen, weil er erst sein Tagespensum schaffen muß, was so lange dauert, weil seine Axt so stumpf ist ... Ich habe den von meinem Vorgänger "geerbten" Code nach und nach aufgeräumt; dabei ist er trotz erheblich erweitertem Funktionsumfang von über 400 kB auf 130 kB geschrumpft und hat weniger "seltsame Nebenwirkungen". Trotzdem wünsche ich mir immer noch, ich hätte lieber bei null richtig angefangen! Ich drücke Dir die Daumen, daß Du es schaffst!
Hallo! Ich danke euch für eure großartigen Denkanstöße. Ich werde versuchen, den einen oder anderen Tipp auszuprobieren und anzunehmen. Tschüss Martin
Hallo Martin, wie andere hier schon erwähnten ist eine Doku unerlässlich. Generell sollte man sich an einen Development-Zyklus halten, z.b. den bei großen Unternehmen verwendeten V-Zyklus. Dabei erstellt man erstmal eine Software-Requirement, quasi was soll diese überhaupt können. Beschreibt das grobe Thema, und arbeitet sich in Details voran. Danach folgt die Software-Architektur und Design, sprich welche Interfaces gibt es, welche Module kommunizieren miteinander, Programm-Ablauf-Pläne, Beschreibung der State-Machine etc. Erst jetzt sollte man mit dem Programmieren beginnen, wenn alle Details abgeklärt und abgesegnet worden sind. (der Kunde kann sich danach z.b. nicht mehr herausreden wenn er sagt: "das teil soll aber auch dies machen können"). Die erstellten Requirements helfen dann auch, einen Testplan zu erstellen. Was man sich noch unbedingt abgewöhnen (oder nie angewöhnen) sollte, für alles erdenkliche sog. "Compiler-Switches" zu verwenden, also #ifdef's etc. Ich habe derzeit eine Clean-Up Study durchzuführen eines ca. 15Jahre alten Codes, und um den Ablauf verstehen zu können, bleibt mir nur noch übrig ihn Schritt-Für-Schritt zu debuggen. Da bin ich schon seit Wochen dran. Weiterhin, ist es wichtig, wirklich alles was zusammengehört, in ein Modul zu packen. Also z.B. hardwarenahe Routinen zu einem Low-Level Module, und dazu ein High-Level Module für den "ANwender". Als Tools für die DOkus empfehle ich MS Visio für Flussdiagramme etc. MS Word tut den Rest ;) Doxygen ist mit einem Add-ON namens "Graph-Viz" oder "Vis" sehr hilfreich, um einen Überblick der Beziehungen zwischen verschiedenen Dateien (C) oder Klassen (C++) zu bekommen. Es erstellt "UML-Ähnliche" grafische(!) Skizzen und erstellt eine Doku daraus, durch die man vollständig Navigieren kann. PDF, RTF, HTML etc. sehr viele Formate werden unterstützt. Was bei jeder Entwicklung nicht fehlen darf, ist eine Versionsverwaltung. Ich nehme da SubVersion, es ist Datenbankbasiert und erzeugt sehr wenig OVerhead. WIchtig ist aber, dass man wirklich nur Source Files zur Versionsverwaltung heranzieht, nicht irgendwelche Debug Files etc., da diese ja eh bei jedem COmpile neu generiert werden. Es bietet komfortable Benutzerumgebung, die sich im WindowsExplorer einbettet. Ein neues Projekt aufnehmen geschieht einfach mit rechtem Mausklick auf Ordner, und dem entsprechenden COmmando. "Auschecken" geht genauso einfach. Der Backup geht sehr einfach, die Datenbankdatei komprimieren (am besten mit bzip2) und auf CD Brennen. Für Dich würde ich folgendes VOrgehen empfehlen: Schreibe eine CleanUp-Study, also quasi einen Auftrag an Dich selbst. Danach erstelle die Requirements an die Software, ein Design und einen Testplan und sprich mit allen Mitarbeitern die irgendwie etwas mit dem Projekt zutun haben. Wenn alles umfassend abgeklärt ist, fange das Redesign an. Gehe wie oben beschrieben, modular vor. Benutze die Versionsverwaltung täglich, sprich jeden Tag einchecken. Du glaubst gar nicht wie oft man sich wünscht, einen bestimmten Schritt rückgängig machen zu können. Hoff Dir helfen diese Anregungen ein wenig. Gruß
Hallo. Schade ist, dass ich nur C kann. C++ haben wir in der Schule mal so in 2 Einheiten theoretisch durchgenommen. Darum kenne ich C++ von der Struktur her nicht wirklich. Wir machten nur so ein kleines Beispiel mit einem Baum, den man vererbte. Mehr leider nicht. Leider haben wir auch im Bereich Programmplanung usw. nur in ganz ganz groben Ansätzen was gemacht (Einmal kurz auf der Tafel). Ich war aber kein Schüler, der den Unterricht einfach so an sich vorbeilaufen ließ, besonders im Bereich Programmierung entging mir nichts. Um mal das Problem mit den globalen Variablen zu lösen. Ich habe genau das Problem, dass es bei mir immer zu viele sind. Man hat die dann ganz oben stehen und weiß eigentlich gar nicht mehr wo die eigentlich überall verwendet werden. Ein Beispiel, warum bei mir die globalen Variablen immer zuviel werden: Alle Motoren werden mittels IRQ-Timerroutine gesteuert. Um jetzt einen Motor beim Start auswählen zu können, benötige ich schon wieder eine globale Variable, damit in der IRQ-Routine die Steuerroutine für den richtigen Motor aufgerufen werden kann. Oder: Eine Timerroutine fragt im 100ms-Abstand Taster und Schalter ab oder es werden Variablen in dieser Routine hochgezählt, die für spätere Ereignisse verantwortlich sind. Z.B. Automatisches Abschalten nach einer gewissen Zeit. Hier liegt die eigentliche Unübersichtlichkeit begraben: Also das Zusammenspiel zwischen Hauptprogramm und IRQ-Routinen. Durch die IRQ-Routinen hat man das Problem, dass alles so auseinandergerissen ist. Könnt ihr mir in diesem Zusammenhang bitte Tipps geben? Tschüss Martin
Du koenntest z.B. eine Liste erstellen in die sich die Komponenten (Tastaturtreiber, Motortreiber) mit den benoetigten Aufrufintervallen eintragen koennen (Pseudocode): void keys_init(void) { timer_register_periodic_task(keys_debounce, 100); } Damit weiss dann die Interruptroutine dass die Funktion keys_debounce alle 100 ms aufgerufen werden will. Das hat u.a. den Vorteil dass du nicht in der Int.routine herumbasteln musst wenn du die Intervalle aendern oder Komponenten hinzufuegen willst. Evtl. koennte auch ein einfaches kooperatives Multitasking oder gleich ein fertiges OS sinnvoll sein (da gibt's fuer AVR auch einiges zur Auswahl).
wie waere es mit einem RTOS... ich fand das immer recht hilfreich...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.