Forum: Mikrocontroller und Digitale Elektronik Datenaustausch in Steuerungssoftware - global oder nicht?


von Martin M. (mcmaier)


Lesenswert?

Hallo,

ich habe zwar in den Foren hier schon einige Threads durchstöbert, 
konnte aber noch nichts passendes für mein Projekt finden.
Vielleicht könnt ihr mir ja weiterhelfen.

Es geht um folgendes:
Ich habe eine Motorsteuerung (basierend auf einem AT91SAM7S256) 
entwickelt.
Die Software hierfür beinhaltet einen Hauptzustandsautomaten, der die 
grundlegenden Abläufe steuert, zyklisch aufgerufen von einem 
Timer-Interrupt (Keine Angst, der Automat steht nicht in der ISR, ein 
Ringpuffer sammelt die Events, die dann vom Automat bearbeitet werden).
Außerdem enthält die Software noch kaskadierte Reglerroutinen für eine 
Motorregelung (Strom, Drehzahl, Lage) und verschiedene 
Peripherie-Funktionen, wie z.B. Encoderauswertung, EEPROM-Zugriffe, 
Lesen und Setzen von Steuerein- und Ausgängen, Datenaustausch mit 
serieller Schnittstelle,...

Die bisherige Software ist sehr globale-Variablen-lastig, d.h. es gibt 
mehrere globale Strukturen á 16 Byte, die jeweils ein Index-Byte vorne 
und eine CRC16 am Ende enthalten. Die Bytes dazwischen enthalten die 
relevanten Daten. Die Strukturen sind nach Funktionsbereich gegliedert, 
z.B. Istwerte, Merker, Einstellungen,... (siehe Beispiel)
1
typedef struct
2
{
3
  uint8_t     index;
4
  int8_t      pwmDutyCycle_percent; 
5
  int16_t     current_mA;
6
  int16_t     rotationSpeed_cHz;
7
  int16_t     linearSpeed_mmps;
8
  uint16_t    mainVoltage_mV;
9
  int16_t     currentPosition_increments;
10
  int16_t     blank;
11
  crc         checksum;
12
} MomentarySystemState_t;

Durch den festgelegten Aufbau der Strukturen können alle Daten auch 
problemlos im EEPROM gespeichert bzw. über die serielle Schnittstelle 
ausgelesen und verändert werden (Das war der Hauptgrund für diesen 
Aufbau).

Und man hat natürlich überall Zugriff auf alles... (Datenkapselung? Was 
ist das?...)

Die bisherige Software funktionert zwar gut, ist aber aus Wartungs- und 
Portierbarkeits-Sicht etwas unvorteilhaft aufgebaut (auch bekannt als 
Spagetthi-Code...).

Ich möchte das ganze modularer, übersichtlicher und leichter erweiterbar 
gestalten und habe deshalb mit einer Überarbeitung angefangen.

Allerdings komme ich an diesem Punkt nicht richtig weiter.
Da es eben viele Daten gibt auf die man von verschiedenen Punkten aus 
zugreifen können muss, bin ich hier in einer Zwickmühle:
Es wäre durch globale Variablen einfach zu bewerkstelligen, gleichzeitig 
sollte man sie aber vermeiden.

Was ist Eures Erachtens nach die beste Vorgehensweise oder das beste 
Konzept für den Datenaustausch in einer solchen Software?

Danke schon mal für eure Antworten.
Gruß, Martin.

von Volker Z. (vza)


Lesenswert?

Kapselung alá OO.
Speichere die Variablen Modul-Lokal und schreibe (Globale) Funktionen 
zum setzen und lesen.
Wenn Du es besonders hübsch machen möchtest, setze vor jeder Funktion 
ein Prefix. zB.   im Modul speed.c/.h   speed_SetRpm(int);

Beides(schneller Zugriff und Modular) geht nicht.

Volker

von Klaus W. (mfgkw)


Lesenswert?

naja, wenn man C+ nimmt, dann sind statische Elemente in Klassen schon 
mal nicht per se langsamer als herkömmliche globale Variablen.
Auch nicht, wenn man den Zugriff über Methoden abwickelt, falls diese 
inline sind.

von Anja (Gast)


Lesenswert?

Volker Zabe schrieb:
> Kapselung alá OO.
> Speichere die Variablen Modul-Lokal und schreibe (Globale) Funktionen
> zum setzen und lesen.

Das hilft aber nur wenn du diese Funktionen gar nie im Interrupt bzw. 
einer höherprioren Task aufrufst. Ansonsten beginnt die niederpriore 
Task mit schreiben wird unterbrochen, der Buffer überschrieben, und zum 
Schluß schreibt dann die niederpriore Task den Rest vom Buffer 
einschließlich (falscher) Checksumme.

Gruß Anja

von MaWin (Gast)


Lesenswert?

> Was ist Eures Erachtens nach die beste Vorgehensweise

Ob OO oder nicht:

Man baut einen Daten-Store auf, den man durch Funktionen befragt. Diese 
Funktionen übernehmen gleich die Synchronisation bei mehreren durch 
Interrupts ausgelösten gleichzeitig ablaufenden Threads durch Locking.

Falls Daten unzertrennbar geliefert werden müssen (beispielsweise 
"elapsed_time" + "remaining_time" muss "cycle_time" ergeben) sollten die 
zusammengehörigen Werte gleichzeitig geliefert werden damit sie bestimmt 
konsistent sind.

von Volker Z. (vza)


Lesenswert?

Hallo Anja,
das Problem hat er auch bei globalen Variablen.
Im Gegenteil, per Funktionsaufruf kann man den Zugriff synchronisieren 
(im einfachsten Fall durch sperren des Interupts am Anfang und freigeben 
am Ende Der Funktion). Dies ist übersichtlicher(modularer, weniger 
Fehler trächtig), als bei jedem Zugriff in jedem Modul dies zu tun.

Gruß Volker

von Martin M. (mcmaier)


Lesenswert?

Hallo zusammen,

danke für Eure Anregungen.
Werd's bei der Umsetzung berücksichtigen.

Gruß, Martin.

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.