Forum: Compiler & IDEs C++ Programm Design


von A. Z. (donvido)


Lesenswert?

Hallo miteinander,
Kurz zu mir:
Ich habe Maschinenbau mit Schwerpunkt Regelungstechnik studiert und 
programmiere privat des Programmieren wegens einen STM32F103 in C++.
Dabei quäle ich mich seit geraumer Zeit wie ich das ganze am besten 
designe.
Soll heißen ich habe die Schnittstellen zwischen den Klassen jetzt 
mehrere Male umgeschrieben um dann immernoch unzufrieden zu sein.

Was mache ich:
Ich konfiguriere und lese verschiedene Sensoren via I2C und SPI aus.
Die Daten werden gefiltert und verarbeitet, das ganze läuft durch 
verschiedene Regler und am Ende soll ein PWM-Signal ausgegeben werden.
Die verschiedenen Konfigurationen und Parameter sollen im Flash 
abgelegt/gespeichert werden und via CLI konfigurierbar sein.

Für die verschiedenen Peripherien und Sensoren habe ich bereits separate 
Klassen angelegt, die auch das machen, was sie sollen.

Die Frage ist jetzt, wie schiebe ich jetzt jeder Klasse die Daten zu, 
die sie braucht?

Ich habe schon überlegt eine "Master-Klasse" zu erstellen in der ich 
alle benötigten Klassen referenziere.

Alternativ packe ich alles in eine Struktur
1
struct Alle_Variablen {
2
struct Systemvariablen sysvars;
3
struct Parameter params;
4
}
und reiche daraus alles an die Klassen.

Wichtig ist mir, dass das ganze einfach erweiterbar ist und nicht jedes 
Mal komplett umgeschrieben werden muss, nur weil ein neuer Sensor 
hinzukommt.
Übersichtlich und lesbar solls natürlich auch bleiben.

Wie würdet ihr das machen.
Könnt ihr vlt passende Literatur empfehlen?


Vielen Dank und
schöne Feiertage

von J. F. (Firma: Père Lachaise) (rect)


Lesenswert?

A. Z. schrieb:
> Für die verschiedenen Peripherien und Sensoren habe ich bereits separate
> Klassen angelegt, die auch das machen, was sie sollen.

Wie sieht denn deine Klassenarchitektur aus? Wenn du doch eine 
Basisklasse für Sensoren erstellt hast und einen neuen Sensor dazu 
implementierst, hast du doch kein Problem. Wie steht es um deine 
Kenntnisse zu Design Pattern? Was hast du bis jetzt?

/edit: welches OS? Benutzt du ein RTOS?

: Bearbeitet durch User
von A. Z. (donvido)


Lesenswert?

Ich habe einen eigenen scheduler geschrieben mit dem ich meine 
unterschiedlichen Tasks ganz gut timen kann.

Sensoren hinzufügen ist ja wirklich nicht schwer. Für die Sensoren auf 
dem I2C-Bus habe ich eine Basisklasse, die sich um die Kommunikation 
kümmert.
Da die einzelnen Sensoren aber sehr unterschiedlich sein können, stellt 
sich eher die Frage, wie ich die Schnittstelle zwischen den 
nachfolgenden Klassen baue.
1
class i2c_sensor{
2
  protected:
3
    I2C* port;
4
    uint8_t addr;
5
6
    uint8_t buffer[32];
7
8
    uint8_t read_register(uint8_t reg_addr);
9
    void read_registers(uint8_t reg_addr, uint8_t* data, bool wait, uint8_t length);
10
    void write_register(uint8_t reg_addr, uint8_t data);
11
12
  public:
13
    i2c_sensor(I2C* i2c_port, uint8_t addr);
14
};
15
16
17
class Sensor1: public i2c_sensor{
18
  private:
19
    sensor_cfg configuration;
20
21
    int8_t selfTest(void);
22
    void reset(void);
23
    void wakeUp(void);
24
25
    void set_CONFIG(config_e byte, bool set);
26
27
    void get_ACCEL(int16_t *data);
28
    void get_GYRO(int16_t *data);
29
30
  public:
31
    Sensor1(I2C* i2c_port);
32
33
    int8_t init(void);
34
    void update(void);
35
    void event_handler(void);
36
37
    void get_values(int16_t* values);
38
39
    void calibrate(void);
40
    void set_configuration(sensor_cfg* cfg_data);
41
    void get_configuration(sensor_cfg* cfg_data);
42
};

Design Pattern sieht eher mau aus bei mir.

: Bearbeitet durch User
von J. F. (Firma: Père Lachaise) (rect)


Lesenswert?

Mir ist unklar was du genau möchtest. Als mögliche Schichten käme so 
etwas in Frage:

High Level (GUI?)
----------------
Daten Handling
----------------
Mediator Schicht (DatenFluss nach oben)
----------------
Low Level Treiber

Hast du eine GUI? Im Prinzip machst du ja nicht wirklich viel: Daten 
auslesen, verarbeiten, ausgeben. Probier doch einfach mal eine 
Möglichkeit bis zum Ende durch, dann siehst du doch schnell ob dir das 
gefällt. Einfach mal machen :-)

von J. F. (Firma: Père Lachaise) (rect)


Lesenswert?

Vergessen habe ich noch den groben Ablauf: die Mediatoren lesen die 
Sensoren zyklisch aus (z.B. in einem Thread) und melden die Daten an die 
Datenschicht. Haben sich diese im Vergleich zu den alten Werten um ein 
gewisses Delta geändert, werden alle Komponenten benachrichtigt die sich 
vorher angemeldet haben. Dann Verarbeitung und Ausgabe wie beliebt.

von A. Z. (donvido)


Lesenswert?

J. F. schrieb:
> Mir ist unklar was du genau möchtest.

Ein sinnvolle übersichtliche Strukturierung wär nicht schlecht.
Aber vielleicht weiß ich auch einfach selber nicht, was ich will. =/

> Hast du eine GUI?

Noch nicht. Aber vlt kommt noch eine.


> Probier doch einfach mal eine
> Möglichkeit bis zum Ende durch, dann siehst du doch schnell ob dir das
> gefällt. Einfach mal machen :-)

Das ist ja das Problem, ich bin jedes Mal unzufrieden und fange von 
vorne an.

von Dumdi D. (dumdidum)


Lesenswert?

Ein struct ist eine Klasse in der alles public ist.

von Sal. (Gast)


Lesenswert?

A. Z. schrieb:
> Ich habe schon überlegt eine "Master-Klasse" zu erstellen in der ich
> alle benötigten Klassen referenziere.

Du musst nicht unbedingt alles in OOP, Klassen und Vererbung zwingen. In 
den letzten Jahren setzt man nicht mehr so sehr auf OOP und Vererbung, 
insbesondere in den neueren Sprachen wie Rust, Go, Nim usw.

Siehe etwa

https://content.pivotal.io/blog/all-evidence-points-to-oop-being-bullshit

von Mikro 7. (mikro77)


Lesenswert?

A. Z. schrieb:
> Die Frage ist jetzt, wie schiebe ich jetzt jeder Klasse die Daten zu,
> die sie braucht?

KISS. https://de.wikipedia.org/wiki/KISS-Prinzip

Implementiere es für die konkrete Anforderung. Nicht für "alle 
möglichen" Erweiterungen.

Falls du dich in klassiche Design Patterns einarbeiten möchtest, dann 
nimm bspw. GoF als Referenzwerk. 
https://en.wikipedia.org/wiki/Design_Patterns

Wie bereits oben geschrieben, die Lösung gibt es meist nicht. Früher 
wurde Vererbung gepredigt. Heute ist das fast schon Teufelswerk.

von Carl D. (jcw2)


Lesenswert?

Dumdi D. schrieb:
> Ein struct ist eine Klasse in der alles public ist.

... in der der Defaultwert der Sichtbarkeit "public" ist.

Bei class aber "privat". Aber nicht verhindert in einer struct 
"protected:"/"private:" zu schreiben, genauso wie eine class 
"public:"/"protected:" Bereice haben kann.

von Andreas H. (ahz)


Lesenswert?

Sal. schrieb:
> Du musst nicht unbedingt alles in OOP, Klassen und Vererbung zwingen. In
> den letzten Jahren setzt man nicht mehr so sehr auf OOP und Vererbung,
> insbesondere in den neueren Sprachen wie Rust, Go, Nim usw.
>

 <FLAME>
Der TO fragt konkret zu einem OO Problem und Dein Vorschlag ist Rust, 
Go, Nim usw. auf einem Controller?
Warum habe ich da den Eindruck dass Du noch nie eine embedded 
Application geschrieben hast, die komplexer als Blinky war und die dann 
ein Team mehrere Jahre supporten muss?
Ist Ansi-C irgendwie an Dir vorbei gegangen?

> Siehe etwa
>
> https://content.pivotal.io/blog/all-evidence-points-to-oop-being-bullshit

Hast Du den Blog gelesen?
Was John Baker da erklärt ist lediglich, dass funktionale Programmierung 
(teilweise) Vorteile gegenüber OO hat.

Leider rennt er (wie so oft bei diesen hirnrissigen Diskussionen) in das 
"klassische" Messer:
"State is not your friend, state is your enemy." ist sicher korrekt. 
Aber die Annahme dass das bei funktionaler Programmierung besser ist ist 
falsch.
Natürlich sind (echte) Funktionen stateless.
Aber der State ist Teil des Systems das Du bearbeitest, nicht der 
Programmiersprache. Das musst Du immer irgendwie handhaben.

Das dickste LOL war aber das Zitat "Java is the most distressing thing 
to happen to computing since MS-DOS. — Alan Kay".
Da zielt Alan Kay sicher auf Java als Sprache, nicht auf OO allgemein. 
Ist bei Bakers Blog also lustig aber nutzlos.

(Hausaufgabe für Dich: Wer ist Alan Kay?).

 </FLAME>

von Vincent H. (vinci)


Lesenswert?

Wenn mich wer fragt was OOP ist, dann denk ich als allererstes an die 
Kapselung von Funktionen und Daten. Also eigentlich genau das, was du 
nicht machst...?

Das ganze Design klingt für mich viel zu komplex für eigentlich recht 
simple Dinge. Wenn ich einen Sensor hab, dann möcht ich mir von dem die 
Daten holen und nicht von irgendeiner "Datenschicht".

von A. Z. (donvido)


Lesenswert?

Mikro 7. schrieb:
> Falls du dich in klassiche Design Patterns einarbeiten möchtest, dann
> nimm bspw. GoF als Referenzwerk.
> https://en.wikipedia.org/wiki/Design_Patterns
>
> Wie bereits oben geschrieben, die Lösung gibt es meist nicht. Früher
> wurde Vererbung gepredigt. Heute ist das fast schon Teufelswerk.

Design Patterns ist ja vlt schonmal ein Anfang.
Ich will auch definitiv nicht alles in OOP pressen, wenn es nicht sein 
muss.

Vincent H. schrieb:
> Wenn mich wer fragt was OOP ist, dann denk ich als allererstes an
> die
> Kapselung von Funktionen und Daten. Also eigentlich genau das, was du
> nicht machst...?

Ich finde auch, dass man die einzelnen Peripherien eines µC ganz 
wunderbar als Klassen darstellen kann. Kommt hier vielleicht nicht so 
rüber.

Nochmal zurück zur Frage, wie ich am besten die Daten zwischen den 
Klassen hin und her schiebe.
In meinem Codebeispiel oben kann man ja schon sehen, dass der Sensor die 
I2C-Klasse als Referenz bekommt
1
class i2c{
2
public: 
3
write_data(uint8_t addr,uint8_t data);
4
}
5
6
class sensor{
7
private:
8
i2c* port;
9
public: 
10
uint16_t get_data();
11
}
Das klappt soweit ganz gut. Vor allem auch, weil ich die I2C Klasse mit 
mehreren Sensoren verwenden kann.

Wenn ich jetzt aber die Sensoren auswerten möchte, habe ich ja nicht 
vor, diese noch anders zu verwenden. Macht es da Sinn, sowas zu bauen:
1
class sensor{
2
public: 
3
uint16_t get_data();
4
}
5
6
class auswertung{
7
private:
8
sensor sensor1;
9
sensor sensor2;
10
public: 
11
float ergebnis();
12
}

oder eher sowas
1
uint16_t data=sensor1.get_data();
2
3
auswertung.intput(data);
4
float ergebnis=auswertung.berechnung();

von Andreas H. (ahz)


Lesenswert?

A. Z. schrieb:
> Die Frage ist jetzt, wie schiebe ich jetzt jeder Klasse die Daten zu,
> die sie braucht?
>

Huhu

Das sieht so aus, als ob Dir da die Grundlagen für OO-Design (und das 
ist nicht das Gleiche wie OO-Programmierung) fehlen. Also wie man eine 
"Aufgabe" so zerlegt, dass man sie dann gut implementiert, getestet & 
gewartet bekommt.

>
> Wie würdet ihr das machen.
> Könnt ihr vlt passende Literatur empfehlen?

Problem dabei ist, dass man da immer noch am rumstochern ist, was nun in 
der Praxis brachbar ist und was nur als "akademischer Ausrutscher" 
taugt.

Der Klassiker schlechthin dürfte das sein:

Grady Booch,‎ Robert Maksimchuk,‎ Michael Engle
"Object-Oriented Analysis and Design with Applications"
(Addison-wesley Object Technology Series)

(Kauf da bloss nicht die deutsche Übersetzung. Die fand ich 
"grusellig".)


Das GOF Buch wurde oben schon von mikro77 erwähnt (und ist wirklich 
unverzichtbar):

Erich Gamma,‎ Richard Helm,‎ Ralph E. Johnson,‎ John Vlissides
"Design Patterns. Elements of Reusable Object-Oriented Software"
(Addison-wesley Professional Computing Series)

Muss man nicht gleich haben/lesen. Ist eher ein Nachschlagewerk und ALLE 
Pattern findest Du jetzt auch schon bei Wikki. Es wird allerdings SOO 
oft refenziert (z.B. "GOF 127" ist das Singleton pattern), dass man es 
immer wieder mal braucht.


Allgemein hast Du immer das Problem, dass OOD heute meist im Kontext der 
aktuellen OO-Sprachen erklärt wird. Da bleibt leider gelegentlich das 
eine oder andere KONZEPT hinter der Implementierung verborgen.

Wenn Du Dich da grundlegend aufschlauen willst noch zwei Empfehlungen 
(für die ich immer verprügelt werde):

Chamond Liu
"Smalltalk, Objects and Design"
(iUniverse.com)


Kent Beck
"Smalltalk best practice patterns"
(Prentice Hall)

Vorteil & Nachteil beider Bücher: Sie beziehen sich weitgehen auf 
Smalltalk.
Ich kenne allerdings keine Sprache mit der man besser die "Grundideen" 
von OO lernt.
Ausserdem machts auch noch viel Spass, weil Smalltalk ein Dialogsystem 
ist, man also sehr interaktiv arbeitet. (Smalltalk taugt aber nicht 
wirklich für Embedded.)

Beide Bücher gehen wenig auf Smalltalk selbst ein sondern mehr darauf, 
wie man objectorientiert Programme aufbaut.

Liu hat auch einige Vergleiche zu C++ an denen man die Unterschiede in 
den Implementierungsideen gut sehen kann.

Beck's pattern sind KEINE design pattern sondern "Tipps" wie man 
(eigentlich triviale) Sachen sinnvoll macht (z.B. gute Variablennamen). 
Auch unabhängig von Smalltalk lesenswert (ausser man betrachtet sich 
selbst als Überflieger).

Das sollte Dich dann über XMas erst mal beschäftigen ;-)

/regards

Beitrag #5252720 wurde von einem Moderator gelöscht.
von Sheeva P. (sheevaplug)


Lesenswert?

Vincent H. schrieb:
> Wenn mich wer fragt was OOP ist, dann denk ich als allererstes an die
> Kapselung von Funktionen und Daten. Also eigentlich genau das, was du
> nicht machst...?
>
> Das ganze Design klingt für mich viel zu komplex für eigentlich recht
> simple Dinge. Wenn ich einen Sensor hab, dann möcht ich mir von dem die
> Daten holen und nicht von irgendeiner "Datenschicht".

Genau. Mein Sensor hätte ein einfaches Interface: einen Konstruktor, der 
eine Konfiguration nimmt und mit read() ein Objekt zurück gibt:
1
template<typename Config, typename Value>
2
class Sensor {
3
public:
4
  Sensor(Config Cfg): cfg(cfg);
5
  Value read(void);
6
protected:
7
  Config cfg;
8
};

von Sheeva P. (sheevaplug)


Lesenswert?

A. Z. schrieb:
> Nochmal zurück zur Frage, wie ich am besten die Daten zwischen den
> Klassen hin und her schiebe.

Im Idealfall: gar nicht. Die Idee von OOP ist, daß Du Instanzen von 
Sensoren übergibst und die Empfänger-Funktionen oder -Methoden selbst 
wissen, wie sie die Daten dieser Sensoren auslesen und verarbeiten 
können.

Beitrag #5252751 wurde von einem Moderator gelöscht.
von Dumdi D. (dumdidum)


Lesenswert?

Carl D. schrieb:
> Dumdi D. schrieb:
>> Ein struct ist eine Klasse in der alles public ist.
>
> ... in der der Defaultwert der Sichtbarkeit "public" ist.
>
> Bei class aber "privat". Aber nicht verhindert in einer struct
> "protected:"/"private:" zu schreiben, genauso wie eine class
> "public:"/"protected:" Bereice haben kann.

Ja. Ich wollte nur darauf hinaus das die vom TE genannte Alternativen 
'Masterklasse' oder 'struct' sich jetzt nicht zwangslaeufig 
unterscheiden.

Beitrag #5252975 wurde von einem Moderator gelöscht.
von Christopher J. (christopher_j23)


Lesenswert?

A. Z. schrieb:
> Sensoren hinzufügen ist ja wirklich nicht schwer. Für die Sensoren auf
> dem I2C-Bus habe ich eine Basisklasse, die sich um die Kommunikation
> kümmert.
> Da die einzelnen Sensoren aber sehr unterschiedlich sein können, stellt
> sich eher die Frage, wie ich die Schnittstelle zwischen den
> nachfolgenden Klassen baue.

Manchmal ist weniger mehr. Mach dir nicht zu viele Schichten zwischen 
deinem I2C-Bus und deinem Sensor. Ich meine die ideale Anzahl an 
Schichten zwischen I2C-Bus und Sensor ist 0. Deinem Bus spendierst du 
dann ein ganz einfaches Interface, in etwa
1
int transfer(const uint8_t *send, unsigned send_len, uint8_t *recv, unsigned recv_len);
d.h. eine Möglichkeit Daten auf den Bus zu senden. In deine 
Sensor-Klasse packst du dann die Logik, wie welches Register gelesen 
oder geschrieben werden kann, wobei dich ja am Ende eigentlich nur noch 
die Daten interessieren, d.h. bei einem Beschleunigungssensor 
entsprechend die Beschleunigungsdaten, also get_accel().

Andreas H. schrieb:
> Sal. schrieb:
>> Du musst nicht unbedingt alles in OOP, Klassen und Vererbung zwingen. In
>> den letzten Jahren setzt man nicht mehr so sehr auf OOP und Vererbung,
>> insbesondere in den neueren Sprachen wie Rust, Go, Nim usw.
>>
>
>  <FLAME>
> Der TO fragt konkret zu einem OO Problem und Dein Vorschlag ist Rust,
> Go, Nim usw. auf einem Controller?
Sal. ging es aber auch wohl offensichtlich nicht darum dem TO Go oder 
Rust anstelle von C++ zu empfehlen, sondern zu zeigen,dass 
implementation inheritance per se nicht besonders prickelnd ist, weshalb 
eben modernere Sprachen (wie etwa Rust oder Go) gänzlich darauf 
verzichten. Trotzdem sind diese Sprachen (jedenfalls meiner Meinung 
nach) immer noch objektorientiert. Go bietet sogar interface 
inheritance.

Andreas H. schrieb:
> Das GOF Buch wurde oben schon von mikro77 erwähnt (und ist wirklich
> unverzichtbar):
>
> Erich Gamma,‎ Richard Helm,‎ Ralph E. Johnson,‎ John Vlissides
> "Design Patterns. Elements of Reusable Object-Oriented Software"
> (Addison-wesley Professional Computing Series)

Dazu (aus Wikipedia):
> "Program to an 'interface', not an 'implementation'." (Gang of Four 1995:18)

> Composition over inheritance: "Favor 'object composition' over 'class 
inheritance'." (Gang of Four 1995:20)

Weiterer Lesestoff:
http://www.blinkingcaret.com/2016/04/13/composition-superior-inheritance/

von Sal. (Gast)


Lesenswert?

Andreas H. schrieb:
> Der TO fragt konkret zu einem OO Problem und Dein Vorschlag ist Rust,
> Go, Nim usw. auf einem Controller?

Nein -- ich hatte nur darauf hingewiesen, dass man heute nicht mehr mit 
Gewalt versucht alles mit OOP, Klassen und Vererbung zu erschlagen. Denn 
ich hatte den Eindruck, dass der Threadstarter eben dieses versucht. Wie 
viele "Fachinformatiker" die im wesentlichen nur Java gelernt haben. Mir 
war OOP in den frühen 90er Jahren auch als ultimative Lösung für alles 
verkauft worden, u.a. auch von Bruce Eckel in seine "Thinking in ..." 
Büchern. Und da ich Rust und Nim erwähnt hatte -- natürlich kann man 
damit auch gut Mikrocontroller programmieren, jedenfalls grundsätzlich. 
Aber darum ging es hier nicht.

von Genervter Entwickler (Gast)


Lesenswert?

Ja, im Hardware- und Steuerungsbereich ist das in der Tat gar nicht so 
einfach, ordentliche Abstraktionen zu finden und den Code gut zu 
strukturieren.

Die Literatur beschäftigt sich fast ausschließlich nur mit 
"Kindergarten"-Systemen. D.h. selten mit mehr als ein Dutzend IOs. Reale 
Systeme sind aber viel komplexer. Kleinere Geräte/Maschinen/Anlagen 
haben ganz schnell viele hundert IO-Punkte, von einzelnen Bits bis zu 
komplexen Messwerten.

Das andere Extrem in der Literatur/Forschung/Lehre ist, auf ein 
Minimalproblem mit Kanonen zu schießen, d.h. um eine Lampe ein- und 
auszuschalten wird ein extrem komplexes Framework bemüht mit völlig 
überzogenen Hardware-Anforderungen.

Der schwierigste Teil besteht meiner Meinung darin, dass die ganzen 
Hardware-Komponenten untereinander komplexe Abhängigkeiten haben und 
diese in Software irgendwie nachgebildet werden müssen. Z.B. wenn Sensor 
A irgendwas meldet, sind die Werte von Sensor B ungültig.
Somit ist z.b. das skalierte und gefilterte Messergebnis vom Sensor B 
plötzlich vom Sensor A auch in der Software abhängig. Dieses Geflecht 
möchte man in Software eigentlich nicht haben. Dummerweise muss man 
aber. Und das macht meiner Erfahrung nach solche Software erstaunlich 
komplex.

Wie man es gut macht? Keine Ahnung. Ich suche nun schon seit Jahren nach 
Antworten. Erschwerend kommt hinzu, dass es im Controller- und 
Steuerungs-Bereich keinen lebendigen Austausch der Entwicklern 
untereinander gibt. Keiner will etwas von seiner Erfahrung preisgeben. 
Letztendlich würde aber jeder vom Austausch profitieren.

Beitrag #5253616 wurde von einem Moderator gelöscht.
von Dumdi D. (dumdidum)


Lesenswert?

Vincent H. schrieb:
> Wenn ich einen Sensor hab, dann möcht ich mir von dem die Daten holen
> und nicht von irgendeiner "Datenschicht"

Der Vorteil einer Datenschicht ist aber, das simulierte Daten injiziert 
werden koennen, und Du dann Dein Programm ordentlich testen kannst.

Beitrag #5253726 wurde von einem Moderator gelöscht.
von MitLeserin (Gast)


Lesenswert?

@mod: bitte unvollständigen post löschen
***************************************

Genervter Entwickler schrieb:
> Der schwierigste Teil besteht meiner Meinung darin, dass die ganzen
> Hardware-Komponenten untereinander komplexe Abhängigkeiten haben und
> diese in Software irgendwie nachgebildet werden müssen.

Mit Templates können Abhängigkeiten implementiert werden ...

class Display {};
class Timer {};


template <class display, class timer>
class Sensor {

  do_something() {
    display::display_var = 10;
    timer::timer_var=99;

    display::display_functions();
    timer::timer_functions();
  }

};

typedef Display display7x8;
typedef Timer timer_sec;

typedef Sensor<display7x8, timer_sec> sensor;

int main(){ sensor::do_something(); }

Beitrag #5254107 wurde von einem Moderator gelöscht.
Beitrag #5254419 wurde von einem Moderator gelöscht.
Beitrag #5255245 wurde von einem Moderator gelöscht.
Beitrag #5256275 wurde von einem Moderator gelöscht.
Beitrag #5257312 wurde von einem Moderator gelöscht.
Beitrag #5258498 wurde von einem Moderator gelöscht.
Beitrag #5259476 wurde von einem Moderator gelöscht.
Beitrag #5259478 wurde von einem Moderator gelöscht.
von c++ auch für embedded (Gast)


Lesenswert?

Martin G. schrieb im Beitrag #5259478:
> C++ kommt mir wie ein zusammengemurkstes Flickwerk vor: Weil das
> Pflaster nicht hält haut man nen Nagel rein, weil sich dann aber das
> Pflaster darunter trotzdem löst spachtelt man Gips drüber.

Genau, C++ flickt die großen C Löcher. Jetzt haben auch die nur Cler den 
Nutzen von richtigen Compilern.

Wer nichts mit Typsicherheit, Datenkapselung, Vererbung anfangen kann, 
bleibt ein Frikeler. Im embedded Bereich muss man nicht den ganzen 
Standard nutzen. Man kann sich und den Nachkommen aber das Leben 
erleichtern.

=> Der Mensch sieht und erkennt Objekte überall in seinem Umfeld. Warum 
soll er dann nicht seine Probleme mit Objekten lösen?

von Peter D. (peda)


Lesenswert?

J. F. schrieb:
> Im Prinzip machst du ja nicht wirklich viel: Daten
> auslesen, verarbeiten, ausgeben.

Ich benutze auch sehr gerne dieses EVA-Prinzip.
Dazu trenne ich die Tasks komplett, damit ich nicht unnütz irgendwo 
warten muß. Z.B. müßte ich ja sonst auf einen DS18B20 min 750ms warten, 
ehe ich den Meßwert habe.
Eine Task liest also alle Sensoren, Tasten, Drehgeber zyklisch ein und 
legt die Werte im RAM ab.
Die andere Task macht die ganze Verarbeitung und legt die Ausgabewerte 
wieder in einem Shadow-RAM ab.
Die 3.Task gibt dann alles aus, entweder zyklisch oder mit einem 
Änderungsflag.

von P. P. (Gast)


Lesenswert?

Das Problem würde ich nicht mit OO erschlagen wollen, dafür gibt's 
geeignete Design Patterns.
Schau dir mal z.B. das Publish-Subscriber-Pattern an:
https://en.wikipedia.org/wiki/Publish–subscribe_pattern

Das lässt sich vereinfacht auch auf Funktionsebene implementieren, so 
dass es auch auf einem Mikrocontroller kaum zusätzlichen Platz und 
Performance frisst. Dafür bekommst du aber die Flexibilität für deine 
Sensoren, die du brauchst.

Gruß Pirx

Beitrag #5273216 wurde von einem Moderator gelöscht.
Beitrag #5273217 wurde von einem Moderator gelöscht.
von A. S. (Gast)


Lesenswert?

Für embedded mit realer Umwelt-Interaktion ist es wichtig, sich von der 
Elektronik und Bussystem zu lösen.

Dein relevanten Objekte sind eine "Temperatur am Fenster 3" oder 
"Lichtmenge am Sessel" oder Lüfteransteuerung

Ob die per I2C oder SPI angebunden sind, sind Implementierungsdetails 
eines HAL. Verschwende darauf nicht allzuviel Architekturblut sondern 
Sorge dafür, dass sie angemessen oft aktualisiert werden undi dafür 
gleichartige Funktionen bzw. Kommandos verwendet werden.

von Feldstecher (Gast)


Lesenswert?

Wie ich es machen würde (Ebenfalls Maschinenbauer mit Vertiefung RT):

- Erstmal C++ deinstallieren und Pascal hernehmen:-)
- Jede Schnittstellen bekommt ihre eigene Klassen (und auch Datei).
- Jeder Sensortyp bekommt seine eigene Klasse (und auch Datei). Diese 
sind in in der Anwendung angemessenen typischen Bereichen 
parametrierbar.
- Eine Klasse/Datei "Sensoren" zur Kapselung aller Sensoren und eine 
Datei "Aktuatoren". Dort werden die einzelnen Sensoren/Aktuatoren 
initialisiert. Hier wird auch bspw. die Instanz "ServoHöhenruder" einer 
Klasse "Servo" deklariert und auf den entsprechenden Kanal gelegt. Der 
Kanal kann in einer Datei "HardwareKonstanten" definiert sein. Bei 
Servos sind individuelle Maximalwerte sinnvoll, das kann entweder bei 
der Initialisierung übergeben werden, oder es werden in der 
Aktuatoren-Klasse Funktionen bereitgestellt, die diese berücksichtigen, 
Skalierungen können hier sinnvoll sein. Z.B. eine Funktion 
"SetHöhenruder" könnte als Übergabewert den Bereich -1 bis 1 haben, und 
entsprechend der Servoklasse den umgerechneten PWM-Wert von 0,7 bis 0,8 
übergeben. Oder die Funktionen "LandeklappeAktiv" und 
"LandeklappeInaktiv" werden auch hier definiert.
- In einer wieder anderen Klasse (und Datei) findet die Ablaufsteuerung 
statt, durch die Abstrahierung ist der Hardwarezugriff hier nun sehr 
einfach und greift direkt nur auf die Klassen "Sensoren" und 
"Aktuatoren" zu.
- Für die per Fernzugriff veränderbaren Parameter gibts wieder eine 
eigene Datei. Auf diese greiffen nur die "Sensoren" und 
"Aktuatoren"-Klasse zu, bzw. die Reglerklasse. Aber nicht die 
Servoklasse selber etc.

Beitrag #5279642 wurde von einem Moderator gelöscht.
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.