Forum: Mikrocontroller und Digitale Elektronik C++ Objektorientierung ?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Reiner D. (dollreiner)


Lesenswert?

Nachdem ich bei der Frage nach " 1<<PA3 " gründlich abgewatscht wurde, 
dabei aber auch reichlich gelernt habe, trau ich mich noch ein Problem 
anzusprechen.

Ich programmiere an einem Modellbauprojekt auf dem ArduinoMega256 in C++ 
unter Code::Blocks.

Es gibt eine main-Routine, an der ein paar ISR dranhängen, die z.b. 
Ereignisse zählen (Inkremente usw.)

In der main werden ein paar Klassen instanziert, z.b. die Klasse 
"segel", die Objekte sind dann "fock", "gross", "besan" usw..
Die Methoden darin heißen dann "bergen", "setzen" und sowas.

Ich würde gerne die genannten Objekte (z.b. fock) nicht in der main, 
sondern in einem anderen Objekt (z.b. "mannschaft" oder so) 
instanzieren, um die main übersichtlicher zu machen. (Anschaulich : die 
main ist der Skipper, die Mannschaft sind die Matrosen, und erst die 
machen die Arbeit..)

Mein Problem :
Wenn ich ein Objekt nicht in der main, sondern in einem anderen Objekt 
erzeuge, kann das nicht auf die ISR-Werte aus der main zugreifen (oder 
andersrum).

Ich hoffe, mich einigermaßen verständlich ausgedrückt zu haben.

Was muß ich lernen, um das zu lösen ??

von Oliver S. (oliverso)


Lesenswert?

Reiner D. schrieb:
> Ich hoffe, mich einigermaßen verständlich ausgedrückt zu haben.

Nein. Selbst in C++ hängen ISRs nicht an main, sondern sind völlig 
losgelöste Funktionen.

> Was muß ich lernen, um das zu lösen ??

Eine beliebige Programmiersprache.

Aber zeig doch mal einen beispielhaften Code, der deine Probleme 
veranschaulicht.

Oliver

: Bearbeitet durch User
von Reiner D. (dollreiner)


Lesenswert?

Schwierig, ist viel Code...
Hier die letzten Zeilen der main, und der Beginn der ersten ISR.
Die ISR sind in der Datei main integriert, hängen unten dran (nicht im 
Programmkörper von main).
In der mit "#####" gekennzeichneten Zeile wird ein Attribut der Klasse 
"segel", instanziert im Objekt "Gross", beschrieben. Das geht so nicht, 
wenn die Instanzierung von Gross nicht in der main, sondern einem 
anderen Objekt, geschieht.

Was tun ?






         }//ende der 10hz-task in der "while 1" -main-schleife
    };//ende "while 1" - schleife innerhalb main
    return 0;

}//ende von main 
********************************************************

//Hardwarebelegung :
//Timer 0 : PPM-Generator (für Servo und RC-Winden)
//Timer 1 : 10HZ-Generator für NPRM-Scheduler
//Timer 2 : PWM-Generator (A für Maschine )
//Timer 3 : Zähler für PPM-Decoder (vom RC-Sender)
//Timer 4 : PPM für Winden in Gruppen
//Timer 5 : Entprellung der Inkrementgeber
//UART0 : USB zum PC
//UART1 : GPS

ISR (PCINT0_vect)       //Inkremente aus Gruppe 0
{
    if (int_done0 == 0)  //falls das ein neuer interrupt ist
    {
        TCNT5 = 0;      //Timer 5 auf Null
        int_done0 = 1;   //merk dir, jetzt war ein signal
    }
    else
    {
        if (TCNT5 > 500)            // letztes Signal länger als 32ms 
her ?
        {
            Gross.KlauInkrement ++ ;   //############################
            Besan.KlauInkrement ++ ;
            int_done0 = 0;
        }
    }

}

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Ich hoffe, mich einigermaßen verständlich ausgedrückt zu haben.

leider nicht, nein.

Reiner D. schrieb:
> Das geht so nicht,
> wenn die Instanzierung von Gross nicht in der main, sondern einem
> anderen Objekt, geschieht.

hä?

Alle Salamischeiben liefern, bitte.

von Reiner D. (dollreiner)


Lesenswert?

Fällt mir echt schwer, das sauber zu beschreiben.

Normalerweise referenziere (instanziere) ich Objekte in der main.
Deren Methoden kann ich dann aufrufen, die Attribute zugreifen.

Von der Klasse "segel" gibts z.b. zwei Objekte in der main : Gross und 
Fock.
Ich kann jetzt in der main "Gross.setzen()" aufrufen, und 
"Fock.setzen()" .
Als Wert dafür brauche ich in "setzen" einen Inkrementzähler , der in 
einer ISR an der main geschrieben wird. den kann ich z.b. mit 
"Gross.Klauinkrement"
in der ISR schreiben und in "Gross.setzen()" lesen.
Alles prima.

Jetzt möchte ich eine weitere Hierarchieebene einziehen, und die 
Segelbedienung nicht in der main machen. Ich schreibe ein Objekt 
"Deckshand",
dass die ganze Arbeit tun soll, main setzt bloß noch wenige Befehle an 
Deckshand.
Dazu muß ich "segel" in "deckshand" instanzieren, nicht mehr in der 
main.
(Bildlich : der Skipper rührt die Segel nicht an, er befiehlt bloß)

Aber : das Objekt "Gross", das jetzt in dem Objekt "deckshand" 
instaziert wurde, kann nicht auf die ISR-Variablen zugreifen !

Als, was tun (außer die Struktur ändern ;-) ??

von Oliver S. (oliverso)


Lesenswert?

Reiner D. schrieb:
> Was tun ?

Wie ich schon schrieb, eine Programmiersprachen lernen. In dem Fall C 
und/oder C++.

Die Aufteilung von Sourcecode auf verschiedene Dateien und in 
Source/headerdateien sind die absoluten Basics. Die sollte man kennen.

https://de.wikibooks.org/wiki/C-Programmierung:_Eigene_Header

Oliver

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Fällt mir echt schwer, das sauber zu beschreiben.

Nö. Ist ganz einfach. Sourcecode in den Anhang. Fertig.

Reiner D. schrieb:
> Aber : das Objekt "Gross", das jetzt in dem Objekt "deckshand"
> instaziert wurde, kann nicht auf die ISR-Variablen zugreifen !

Tut mir leid, als Prosa ist das vollkommen unverständlich.

Und was das mit Objektorientierung zu tun haben soll, verstehe ich auch 
nicht.

von Stefan F. (Gast)


Lesenswert?

In welcher Datei eine ISR liegt, spielt keine Rolle. Jedenfalls sind ISR 
keine C++ Methoden. Wenn ISR auf Objekte zugreifen, brauchst du Zeiger 
auf diese Objekte, welche für die ISR erreichbar sind.

Für solche global verfügbaren Dinge benutze ich gerne eine Datei die ich 
global.c nenne und dazu natürlich auch eine global.h die ich dann bei 
Bedarf inkludieren kann.

von Harald K. (kirnbichler)


Lesenswert?

In C++ wird der Begriff "Methode" nicht verwendet. So etwas heißt dort 
Funktion, auch wenn es zu einer Klasse gehört.

Reiner D. schrieb:
> Normalerweise referenziere (instanziere) ich Objekte in der main.

Auch hier ist die Terminologie kaputt. Eine Referenz ist etwas anderes 
als eine Instanz.

von Reiner D. (dollreiner)


Lesenswert?

Ich probiers mal mit Code. Zuerst eine symbolische main :


//Klassen :
#include "segel.h"
#include "deckshand.h"

//Objekte :
deckshand Matrose1;
deckshand Matrose2;
segel Fock;
segel Gross;
segel Besan;

//Variablen usw.

int main(void)
{
    while(1)                            //endlosschleife (wie bei ner 
sps)
    {
        if (trigger_10hz == 1)          //timergesteuerte ausführung
        {
            trigger_10hz = 0;
            //------Hier spielt die Musik-----------------

            Gross.setzen();

            //Irgendwas ...
            //--------------------------------------------


        }//ende der 10hz-task in der "while 1" -main-schleife
    };//ende "while 1" - schleife innerhalb main
    return 0;
}//ende von main


ISR (PCINT0_vect)       //Inkremente aus Gruppe 0
{
    Gross.Klauinkrement ++ ;
}

Im Objekt "Gross" wird die Methode "setzen" aufgerufen.
In Methode "setzen" wird das Attribut "Klauinkrement" benötigt.
Sowohl das Objekt "Gross" als auch das Objekt "Fock" haben dieses 
Attribut.
Beide sind aus der ISR zugreifbar, ohne sich zu überschreiben.

Insgesamt soll das eine exemplarische Grundstruktur von OO sein.
Danach werden Methoden durch Vererbung erzeugt usw, usw ...

Wenn jetzt "segel" in "deckshand" instanziert wird statt in main :

#include "segel.h"
segel Grossegel;                //Klasse instanzierenn-> Objekt
deckshand::deckshand()          //Konstruktorlauf
{
    fockfallsollwert=0;         //die Fallwinden aus
    grossfallsollwert=0;
    besanfallsollwert=0;
}
void deckshand::segelsetzen()
{
    if (Klauinkrement < 600)
    {
        //irgendwas
    }
}

.. dann klappt das nicht, weil das Attribut Klaukinkrement (siehe ISR 
oben) natürlich nicht zugegriffen werden kann, es gibt in main ja kein 
Objekt "Gros" mehr. Ich bräuchte : "Matrose1.Gross.Klauinkrement" , aber 
das ist wohl Quatsch ;-)

von Reiner D. (dollreiner)


Lesenswert?

Harald K. schrieb:
> In C++ wird der Begriff "Methode" nicht verwendet. So etwas heißt dort
> Funktion, auch wenn es zu einer Klasse gehört.
>

Da schau her. Zitat Wikipedia :

Was ist eine Methode in C++?
Methoden (englisch method oder member function) sind in der 
objektorientierten Programmierung Unterprogramme in der Form von 
Funktionen oder Prozeduren, die das Verhalten von Objekten beschreiben 
und implementieren. Über die Methoden des Objekts können Objekte 
untereinander in Verbindung treten.

von Purzel H. (hacky)


Lesenswert?

Wie kann man sich Objekte und ISR gleichzeitig antun ? Aber das Konzept 
der Objekte wurde verstanden ? Und das Konzept der ISR wurde auch 
verstanden ?
Objekte kapseln Code und zugehoerige Daten. Ein Objekt hat dafuer 
passende Code Konstrukte. Und jetzt willst du quer hinein pfuschen mit 
Interrupts ?
Lass mal - das wird so nichts.

von Harald K. (kirnbichler)


Lesenswert?

Wikipedia ist nicht der C++-Sprachstandard, sondern spiegelt nur das 
wieder, was die dortigen Texteschreiber gerade der Ansicht sind, als 
NPOV durchgehen zu lassen.

von Oliver S. (oliverso)


Lesenswert?

Reiner D. schrieb:
> .. dann klappt das nicht

weil dir halt so ziemlich alle Grundlagen fehlen.
Schlag mal in deinem C/C++-Buch das Stichwort „extern“ nach.

Oliver

von Martin W. (martinw0)


Lesenswert?

Harald K. schrieb:

> Auch hier ist die Terminologie kaputt.

> Eine Referenz ist etwas anderes
> als eine Instanz.

Reiner D. schrieb:
> Was ist eine Methode in C++?

Oliver S. schrieb:
> Schlag mal in deinem C/C++-Buch das Stichwort „extern“ nach.

usw. usf.


Reiner D. schrieb:
> Ich hoffe, mich einigermaßen verständlich ausgedrückt zu haben.
>
> Was muß ich lernen, um das zu lösen ??

Für kleine 8Bitter die Programmiersprache anpassen?
Sonst läuft man wie gesehen schnell in die Falle sich mehr mit 
Sprachbürokratien denn mit dem eigentlichen Problem herumzuschlagen.

Oliver S. schrieb:
> In dem Fall C

oder je nach Programmumfang noch ne Stufe drunter!

: Bearbeitet durch User
von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> .. dann klappt das nicht, weil das Attribut Klaukinkrement (siehe ISR
> oben) natürlich nicht zugegriffen werden kann,

Es heißt ja auch Gross.Klauinkrement

> es gibt in main ja kein
> Objekt "Gros" mehr.

Hä? Ja doch. Steht doch da.
segel Gross;

> Ich bräuchte : "Matrose1.Gross.Klauinkrement" , aber
> das ist wohl Quatsch ;-)

Ja. Keine Ahnung, wo jetzt der matrose1 herkommt.

von Stefan F. (Gast)


Lesenswert?

Harald K. schrieb:
> In C++ wird der Begriff "Methode" nicht verwendet. So etwas heißt dort
> Funktion, auch wenn es zu einer Klasse gehört.

Ist doch Scheiß egal. Jeder weiß, was gemeint war. Nach zig Jahren 
Berufserfahrung mit zahlreichen Programmiersprachen hat man andere 
Probleme als solche albernen Eitelkeiten.

von DSGV-Violator (Gast)


Angehängte Dateien:

Lesenswert?

> Was muß ich lernen, um das zu lösen ??

Klingt der Funktion nach nach einem Task/process-Scheduler.
Der Linus hat mal zwischen Januar und september1991 einen solchen für 
x386 geschrieben und später zum Linux-Kernel erweitert.

Nachlesbar im Link wie im Anhang gezeigt, die direkte Wiedergabe des 
Links wird von der Forumssoftware blockiert. Seufz ....

https://de?.to/satorutakeuchi/a-brief-history-of-the-linux-kernel-s-process-scheduler-the-very-first-scheduler-v0-01-9e4


? durch v ersetzen

von Reiner D. (dollreiner)


Lesenswert?

Jetzt kam ein Haufen.

Ja, das ist ein Scheduler (wenn wir das gleiche meinen). Aber 
non-premptive, um sich den ganzen Quatsch mit Deadlock, Race und so zu 
ersparen. NPRM im Klartext.

Globale Variable (extern ?) sind möglicherweise nicht zielführend, weil 
ich dann ja für die Attribut eines jeden neuen Objekts neue Variablen 
brauche. Aber es geht natürlich. Ich denke bloß, da muß es im Konzept 
eine elegantere Methode geben.
Konzeptuell müßte bei der Instanzierung (nicht  Referenzierung, sorry) 
des Objekts irgendwo eine globale Variablenerzeugung möglich sein.
Ich sehe auch nicht, wie das mit einem Zeiger geht, wenn wie hier 
mehrere Objekte die im "Orginal" (der Klasse) gleichen Attribute hat. 
Aber hier weiß ich sicher viel zu wenig über Zeiger in C.


Ist aber anders formuliert eigentlich meine Frage :

Wie kann ich im OO-Konzept Objektattribute so erzeugen (instanzieren), 
daß sie von überall (global) zugreifbar sind ?

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Konzeptuell müßte bei der Instanzierung (nicht  Referenzierung, sorry)
> des Objekts irgendwo eine globale Variablenerzeugung möglich sein.

> Wie kann ich im OO-Konzept Objektattribute so erzeugen (instanzieren),
> daß sie von überall (global) zugreifbar sind ?

Kann es sein, dass du gar nicht so richtig weißt, was diese Fachbegriffe 
alle bedeuten? Ich verstehe jedenfalls nur Bahnhof und diese 
Aneinanderreihung der Begriffe ergibt für mich wenig Sinn.

Zeig doch einfach einmal ein einfaches(!) minimales(!) Stück Code, was 
dein Problem zeigt.

von Reiner D. (dollreiner)


Lesenswert?

Was ist daran so schwer zu verstehen ?

Ich möchte bei Erzeugen eines Objekts eine "Variable" (besser ein 
"Attribut", wenn die Zahl der Erbsen eine Rolle spielt) generieren, die 
die Eigenschaften einer globalen hat. Bitte jetzt keine Diskussion über 
das alte public/private Spiel..

Wenn "extern" das kann, wäre einer so lieb, mir ein Stück Beispielcode 
zu zeigen ?

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Ich möchte bei Erzeugen eines Objekts eine "Variable" (besser ein
> "Attribut", wenn die Zahl der Erbsen eine Rolle spielt) generieren

Dein Text ergibt überhaupt gar keinen Sinn.

Das ist das Problem.

Was ist "das Erzeugen eines Objekts"? Ist es der Aufruf des 
Konstruktors?
Was meinst du mit "Attribut"? Was ist "generieren"? Warum setzt du 
"Variable" in Anführungszeichen. Meinst du was anderes?

: Bearbeitet durch User
von Purzel H. (hacky)


Lesenswert?

Bei der Instanzierung des Objektes wird die Variable erzeugt. Dann muss 
man ihr nur noch einen Wert zuweisen.

von Markus W. (dl8mby)


Lesenswert?


von Reiner D. (dollreiner)


Lesenswert?

Folgende Situation, selbst erlebt :

Ein promovierter Jurist frägt den Ingenieur nach einem Vortrag. "Was ist 
denn ein Operationsverstärker ? ". Darauf die Antwort (nicht erfunden 
!!) : "Stellen sie sich einfach einen LM324 vor".

Wer's im Kontext lustig findet, möge lachen ;-)

von Reiner D. (dollreiner)


Lesenswert?

Purzel H. schrieb:
> Bei der Instanzierung des Objektes wird die Variable erzeugt. Dann muss
> man ihr nur noch einen Wert zuweisen.

Was ggf. der Konstruktor tut. Und weil sie in OO eine spezielle 
Charakteristik hat, wird sie Attribut genannt, um sie von der 
klassischen Variablen  abzuheben. Aber : darum gehts überhaupt nicht. 
Ich will hier keine Wortkunde betreiben ...

von Reiner D. (dollreiner)


Lesenswert?

@Markus W.
Ein Traum. Jede Kritik, warum ich zu blöd war, sowas selber zu finden, 
nehme ich bereitwillig an. Vielen Dank !

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Aber : darum gehts überhaupt nicht.
> Ich will hier keine Wortkunde betreiben ...

Wenn man verstanden werden will, muss man eine gemeinsame Sprache 
sprechen.

von Stefan F. (Gast)


Lesenswert?

So geht das
1
#include <iostream>
2
using namespace std;
3
4
int* globalerZeiger;
5
6
class Schiff {
7
    int geschwindigkeit;
8
    
9
public:
10
    Schiff() {
11
        globalerZeiger = &geschwindigkeit;
12
    }
13
14
    ~Schiff() {
15
        globalerZeiger = nullptr;
16
    }
17
18
    int getGeschwindigkeit() {
19
        return geschwindigkeit;
20
    }
21
};
22
23
int main() {
24
    Schiff einSchiff;
25
    *globalerZeiger = 99;
26
    cout << "Geschwindigkeit:" << einSchiff.getGeschwindigkeit() << endl;
27
}

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> int* globalerZeiger;
> class Schiff {
>     int geschwindigkeit;
>
> public:
>     Schiff() {
>         globalerZeiger = &geschwindigkeit;

Das ist ja schon fast Körperverletzung.
Es gibt keinen einzigen Grund und keine Entschuldigung so etwas zu tun.

von Reiner D. (dollreiner)


Lesenswert?

Die static-Deklaration ist es wohl nicht, siehe :

"Static variable in a class:

Static variable in a class is not a part of the subobject of the class. 
There is only one copy of a static data member shared by all the objects 
of the class."

Also das friend-Konzept. Ich dachte bisher, das wär was für Functions in 
namespaces, und mit solchen Dingen hab ich auf den kleinen uP nie zu tun 
gehabt. Liege ich richtig, wenn ich vermute, daß ein friend-Konstrukt 
den Zugriff aus einem Objekt auf ein Attribut eines anderen Objekts 
zuläßt (alles public, oder ?) ?  ..Viel zu tun.

von DSGV-Violator (Gast)


Lesenswert?

Reiner D. schrieb:
> Folgende Situation, selbst erlebt :
>
> Ein promovierter Jurist frägt den Ingenieur nach einem Vortrag. "Was ist
> denn ein Operationsverstärker ? ".

Eben, der Juristen formuliert eine trollig falsch formulierte Frage und 
bekommt denoch eine korrekte Anwort.

Hätte der Jursit statt der Frage "Was ist ein Operationsverstärker", die 
mit der Nennung der Typbezeichnung völlig korrekt beantwortet ist, 
gebeten "Bitte erklären Sie mir als elektronisch Ungebildeten die 
Aufgabe und Funktion eines Operationsverstärkers" hätte er mehr Erfolg 
gehabt.

Aber wer gibt schon zu, da er zu doof für das Thema "Elektronik" ist.


> Wer's im Kontext lustig findet, möge lachen ;-)

Das finden nur Kinder die bespasst werden müßen, lustig. Dist Du so 
eins?

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Das ist ja schon fast Körperverletzung.
:-)

Er hat bekommen, wonach er gefragt hat.

von DSGV-Violator (Gast)


Lesenswert?

MaWin O. schrieb:

> Es gibt keinen einzigen Grund und keine Entschuldigung so etwas zu tun.

Manche sind halt Masochisten und fordern für sich das Rechtein,  sich 
ins eigen Knie zu schiessen ...

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Das ist ja schon fast Körperverletzung.
> Es gibt keinen einzigen Grund und keine Entschuldigung so etwas zu tun.

Jetzt kannst du einen besseren Vorschlag machen, wo eine ISR in C die 
Geschwindigkeit des Schiffes ändert. Denn ich denke, darauf will der TO 
hinaus.

von Reiner D. (dollreiner)


Lesenswert?

@ Stefan F.

Ich brauche ne Weile, um deinen Code zu verstehen, sorry. Mein 
Syntaxvorrat reicht immer genau so weit wie ich zur Lösung von irgendwas 
brauche, ich hatte nie systematisch C gelernt. (Merkt man ja ;-).

Wenn ichs richtig interpretiere, wird statt des Attributs eine indirekte 
Adressierung ausgeführt, also ein Pointer benutzt, wie das in C wohl 
heißt.

Legt der Compiler dann da ne Liste an, welche Adresspeicher (Pointer) zu 
welchem Objekt gehören ?

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Liege ich richtig, wenn ich vermute, daß ein friend-Konstrukt
> den Zugriff aus einem Objekt auf ein Attribut eines anderen Objekts
> zuläßt (alles public, oder ?)

Ja.
Aber eben fordertest du noch:

Reiner D. schrieb:
> Bitte jetzt keine Diskussion über
> das alte public/private Spiel..

Stefan F. schrieb:
> Jetzt kannst du einen besseren Vorschlag machen, wo eine ISR in C die
> Geschwindigkeit des Schiffes ändert. Denn ich denke, darauf will der TO
> hinaus.
1
ISR()
2
{
3
  schiff.schneller(10);
4
}

Man braucht weder einen Zeiger auf schiff.geschwindigkeit, noch braucht 
man von außen direkt auf schiff.geschwindigkeit zuzugreifen.

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Syntaxvorrat

Dein was? Schon wieder ein Wort falsch verwendet?

> ich hatte nie systematisch C gelernt. (Merkt man ja ;-).

Allerdings.
Aber das kannst du ja ändern.

Reiner D. schrieb:
> wird statt des Attributs

Das ist kein Attribut. Das ist eine Member-Variable. Ein Attribut ist in 
C++ etwas anderes.
https://en.cppreference.com/w/cpp/language/attributes
Du verwendest ständig Worte falsch. Und deshalb versteht dich niemand.

Reiner D. schrieb:
> Legt der Compiler dann da ne Liste an, welche Adresspeicher (Pointer) zu
> welchem Objekt gehören ?

hä?
Wozu soll eine Liste benötigt werden? Wozu sollte das gut sein?

von Reiner D. (dollreiner)


Lesenswert?

Nur zur Erklärung :

Nein, hat nix mit Schiffsgeschwindigkeiten oder ähnlichem zu tun.

Im Kern geht's um Hierarchisierung von Funktionen.
Ich schreibs nochmal als "Prosa", Modellierung ist ja auch ein 
Bestandteil von OO.

Oberste Ebene : "main"    (im Modell : Der Käptn')

erste drunter : Objekte der Klasse "deckshand" : "matrose1", "matrose2"

matrose1 ist eine Instanz von deckshand, die in main instanziert wurde.
Voteile : wenn man neue Funktionen will, wird ein neuer matrose 
instanziert.
Methoden von deckshand können vererbt usw. werden.

wieder drunter : Objekte der Klasse "segel". Die werden jetzt in den 
Matrosen instanziert. Vorteile wie üblich in OO. z.b "fock" oder 
"gross".

so, jetzt kann ich in "matrose1" die methode "fock.setzen()" aufrufen.

-> Ich will aber in main auf Attribute von "fock" in "matrose" zugreifen 
!

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> -> Ich will aber in main auf Attribute von "fock" in "matrose" zugreifen

Dann mache das doch. Sehe das Problem nicht.
1
int main() {
2
3
matrose1.fock.setzen();
4
}

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Legt der Compiler dann da ne Liste an, welche Adresspeicher (Pointer) zu
> welchem Objekt gehören ?

Mein Beispiel funktioniert nur mit einer Instanz des Schiffes. Der MaWin 
O. hat meinen obigen Vorschlag zu Recht kritisiert. Denn der Sinn von 
Objekten ist, dass sie ihre Daten Kapseln. Man sollte niemals von außen 
direkt auf die Attribute der Objekte zugreifen, schon gar nicht über 
Zeiger an der Programmiersprache vorbei.

Man kann aber die Instanzen der Objekte global erreichbar machen. Zum 
Beispiel so:
1
#include <iostream>
2
using namespace std;
3
4
class Schiff {
5
    int geschwindigkeit;
6
7
public:
8
    int getGeschwindigkeit() {
9
        return geschwindigkeit;
10
    }
11
12
    void setGeschwindigkeit(int i) {
13
        geschwindigkeit = i;
14
    }
15
16
    void changeGeschwindigkeit(int i) {
17
        geschwindigkeit += i;
18
    }
19
};
20
21
Schiff* schiffe[20];
22
23
// Bei Interrupt wird das erste Schiff verlangsamt
24
void isr() {
25
    schiffe[0]->changeGeschwindigkeit(-1);
26
}
27
28
int main() {
29
    // Erzeuge drei Schiffe
30
    schiffe[0] = new Schiff();
31
    schiffe[1] = new Schiff();
32
    schiffe[2] = new Schiff();
33
34
    // Alle drei Schiffe sind unterwegs
35
    schiffe[0]->setGeschwindigkeit(99);
36
    schiffe[1]->setGeschwindigkeit(99);
37
    schiffe[2]->setGeschwindigkeit(99);
38
39
    // Interrupt simulieren
40
    isr();
41
42
    cout << "Geschwindigkeit erstes Schiff:" << schiffe[0]->getGeschwindigkeit() << endl;
43
    cout << "Geschwindigkeit zweites Schiff:" << schiffe[1]->getGeschwindigkeit() << endl;
44
    cout << "Geschwindigkeit drittes Schiff:" << schiffe[2]->getGeschwindigkeit() << endl;
45
}

von Sebastian W. (wangnick)


Lesenswert?

Reiner D. schrieb:
> Ich bräuchte : "Matrose1.Gross.Klauinkrement" , aber das ist wohl
> Quatsch ;-)

Nein, genau so geht es.

LG, Sebastian

Beitrag #7384370 wurde von einem Moderator gelöscht.
von Stefan F. (Gast)


Lesenswert?

Stefan F. schrieb:
> // Erzeuge drei Schiffe
> schiffe[0] = new Schiff();
> schiffe[1] = new Schiff();
> schiffe[2] = new Schiff();

Ich sollte dazu noch etwas ergänzen: Diese Zeilen müssen nicht in der 
main stehen. Du kannst wie gewünscht ein Schiffsbauer-Objekt 
programmieren, dass die Schiffe baut (mit new erzeugt) und dem Array 
zuweist.

Anstelle des Arrays könntest du auch drei einzelne globale Variablen 
verwenden, wenn dir das lieber ist. Aber auf jeden Fall müssen die 
Zeiger oder die Referenzen auf auf die Schiffe global sein, sonst kommst 
du innerhalb deiner ISR nicht heran.

von Reiner D. (dollreiner)


Lesenswert?

Was lange währt, wird endlich gut.
Natürlich lag es an meiner unpräzisen Beschreibung meines Problems.

Ich dachte nur, meine Syntaxerfindung : "Matrose1.Gross.Klauinkrement" 
wäre ein frommer Wunsch. Daß das in C++ geht, ist überraschend.

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Was lange währt, wird endlich gut.
> Natürlich lag es an meiner unpräzisen Beschreibung meines Problems.
>
> Ich dachte nur, meine Syntaxerfindung : "Matrose1.Gross.Klauinkrement"
> wäre ein frommer Wunsch. Daß das in C++ geht, ist überraschend.
1
Schiff erstesSchiff;
2
Schiff* zeigerAufZweitesSchiff;
3
4
int main() {
5
    zeigerAufZweitesSchiff = new Schiff();
6
7
    cout << "Geschwindigkeit erstes Schiff:" << erstesSchiff.getGeschwindigkeit() << endl;
8
    cout << "Geschwindigkeit erstes Schiff:" << zeigerAufZweitesSchiff->getGeschwindigkeit() << endl;
9
}

Oder wenn Geschwindigkeit public ist:
1
Schiff erstesSchiff;
2
Schiff* zeigerAufZweitesSchiff;
3
4
int main() {
5
    zeigerAufZweitesSchiff = new Schiff();
6
7
    cout << "Geschwindigkeit erstes Schiff:" << erstesSchiff.geschwindigkeit << endl;
8
    cout << "Geschwindigkeit erstes Schiff:" << zeigerAufZweitesSchiff->geschwindigkeit << endl;
9
}

Du benutzt "." um direkt auf Eigenschaften deiner Objekte zuzugreifen.
Bei Zeigern auf Objekte benutzt du hingegen "->".

Beitrag #7384388 wurde von einem Moderator gelöscht.
von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Ich dachte nur, meine Syntaxerfindung : "Matrose1.Gross.Klauinkrement"
> wäre ein frommer Wunsch. Daß das in C++ geht, ist überraschend.

Sauber ist es trotzdem nicht, weil es die Kapselung durchbricht.
Solche Konstrukte zeigen in der Regel einen Fehler in der Architektur 
auf.

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Ich brauche ne Weile, um deinen Code zu verstehen, sorry. Mein
> Syntaxvorrat reicht immer genau so weit wie ich zur Lösung von irgendwas
> brauche, ich hatte nie systematisch C gelernt.

Du meinst C++. Vielleicht hilft dir mein Tutorial 
http://stefanfrings.de/qt_lernen/index.html

Deine folgenden Fragen beziehen sich auf meinen (fragwürdigen) 
Vorschlag:
1
int* globalerZeiger;
2
3
class Schiff {
4
    int geschwindigkeit;
5
6
  public:
7
    Schiff() {
8
        globalerZeiger = &geschwindigkeit;
9
    }
10
}
11
12
*globalerZeiger = 99

> Wenn ichs richtig interpretiere, wird statt des Attributs eine indirekte
> Adressierung ausgeführt, also ein Pointer benutzt

Ja, in meinem Vorschlag ist int* ein Zeiger auf eine Integer Variable. 
Und &geschwindigkeit ist die Adresse der Geschwindigkeit im RAM.

> Legt der Compiler dann da ne Liste an, welche Adresspeicher (Pointer) zu
> welchem Objekt gehören ?

Der Zeiger hat initial den Wert 0, was allgemein als "zeigt nirgendwo 
hin" interpretiert wird. Der Konstruktor des Schiffes setzt den Zeiger 
auf die Adresse seiner Geschwindigkeits-Variable. Erst nach Ausführung 
des Konstruktors kann man über den Zeiger auf den Speicher der Variable 
im RAM zugreifen.

Die letzte Zeile im obigen Code-Fragment heißt: Setze den Speicher auf 
den der Zeiger zeigt, auf den Wert 99. Dadurch wird effektiv die 
Variable geschwindigkeit von dem Schiff geändert, weil sie sich genau 
dort im Speicher befindet, wo der Zeiger hin zeigt.

Unsauber ist daran, dass ich dadurch eine eigentlich private Eigenschaft 
des Objektes global zugänglich gemacht habe, und zwar nicht nur für 
lesende Zugriffe, sondern auch noch für schreibende.

von J. S. (jojos)


Lesenswert?

So Singletons sind meistens unschön. Und wenn schon mit C++ abstrahiert 
werden soll, dann würde ich die Methodenaufrufe auch nicht direkt in der 
ISR machen.
Schöner geht das z.B. mit einer EventQueue die auch zyklische Aufrufe 
erlaubt. Ein instantiiertes Objekt kann sich dann selber in die Queue 
eintragen. Methodenaufrufe sind nur etwas tricky, die callbacks brauchen 
den this pointer und die Adresse der Funktion.

von Oliver S. (oliverso)


Lesenswert?

J. S. schrieb:
> Schöner geht das z.B. mit einer EventQueue die auch zyklische Aufrufe
> erlaubt. Ein instantiiertes Objekt kann sich dann selber in die Queue
> eintragen. Methodenaufrufe sind nur etwas tricky, die callbacks brauchen
> den this pointer und die Adresse der Funktion.

Die Sprachkenntnisse des TO liegen irgendwo zwischen Frühgeburt und 
Analphabet. Da ist dein Vorschlag vielleicht doch etwas verfrüht.

Oliver

von Purzel H. (hacky)


Lesenswert?

Rainer D. :
> Legt der Compiler dann da ne Liste an, welche Adresspeicher (Pointer) zu
welchem Objekt gehören ?

Es ist viel einfacher. Dein Objektname ist schon der Pointer auf das 
Objekt.

von Falk S. (db8fs)


Lesenswert?

Hmm, na ja, es werden viele Sachen hier durchmischt, glaube ich.

Worum es geht, soweit ich das nachvollziehen kann, ist es, dass der OP 
ein Objektmodell erzeugen möchte, welches ein Schiffsmodell mit 
verschiedenen Szenarien beschreibt.

Ein Objekt hat ja grundsätzlich eine Lebenszeit, startend beim 
Konstruktor und endend beim Destruktor - solange das Objekt 'lebt', hat 
es Zustand (Membervariablen), deren Inhalt sich im Laufe der Lebenszeit 
ändern kann. Diese 'Member' sind üblicherweise private und sollten nur 
über definierte Memberfunktionen/Methoden verändert werden. So die die 
Theorie.

Singletons bzw. statische Klassen sind im Prinzip ja genau dasselbe, nur 
dass es eben bloß 1 Exemplar dieser Klasse zur Laufzeit (=1 Objekt) 
gibt. Ändert fürs Objektmodell eigentlich nicht viel.

Wenn du ein Objekt anlegst/instanziierst, kann das so aussehen, wie 
Stefan F. das beschrieben hat, mit dem new-Operator instanziiert. Ne 
andere Variante wäre einfach:
1
class Segel
2
{
3
public:
4
  enum class Status
5
  {
6
     Gerefft = 0,
7
     VollesSegel
8
  };
9
10
  void setzen(enum class Status state )
11
  {
12
     if(m_status != state)
13
     {
14
        m_status = state;
15
        //... auf aenderung etwas ausloesen
16
     }
17
  }
18
19
20
private:
21
  Status m_status;
22
};
23
24
class Kapitaen
25
{
26
 int m_flaschenGrogIntus = 0;
27
public:
28
   
29
   void auftanken()
30
   {
31
      ++m_flaschenGrogIntus;
32
   }
33
34
   void ablassen()
35
   {
36
      if(m_flaschenGrogIntus>0)
37
      {
38
         --m_flaschenGrogIntus;
39
      }
40
   }
41
42
};
43
44
class Schiff
45
{
46
  Segel m_segel;
47
  Kapitaen m_kapitaen;
48
49
public:
50
51
  Schiff()
52
  {}
53
54
  void volleFahrt()
55
  {
56
     m_segel.setzen(Segel::VollesSegel);
57
     m_kapitaen.auftanken();
58
  }
59
60
  void angreifen(Schiff & gegner)
61
  {
62
    gegner.bumm();
63
  }
64
65
  void bumm()
66
  {
67
     m_kapitaen.auftanken();
68
     m_kapitaen.auftanken();
69
     //untergehen
70
  }
71
};
72
73
int main()
74
{ 
75
   Schiff seaMonkey;
76
   Schiff leChuckSchiff;
77
   seaMonkey.volleFahrt();
78
   seaMonkey.angreifen(leChuckSchiff);
79
}

Legst du eine Instanz vom Schiff an (seaMonkey), wird der Konstruktor 
aufgerufen. Bei der schließenden Klammer } fliegt das Objekt aus dem 
Scope, die Lebenszeit ist vorbei - der Destruktor wird aufgerufen. 
Dazwischen kannste Methoden der Klasse aufrufen, wie z.B. volleFahrt, 
wobei auch gleich der Käptn mitgetankt wird.

In erster Linie erzeugst du hierarchische Abbildung durch Komposition - 
quasi das große ist die Summe der Teile - im Beispiel enthält das Schiff 
einen Käptn und ein Segel. Heißt - erzeugst du ein Schiff, wird Segel 
und Käptn mit erzeugt. Man kann auch Aggregation machen, dann können die 
Teile auch länger leben als das Schiff.

Mal grob als Idee, hilfreich zum Verständnis sind vielleicht UML 
Objektdiagramme oder auch ein E/R-Modell.

von Jens R. (tmaniac)


Lesenswert?

So mal abseits der Programmierkenntnisse würde ich darauf tippen, das 
einfach die verschiedene Sichtweisen zu Problemen führen.

Reiner D. schrieb:
> Oberste Ebene : "main"    (im Modell : Der Käptn')

Das ist nämlich der komplett falsche Ansatz um deine Objekte zu 
betrachten.

Die main.c (oder main.cpp) ist deine Welt in der du dich bewegst.
In der main.h(pp) musst du alles benennen (nicht definieren) was in der 
Welt existieren soll. Dabei musst du es nicht unmittelbar machen. Du 
kannst mit einem #include auch andere Sammlungen von Benennungen, aka 
andere Headerdateien einbinden.

Deine main.c sollte dann auch nur die Geschehnisse deiner Welt 
beschreiben. Also wie sie entsteht, dass passiert in der main-Funktion 
und was sie so macht, das sind die Interruptroutinen.
Da deine Welt über die Header weiß was es alles auf ihr gibt solltest du 
auch darauf zu greifen können. Wenn es richtig von Grundauf OO ist, dann 
in der Art Schiff.GetMatrose(Kapitän).GebBefehlAn(Steuermann)


Wie viele schon geschrieben habe, mache die mit den Konzepten betraut 
und male dir einen Bauplan auf ein Stück Papier.

###
Nebenfrage: welches main meinst du wieder.
Du selber schreibst weiter oben das es ja main-Funktion und main.h gibt
Die beiden hängen nicht wirklich systematisch zusammen
###

von Reiner D. (dollreiner)


Lesenswert?

Falk S. schrieb:
> Mal grob als Idee, hilfreich zum Verständnis sind vielleicht UML
> Objektdiagramme oder auch ein E/R-Modell.


Danke !

von Reiner D. (dollreiner)


Angehängte Dateien:

Lesenswert?

@Jens :

Syntax ist mir egal, mich interessiert nur das Konzeptuelle.

"Die main.c (oder main.cpp) ist deine Welt in der du dich bewegst.
In der main.h(pp) musst du alles benennen (nicht definieren) was in der
Welt existieren soll."

In Code::Blocks Projekten gibts gar keine main.h
Ich wollte so modellieren wie im Wordbild dargestellt.
Die main.cpp ist bei mir das Deck meines Schiffes, auf dem alle Akteure 
kommunizieren. Sie sind in der  #include - Liste mit ihren .h aufgeführt 
(quasi meine Decksrolle, Besatzungsliste).

Die Objekte gliedern das Konzept sehr schön, man könnte die Arbeit auch 
gut verteilen, wenn die Schnittstellen sauber definiert sind.

Käptn gibt Befehle an Matrosen, die haben Elemente des Schiffs (Segel, 
Ruder, Maschine, Navigationsraum...), dort steht die Hardware (Winden, 
Motor, GPS...).

Leider ist ein Teil der Messtechnik (z.b. die Inkrementgeber der Winden) 
in ISR (geht wegen Timing nicht anders). Und die ISR sind hier auf 
main-Ebene.
Der Pfeil von ISR zur class segel (eigentlich besser zum Objekt Fock 
z.B.) ist mein Problem. Aber ich denke mit den Zeigern von Stefan F. 
wird das.

Konzept schlecht ?
(sind ja wohl verschiedene Ansätze möglich...)

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> an Matrosen, die haben Elemente des Schiffs (Segel,
> Ruder, Maschine, Navigationsraum...)

Ich finde es äußerst bizarr, dass du eine Komposition von Matrosen und 
Schiffselementen machst.

Ein natürlicheres Modell wäre eine Komposition aus Schiff + Schiffsteile 
und eine weitere Komposition der Besatzung. Die Besatzung würde dann per 
(kurzlebiger) Referenzen auf die Schiffsteile einwirken.

Reiner D. schrieb:
> Aber ich denke mit den Zeigern von Stefan F. wird das.

In modernem C++ arbeitet man auch gutem Grund praktisch nie mit Zeigern.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> In modernem C++ arbeitet man auch gutem Grund praktisch nie mit Zeigern.

In C++ gibt es auch keine Interrupthandler. Da stoßen zwei Welten 
aneinander, die man ganz ohne Regelbruch nicht zusammen kriegt.

von Reiner D. (dollreiner)


Lesenswert?

Der Käptn "bedient" den Matrosen
Der Matrose1 bedient die Fock
Der Matrose2 bedient das Gross
Der Matrose3 bedient den Besan    (wobei die Methoden leicht 
differieren)

Modellgrundlage ist, wer mit was arbeitet

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
>> In modernem C++ arbeitet man auch gutem Grund praktisch nie mit Zeigern.
>
> In C++ gibt es auch keine Interrupthandler. Da stoßen zwei Welten
> aneinander, die man ganz ohne Regelbruch nicht zusammen kriegt.

Und wieso sollte man dort zwingend Rohzeiger brauchen?

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> In C++ gibt es auch keine Interrupthandler

Ist AVR-GCC kein C++ ?

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Modellgrundlage ist, wer mit was arbeitet

Ja. Das ist meiner Ansicht nach ein schlechtes Modell.

Komposition sollte IMO eher durch physikalische Zusammenhänge gebildet 
werden und "arbeitet mit" sollte mit Referenzen gebildet werden.
Der Vorteil ist, dass man so sehr viel flexibler ist.
Was, wenn ein Matrose mal das Deck schrubben soll? Was, wenn das immer 
ein anderer Matrose sein soll, weil die Drecksarbeit geteilt wird? Mit 
einer Komposition ist das nicht abbildbar.

von Oliver S. (oliverso)


Lesenswert?

Stefan F. schrieb:
> In C++ gibt es auch keine Interrupthandler. Da stoßen zwei Welten
> aneinander, die man ganz ohne Regelbruch nicht zusammen kriegt.

In C gibts die auch nicht. Die gibt es halt nur im realen Leben, als 
Notbehelf.

Oliver

von Reiner D. (dollreiner)


Lesenswert?

@MaWin :

Nochmal für C++ - Analphabeten :

"schrubben" als Methode in die deckshand-class zu schreiben ist Mist, 
oder ?
(so daß jeder Matrose das kann)

Also "schrubben" quasi als "subroutine" (wenns das in C++ noch gibt), 
und aufrufen wenn gebraucht (=Referenz ?)

von J. S. (jojos)


Lesenswert?

Dem Schiff ist doch egal wer die Winde oder Ruder bedient. Für eine 
Rechts oder Linkskurve muss ein bestimmter Ablauf eingehalten werden. 
Ich würde auch die Schiffskomponenten als Objekte sehen.

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> "schrubben" als Methode in die deckshand-class zu schreiben ist Mist,
> oder ?
> (so daß jeder Matrose das kann)

Mal als Konzeptbeispiel:
1
class Deck { ... };
2
3
class Matrose {
4
...
5
   void schrubbe(deck &Deck) {
6
      ...
7
   }
8
};
9
10
int main() {
11
    Deck deck;
12
    Matrose matrose1;
13
    Matrose matrose2;
14
15
    if (/* Montag */) {
16
       matrose1.schrubbe(deck);
17
    } else {
18
       matrose2.schrubbe(deck);
19
    }
20
}

Tippfehler sind absichtlich ;)

von Reiner D. (dollreiner)


Lesenswert?

J. S. schrieb:
> Für eine
> Rechts oder Linkskurve muss ein bestimmter Ablauf eingehalten werden.

Bei meinem Schiffchen :

Der Käptn will (z.b. wenn der Sender ausfällt, oder ich das Schiff nicht 
mehr sehe) per Autopilot irgendwohin (oder nach home).

Er frägt den Navigator nach dem Zielkurs, Navigator liest GPS, rechnet 
PID und kriegt Zielkurs raus.

Er befiehlt dem Rudergänger den Zielwinkel, der liest den Kompass, PID 
für Sollwinkel.

Daneben befiehlt der Käptn den Matrosen1 bis 3 ihre jeweiligen Segel zu 
bergen, und dem Maschinisten, den Motor zu starten.

von Reiner D. (dollreiner)


Lesenswert?

MaWin O. schrieb:
> class Matrose {
> ...
>    void schrubbe(deck &Deck) {
>       ...
>    }

So hab ich das gedacht. z.b. hat jedes Objekt von segel eine Methode 
"fall_hoch", mit der es per geregelter Winde das Segelchen ein 
gewünschtes Stück hochziehen kann.

ok ?

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Ist AVR-GCC kein C++ ?

Die AVR GNU Compiler Collection ist ein Set aus mehreren Compilern, 
unter anderem (hier relevant) der zu C kompatible C++ Compiler mit 
Spezieller Unterstützung für AVR Mikrocontroller. Interrupthandler sind 
im Sprachumfang vom C++ Standard nicht vorgesehen. In C sind sie auch 
nicht vorgesehen, daher die Mikrocontroller spezifische Erweiterung.

Eine Objekt-Funktion (Methode) kann deswegen nicht als Interrupthandler 
dienen, weil die Interrupt-Vektoren des AVR Mikrocontrollers

a) nur auf Funktionen, nicht auf Objekte zeigen kann. Die Tabelle müsste 
für jedes Objekt zwei Zeiger enthalten (Funktion und Daten (this)).

b) schreibgeschützt ist. Objekte, die erst zur Laufzeit erzeugt werden, 
können sich nicht in die Interrupt-Vektoren eintragen.

MaWin O. schrieb:
> In modernem C++ arbeitet man auch gutem Grund praktisch nie mit Zeigern.

Dazu habe ich eine ernst gemeinte Frage: Referenzen sind technisch 
gesehen auch Pointer, haben lediglich eine andere Syntax. Wie erzeugst 
du Objekt-Instanzen zur Laufzeit, ohne new und ohne 
Referenzen/Pointer?

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Dazu habe ich eine ernst gemeinte Frage: Referenzen sind technisch
> gesehen auch Pointer, haben lediglich eine andere Syntax.

Nein. Das ist nicht nur eine andere Syntax.
In C++ gibt es viele verschiedene Arten Objekte zu referenzieren. 
Klassische Referenzen und auch verschiedene Smartpointer.
Mit Rohzeigern haben die alle eigentlich nichts zu tun.

Aber ich würde auch behaupten, dass man für eine ISR weder Rohzeiger, 
noch Referenzen, noch Smartpointer braucht. Man kann doch ganz einfach 
ganz normal auf statisch alloziierte globale Ressourcen zugreifen.

Stefan F. schrieb:
> Wie erzeugst
> du Objekt-Instanzen zur Laufzeit, ohne new und ohne
> Referenzen/Pointer?

Einfach auf dem Stack?

von Oliver S. (oliverso)


Lesenswert?

Stefan F. schrieb:
> Die AVR GNU Compiler Collection ist ein Set aus mehreren Compilern,
> unter anderem (hier relevant) der zu C kompatible C++ Compiler mit
> Spezieller Unterstützung für AVR Mikrocontroller.

Was genau soll ein „zu C kompatibler C++ Compiler“ sein? Der erste April 
war gestern.

Die AVR-gcc-toolchain kommt, wie jeder gcc, mit einem C- und einem C++ 
-Compiler. Der eine spricht nur vollwertiges C, der andere nur 
vollwertiges C++. „Kompatibel“ ist das nur in so weit, wie C und C++ 
gemeinsame Sprachkonstrukte haben.

Oliver

: Bearbeitet durch User
von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Eine Objekt-Funktion (Methode) kann deswegen nicht als Interrupthandler
> dienen, weil die Interrupt-Vektoren des AVR Mikrocontrollers

Richtig. Nicht direkt. Aber:
1
class MyClass {
2
  void handle_irq() {
3
    ...
4
  }
5
}
6
7
MyClass myclass;
8
9
ISR() {
10
  myclass.handle_irq();
11
}

> b) schreibgeschützt ist. Objekte, die erst zur Laufzeit erzeugt werden,
> können sich nicht in die Interrupt-Vektoren eintragen.

Da könnte man Smartpointer verwenden. Aber auf AVR8 ist es wohl eher 
generell eine schlechte Idee dynamische Objekte anzulegen. Nicht nur in 
C++. ;)

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Aber ich würde auch behaupten, dass man für eine ISR weder Rohzeiger,
> noch Referenzen, noch Smartpointer braucht. Man kann doch ganz einfach
> ganz normal auf statisch alloziierte globale Ressourcen zugreifen.

Kommt drauf an, was man machen will. Der TO möchte, dass die ISR 
Eigenschaften seiner Objekt-Instanzen ändert.

> Wie erzeugst du Objekt-Instanzen zur Laufzeit, ohne new und ohne
> Referenzen/Pointer?

Einfach auf dem Stack?

Der Stack verliert beim Verlassen einer Funktion seine Gültigkeit. Mit 
der Beschränkung verlierst du die Möglichkeit, Objekte innerhalb von 
Funktionen zu erzeugen und danach außerhalb dieser zu benutzen. Früher 
oder später brauchst du das aber.

Der TO braucht es. Seine ISR soll auf Objekte zugreifen, die innerhalb 
einer Objekt-Funktion (Methode) erzeugt wurden.

> Aber auf AVR8 ist es wohl eher generell eine schlechte
> Idee dynamische Objekte anzulegen.

Ich möchte es nicht generell verbieten, aber man sollte sich diese Fälle 
gut überlegen. Insbesondere wegen der möglichen Fragmentierung des Heap.

von Stefan F. (Gast)


Lesenswert?

Oliver S. schrieb:
> Was genau soll ein „zu C kompatibler C++ Compiler“ sein? Der erste April
> war gestern.

C++ ist in meinen Augen ein Aufsatz auf C. So habe ich dessen 
Entwicklung erlebt.

Als Kontrast dazu möchte ich Java nennen, welches keine Funktionen 
außerhalb von Objekten kennt.

von Oliver S. (oliverso)


Lesenswert?

Stefan F. schrieb:
> Dazu habe ich eine ernst gemeinte Frage: Referenzen sind technisch
> gesehen auch Pointer, haben lediglich eine andere Syntax. Wie erzeugst
> du Objekt-Instanzen zur Laufzeit, ohne new und ohne
> Referenzen/Pointer?

Z.B. als lokale Variable, die dann auf dem Stack landet.

Oliver

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
>> Aber ich würde auch behaupten, dass man für eine ISR weder Rohzeiger,
>> noch Referenzen, noch Smartpointer braucht. Man kann doch ganz einfach
>> ganz normal auf statisch alloziierte globale Ressourcen zugreifen.
>
> Kommt drauf an, was man machen will. Der TO möchte, dass die ISR
> Eigenschaften seiner Objekt-Instanzen ändert.

Das widerspricht sich doch gar nicht.
1
class MyClass {
2
public:
3
  void handle_irq() {
4
     eigenschaft++;
5
  }
6
7
protected:
8
  int eigenschaft = 0;
9
}
10
11
MyClass myclass;
12
13
ISR() {
14
  myclass.handle_irq();
15
}

> Der Stack verliert beim Verlassen einer Funktion seine Gültigkeit. Mit
> der Beschränkung verlierst du die Möglichkeit, Objekte innerhalb von
> Funktionen zu erzeugen und danach außerhalb dieser zu benutzen. Früher
> oder später brauchst du das aber.

Das ist eine Behauptung. Kannst du auch ein Beispiel liefern, wo ich das 
unbedingt brauche?

> Der TO braucht es.

Das würde ich in Frage stellen.

> Seine ISR soll auf Objekte zugreifen, die innerhalb
> einer Objekt-Funktion (Methode) erzeugt wurden.

Das würde ich als kaputtes Konzept beschreiben, weil die Methode ja per 
Definition zum ISR-Aufruf nicht läuft. Und damit auch alle Objekte 
innerhalb die Gültigkeit verlieren, wie du schon richtig erkanntest.

Das kann man nicht einmal mit Rohzeigern hinfrickeln.
Das geht einfach nicht.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
>> Der TO braucht es.
> Das würde ich in Frage stellen.

Zumindest will er es so machen. Lass ihn doch! Du kannst von einem 
Anfänger nicht erwarten, die hohe Kunst der C++ Programmierung so zu 
beherrschen, wie einer, der das jahrelang studiert hat.

Auch Anfänger können damit gut funktionierende Sachen hinbekommen - auch 
wenn sich dem Akademiker dabei die Fußnägel hoch rollen. Ich sage nur: 
Arduino.

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> C++ ist in meinen Augen ein Aufsatz auf C

Das ist es schon lange nicht mehr. Diese Denkweise ist >25 Jahre alt.

Aber das erklärt sehr wohl einige deiner vorherigen Ausführungen und die 
Fixierung auf Rohzeiger. ;)

Du solltest dir unbedingt man etwas >= C++11 anschauen. Es lohnt sich.

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Zumindest will er es so machen. Lass ihn doch!

Ich lasse jeden das tun, was er will. Keine Angst. :)

> Du kannst von einem
> Anfänger nicht erwarten, die hohe Kunst der C++ Programmierung so zu
> beherrschen, wie einer, der das jahrelang studiert hat.

Das tue ich auch nicht. Ganz im Gegenteil. Das ist ja der Grund, weshalb 
ich überhaupt hier Antworte. Ich möchte Anstöße in andere Richtungen 
geben.

> Auch Anfänger können damit gut funktionierende Sachen hinbekommen

Das bestreitet ja auch niemand. Man kann auch in Assembler programmieren 
und alles funktioniert.
Man kann auch C schreiben (Rohzeiger nutzen) und das mit einem 
C++-Compiler übersetzen.
Man braucht auch keine Smartpointer und Referenzen zu benutzen und kann 
trotzdem alles in einen funktionsfähigen Zustand bekommen.
Geht alles.
Aber das schien mir jetzt nicht die Intention des Threaderstellers zu 
sein.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Du solltest dir unbedingt man etwas >= C++11 anschauen. Es lohnt sich.

Wohl kaum. In meinem Beruf sind ganz andere Programmiersprachen 
angesagt, da will niemand mehr etwas von C++ hören. Die Sprache ist nur 
noch für mein Hobby (Mikrocontroller) am Rande neben C ein bisschen 
interessant.

Mag sein, dass die Sprache im Laufe vieler Jahre allmählich besser 
geworden ist. Aber sie ist auch zusammen mit der Generation ihrer 
Entwickler gealtert. In 20 Jahren wenn meiner-einer in Rente geht, 
arbeitet damit kein Mensch mehr.

Also anstatt ständig den Neuen Aspekten der Sprache hinterher zu laufen, 
während ich alte Projekte pflegen muss die das eh nicht nutzen 
können/sollen, lerne ich doch lieber die neuen Programmiersprachen, mit 
denen die Kollegen links und rechts neben mit erfolgreich Geld für die 
Firma verdienen. Sonst bin ich nämlich schneller raus aus dem Geschäft, 
als das Renten-Eintrittsalter vorsieht.

von Reiner D. (dollreiner)


Lesenswert?

@Stefan :

no pain, no gain.
So eine Lernkurve tut weh ...

Also für Doofe :

Ganz oben, in der main :

--------------------
int* Fallinkrement;
--------------------

ganz unten, in der class segel.cpp :

-------------------------------
int Fallinkrement;
segel::segel()
{
    Fallinkrement = &Fallinkrement;
-------------------------------

Im Konstruktorlauf wird dem Objekt ein Zeiger zugeordnet (symbolisch 
(!!) quasi bei Objekt Fock also "Fock.*Fallinkrement" : Zeiger 
Fallinkrement, der dem Objekt Fall zugeordnet ist)

und jetzt in der ISR :
-----------------------------
Fock.*Fallinkrement ++ ;
-----------------------------

Hab ich jetzt ein Syntaxproblem, oder hab ich das Zeiger-Konzept noch 
nicht verstanden ?

Im Kern stört bei mir, dass jedes Segel 3 Taue hat, die jeweils gleich 
heißen (Fall, Klau, Piek). Und die Auffächerung in Gross.Piek und 
Besan.Piek
geschieht ja erst bei Objekterzeugung. In " int*  " gibts die noch 
nicht.

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Wohl kaum. In meinem Beruf sind ganz andere Programmiersprachen
> angesagt, da will niemand mehr etwas von C++ hören.

Ja gut. Dann verstehe ich allerdings nicht, warum du hier Ratschläge zu 
C++ gibst.
Für mich gehört es dazu, dass man auf der Höhe der Zeit ist, wenn man 
Ratschläge gibt.

> Die Sprache ist nur
> noch für mein Hobby (Mikrocontroller) am Rande neben C ein bisschen
> interessant.

Das mag in deiner Blase stimmen.
Das ist aber (leider) ganz und gar nicht die Realität.

> Mag sein, dass die Sprache im Laufe vieler Jahre allmählich besser
> geworden ist.

C++ hat sich nicht nur "allmählich" entwickelt, sondern hat riesige 
Sprünge in den letzten 15 Jahren gemacht.
Das ist nun eine vollkommen neue Sprache, die noch rückwärtskompatibel 
zu 90er-Jahre-C++ ist. (Zu C war C++ noch nie vollständig 
rückwärtskompatibel)

> Aber sie ist auch zusammen mit der Generation ihrer
> Entwickler gealtert. In 20 Jahren wenn meiner-einer in Rente geht,
> arbeitet damit kein Mensch mehr

Sportliche Vorhersage. Ich hoffe, dass du recht behältst. Ich befürchte 
aber, dass es nicht so sein wird.

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Hab ich jetzt ein Syntaxproblem, oder hab ich das Zeiger-Konzept noch
> nicht verstanden ?

Bitte trenne dich davon. Es gibt hier keinen einzigen Grund einen Zeiger 
zu verwenden.

von J. S. (jojos)


Lesenswert?

Reiner D. schrieb:
> Fock.*Fallinkrement ++ ;
1
(*Fallinkrement)++;

Fock gibt es in der ISR nicht wenn es nicht statisch ist.

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Fock.*Fallinkrement ++ ;

So wäre es richtig:

*Fallinkrement++

Du willst in der ISR auf den globalen Zeiger "Fallinkrement" zugreifen, 
nicht auf das Attribut der Instanz der "segel" Klasse. An dieser Stelle 
ist es unvorteilhaft, dass die globale Variable genau so heißt, wie das 
Attribut der Klasse. Nenne die Variable z.B. "FallinkrementPtr", dann 
wird es vielleicht klarer.

von Reiner D. (dollreiner)


Lesenswert?

Und wenn schon gerätselt wird ob meiner Intention :
Das Schiffchen krieg ich auch ohne Objekte zum fahren, das ist nicht das 
Thema. Es geht ums Lernen, hier insbesonders um Konzepte in OO. Für UML 
bin ich aber leider zu faul.

Wenn hier einer was von SPS versteht : so wie Lasal zum Beispiel, das 
fand ich konzeptuell extrem spannend. Brauchen tu ich's nicht.

Brauchen tu ich gar nix, hab die Rentengrenze längst überschritten :-))

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> *Fallinkrement++

Es gibt aber drei Fallinkremente.
Je eines vom Inkrementgeber an Fockfallwinde, Grossfallwinde und 
Besanfallwinde.

Wenn ich nur Objekte in main nutze (die Matrosen also quasi an Deck 
mitreden lasse) werden die durch Fock.Fallinrement, Gross.Fallinkrement 
usw. sauber unterschieden, wie es Attribute von Objekten eben tun.

Habe ich dich falsch verstanden, daß ich einen Zeiger im Konstruktorlauf 
machen kann, der dann dem Objekt zugeordnet ist ?

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Dann verstehe ich allerdings nicht, warum du hier Ratschläge zu
> C++ gibst. Für mich gehört es dazu, dass man auf der Höhe der
> Zeit ist, wenn man Ratschläge gibt.

OK, kann ich nachvollziehen.

MaWin O. schrieb:
>> das Zeiger-Konzept
> Bitte trenne dich davon. Es gibt hier keinen einzigen Grund einen Zeiger
> zu verwenden.

Ja dann gebe ihm doch ein besseres Beispiel, dass er umsetzen kann!

von J. S. (jojos)


Lesenswert?

Das ist schon der richtige Weg an solchen Übungsaufgaben zu lernen.

Solange das ganze Schiff und seine Besatzung statisch sind kann man 
alles global anlegen und braucht keine Zeiger. Wenn Segel statisch 
angelegt wird und den Fallinkrement Zeiger setzt, dann kann in der ISR 
auch gleich direkt auf das Objekt zugegriffen werden. Wie von  MaWin O 
schon gezeigt.

Interessant wird es wenn das ganze dynamisch wird, das Schiff z.B. aus 
einer Konfigurationsdatei zusammengesetzt wird. Dann spielt das OO 
Konzept seine Stärken aus.

: Bearbeitet durch User
von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Ja dann gebe ihm doch ein besseres Beispiel, dass er umsetzen kann!

Habe ich doch bereits.

Beitrag "Re: C++ Objektorientierung ?"

So geht das. Damit kann man auch alle Kompositionen abbilden.

MyClass kann natürlich Instanzen von anderen Klassen enthalten.


1
class MyClass2 {
2
public:
3
  void handle_irq2() {
4
     eigenschaft++;
5
  }
6
7
protected:
8
  int eigenschaft = 0;
9
};
10
11
class MyClass1 {
12
public:
13
  void handle_irq1() {
14
     myclass2.handle_irq2();
15
  }
16
17
protected:
18
  MyClass2 myclass2;
19
};
20
21
MyClass1 myclass1;
22
23
ISR() {
24
  myclass1.handle_irq1();
25
}

von J. S. (jojos)


Lesenswert?

In main wird nur ein Schiff instanziiert, main ist nur der Lebensraum 
für Objekte. Das Schiff hat Kapitän, Rudergänger, Matrose. Jetzt muss 
man überlegen was diese sein sollen, so wie du es wolltest sind es 
Dienstleister die etwas ausführen können (Methoden). Das Schiff hat auch 
verschiedene Segel oder Motoren, das sind auch Objekte die ein Schiff 
hat. Diese kann man auch statisch anlegen weil sie ja fest zum Schiff 
gehören.
Wenn ein Matrose jetzt ein Segel setzen soll, dann muss man ihm auch 
sagen welches. Das gross, besan usw. statisch angelegt wurden, können 
diese als Referenz übergeben werden. Das sind auch Zeiger, aber die 
werden nicht dynamisch angelegt und können damit nicht nullptr sein, das 
macht den Umgang angenehmer. Kann dann aber nicht dynamisch 
zusammengesetzt werden.
1
class Segel {
2
}
3
4
class Matrose {
5
  setzeSegel(Segel &segel);
6
}
7
8
class Schiff {
9
  Matrose hein;
10
  Matrose pit;
11
12
  Segel besan;
13
  Segel gross;
14
}
15
16
Schiff.hein.setzeSegel(besan);
17
Schiff.pit.setzeSegel(gross);

so grob.

von MaWin O. (mawin_original)


Lesenswert?

J. S. schrieb:
> Interessant wird es wenn das ganze dynamisch wird, das Schiff z.B. aus
> einer Konfigurationsdatei zusammengesetzt wird. Dann spielt das OO
> Konzept seine Stärken aus.

Richtig. Aber auch dann braucht man in C++ keine Rohzeiger.
Dann spielen Smartpointer ihre Stärken aus.

von Reiner D. (dollreiner)


Lesenswert?

J. S. schrieb:
> (Segel &segel)

Diesen Teil verstehe ich nicht

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Diesen Teil verstehe ich nicht

Dort wird eine eine Referenz auf das Segel an die Memberfunktion 
übergeben.
Über diese Referenz kann die Funktion auf das Segel zugreifen und es 
auch verändern.

von J. S. (jojos)


Lesenswert?

MaWin O. schrieb:
> Dann spielen Smartpointer ihre Stärken aus.

ja, ist mMn aber eine Feinheit die jetzt für ein Modell keine Rolle 
spielt. Die Smartpointer sollen ja z.B. die Speicherleck Probleme 
entschärfen. In C gibts malloc/free, es ist einfach die nicht balanziert 
aufzurufen.
Ich denke dem TO fehlt der Unterschied Zeiger und Referenz bzw. die 
Anwendung dieser.

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Es gibt aber drei Fallinkremente.

Folglich brauchst du drei Zeiger (oder Referenzen), die jeweils direkt 
auf die gewünschten Attribute zeigen, oder auf die Objekte, welche die 
Attribute enthalten.

Ich möchte daran erinnern, dass man eigentlich nicht an der 
Programmiersprache vorbei direkt auf Attribute der Objekte zugreifen 
soll. Außerdem sind diese drei Winden Bestandteil eines Schiffes, also 
genügt es, global auf das eine Schiff zu zeigen oder zu referenzieren:

Mit Referenzen:
1
class Winde {
2
  public:
3
    int fallinkrement;
4
};
5
6
class Schiff {
7
  public:
8
    Winde fockfallwinde;
9
    Winde grossfallwinde;
10
    Winde besanfallwinde;
11
};
12
13
Schiff schiff;
14
15
ISR whatever() {
16
    schiff.fockfallwinde.fallinkrement++;
17
    schiff.grossfallwinde.fallinkrement++;
18
    schiff.besanfallwinde.fallinkrement++;
19
}

Oder mit Zeigern und dynamischer Speicherverwaltung (bei 
Mikrocontrollern mit Fallstricken behaftet):
1
class Winde {
2
  public:
3
    int fallinkrement;
4
};
5
6
class Schiff {
7
  public:
8
    Winde* fockfallwinde;
9
    Winde* grossfallwinde;
10
    Winde* besanfallwinde;
11
    
12
    // Konstruktor
13
    Schiff() {
14
        fockfallwinde = new Winde();
15
        grossfallwinde = new Winde();
16
        besanfallwinde = new Winde();
17
    }
18
    
19
    // Destruktor
20
    ~Schiff() {
21
        delete fockfallwinde;
22
        delete grossfallwinde;
23
        delete besanfallwinde;
24
    }
25
};
26
27
Schiff* schiff;
28
29
int main() {
30
    schiff = new Schiff();
31
}
32
33
ISR whatever() {
34
    schiff->fockfallwinde->fallinkrement++;
35
    schiff->grossfallwinde->fallinkrement++;
36
    schiff->besanfallwinde->fallinkrement++;
37
}

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> Winde* fockfallwinde;
>
>     // Konstruktor
>     Schiff() {
>         fockfallwinde = new Winde();

Und wozu dynmische statt statische Allokation? Ich sehe hier keinen 
Grund für Zeiger und new.

von J. S. (jojos)


Lesenswert?

Reiner D. schrieb:
>> (Segel &segel)
>
> Diesen Teil verstehe ich nicht

ist vom erzeugten code wie ein Pointer
1
// Pointer
2
setze(Segel *segel) {
3
  segel->setze(50pct);  // wenn segel = nullptr ist, dann knallts
4
}
5
6
// Referenz
7
setze(Segel &segel) {
8
  segel.setze(50pct); // muss nicht auf nullptr geprüft werden
9
}

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Stefan F. schrieb:
> Ich möchte daran erinnern, dass man eigentlich nicht an der
> Programmiersprache vorbei direkt auf Attribute der Objekte zugreifen
> soll.

Jetzt eine Variante mit indirekten Zugriffen über Objektmethoden, was 
ich viel sauberer finde:
1
class Winde {
2
    int fallinkrement;
3
  
4
  public:
5
    void ändereIncrement(int wert)  {
6
        fallinkrement = fallinkrement+value;
7
    }
8
};
9
10
class Schiff {
11
    Winde fockfallwinde;
12
    Winde grossfallwinde;
13
    Winde besanfallwinde;
14
  
15
  public:
16
    void ändereIncrementDerWinden(int wert) {
17
        fockfallwinde.ändereIncrement(wert);
18
        grossfallwinde.ändereIncrement(wert);
19
        besanfallwinde.ändereIncrement(wert);        
20
    }
21
    
22
    Winde getFockfallwinde() {
23
        return fockfallwinde;
24
    }
25
    
26
    Winde getGossfallwinde() {
27
        return grossfallwinde;
28
    }
29
    
30
    Winde getBesanfallwinde() {
31
        return besanfallwinde;
32
    }
33
};
34
35
Schiff schiff;
36
37
ISR whatever() {
38
    schiff.ändereIncrementDerWinden(+1);
39
}
40
41
// oder:
42
43
ISR whatever2() {
44
    schiff.getFockfallwinde().ändereIncrement(+1);
45
    schiff.getGossfallwinde().ändereIncrement(+1);
46
    schiff.getBesanfallwinde().ändereIncrement(+1);
47
}

An den MaWin O hätte ich die Bitte, dieses Beispiel auf die neuen 
besseren Features von C++ 11 zu heben, die mir nicht bekannt sind. Dann 
müssten wir zu einem guten Schluss kommen, denke ich.

von J. S. (jojos)


Lesenswert?

Ein Objekt 'Winde' statt 'Segel' wie Stefan schrieb passt besser. Klasse 
Winde kann gleich sein für die Segel, als Segel würde dann ein enum { 
gross, besan, fock} reichen.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Und wozu dynmische statt statische Allokation? Ich sehe hier keinen
> Grund für Zeiger und new.

Ich habe ja das nur als Beispiel geschrieben, um die Syntax zu zeigen. 
Wie gesagt ist das auf Mikrocontrollern keine so gute Idee.

von MaWin O. (mawin_original)


Lesenswert?

Stefan F. schrieb:
> dieses Beispiel auf die neuen
> besseren Features von C++ 11 zu heben

Bis auf dass du die Referenzen der Rückgabewerte vergessen hast, sehr 
ich kein Problem. Ohne Referenzen funktioniert whatever2 auch in 
90er-C++ nicht.
1
    Winde getFockfallwinde() {
2
        return fockfallwinde;
3
    }

->
1
    Winde& getFockfallwinde() {
2
        return fockfallwinde;
3
    }

von Stefan F. (Gast)


Lesenswert?

J. S. schrieb:
> Ein Objekt 'Winde' statt 'Segel' wie Stefan schrieb passt besser. Klasse
> Winde kann gleich sein für die Segel, als Segel würde dann ein enum {
> gross, besan, fock} reichen.

Ja sorry, ich habe von Schiffen absolut keine Ahnung, deswegen sind 
meine Beispiele diesbezüglich vielleicht etwas holprig.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Bis auf dass du die Referenzen der Rückgabewerte vergessen hast

Upps, ja stimmt. So gebe ich nur Kopien der Winden zurück. Wenn danach 
die Kopien geändert werden, hat das keinen sinnvollen Effekt auf das 
Schiff.

von J. S. (jojos)


Lesenswert?

Stefan F. schrieb:
> Ja sorry, ich habe von Schiffen absolut keine Ahnung, deswegen sind
> meine Beispiele diesbezüglich vielleicht etwas holprig.

ich auch nicht, im Detail wird es irgendwann Geschmacksfrage und mehrere 
Lösungen sind möglich.
Wenn die Winden unterschiedliche Eigenschaften haben, dann können das 
verschiedene Objekte sein. Oder eine Basisklasse und die Varianten sind 
Ableitungen. Möglichkeiten gibt es viele.

Das dynamisch zu machen wäre wie genannt z.B. das Schiff aus einer 
Konfigdatei zu erstellen. Schönes Beispiel dafür ist 3D Drucker SW 
Marlin vs. Smoothieware: Marlin hat config in defines und Änderungen 
müssen neu kompiliert werden, Smoothie kann config aus Datei lesen und 
zur Laufzeit Pins zuordnen.

von Reiner D. (dollreiner)


Lesenswert?

Hab ich auch so probiert, und jetzt liegts wohl an meinem C-Gestammel :

class segel
{
  public :
    int FallInkrement;
};

class deckshand
{
  public :
    segel Fock;
    segel Besan;
};

In der main :

  deckshand Matrose;

In der ISR darunter :

ISR(..)
{
  Matrose.Fock.FallInkrement ++;
}


nix geht, Compilerfehler hier :    Matrose.Fock.FallInkrement ++ ;

von J. S. (jojos)


Lesenswert?

sieht nicht verkehrt aus. Üblicherweise schreibt man die Klassen groß, 
die Instanzen klein. Und zwischen Variable und ++ kein Leerzeichen, ist 
kein Fehler, sieht aber blöd aus.

Matrose muss global über der ISR angelegt sein. Wie ist die 
Fehlermeldung?

von Stefan F. (Gast)


Lesenswert?

J. S. schrieb:
> sieht nicht verkehrt aus

Finde ich auch. Bei mir compiliert das, wenn ich "ISR(..)" durch "void 
test()" ersetze, das liegt aber daran, dass ich mein Testprojekt als 
"Linux Desktop Anwendung" angelegt habe, statt für AVR.

Reiner D. schrieb:
> nix geht, Compilerfehler hier :    Matrose.Fock.FallInkrement ++ ;

Kann ich so nicht nachvollziehen. Zeige die ganze Fehlermeldung oder 
hänge dein Projekt in compilierbarer Form an, so dass wir den gleichen 
Fehler bekommen, wie du.

von Oliver S. (oliverso)


Lesenswert?

Stefan F. schrieb:
> Kann ich so nicht nachvollziehen.

Reiner D. schrieb:
> In der main :
>
>   deckshand Matrose;

Da Rainer nach wie vor main() und main.cpp fröhlich durcheinander wirft, 
könnte es sein, daß er diesmal tatsächlich main() meint. Und dann gehts 
natürlich nicht.

Oliver

von Reiner D. (dollreiner)


Angehängte Dateien:

Lesenswert?

Jetzt kapier ich erst, was du meinst.
Die Datei main.cpp (in der auch die ISR enthalten sind), und die main, 
in der die Endlosschleife zur Programmausführung läuft.
Ich war vermutlich ungenau mit der Bezeichnung ...

Ich hab das C::B - Projekt gezippt und angehängt.
Macht euch aber bitte nicht zuviel Arbeit.

Fehlermeldung :
main.cpp|138|error: 'class deckshand' has no member named 'Gross'|

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,
1
Fehlermeldung :
2
main.cpp|138|error: 'class deckshand' has no member named 'Gross'|
Dafür musst du nur in die deckshand.h reinschauen.
Gibt es einen Member namens "Gross"? Nein.
Du kannst mit deinen Objekten nur Member und Methoden verwenden die 
public zur Verfügung stehen. Wenn das deine eigenen Klassen sind 
solltest du das Wissen.

Selbst wenn du das
1
Matrose.Gross.KlauInkrement ++ ;
2
Matrose.Besan.KlauInkrement ++ ;
korrigierst auf
1
Matrose.KlauInkrement++ ;
2
Matrose.KlauInkrement++ ;
gibt es keinen Member namens "KlauInkrement". Weil Matrose ist ja eine 
Instanz von deckshand.

Fock, Gross und Besan sind Objekte von segel. Die können nur auf public 
von segel zugreifen.Hier steckt auch der Member KlauInkrement drin. 
Wahrscheinlich meinst du
1
Gross.KlauInkrement++ ;
2
Besan.KlauInkrement++ ;

Hier ist einfach zu viele Copy & Paste im Spiel. Erschwerend kommt hinzu 
das Gewürfel mit Groß- und Kleinschreibung. Schreibe Klassennamen 
Anfangs Groß und Member und Methoden Anfangs Klein. Zudem KlauInkrement 
unglücklich ist. Was machst beim Dekrementieren dieser Variablen?

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Reiner D. schrieb:
> class deckshand' has no member named 'Gross'

So ist es. In der Datei deckshand.h gibt es kein Gross. Wenn du auf ein 
Gross in deckshand zugreifen willst, muss es dort existieren.

Folgende Zeilen sind ähnlich fehlerhaft, das zeigt mir meine IDE (Qt 
Creator) schon vor dem Compilieren direkt im Texteditor an:

> Matrose.Gross.KlauInkrement ++ ;
> Matrose.Besan.KlauInkrement ++ ;
> Matrose.Fock.FallInkrement ++ ;
> Matrose.Gross.PiekInkrement ++ ;
> Matrose.Besan.PiekInkrement ++ ;

Matrose ist eine Instanz von deckshand. Deckshand enthält weder ein 
Gross, noch ein Besan, noch ein Deckshand.

KlauInkrement, PiekInkrement sind FallInkrement sind Attribute der 
Klasse segel. In deckshand.cpp gibt es drei globale (!) segel mit Namen 
Fock, Gross, und Besan. Diese sind also nicht Bestandteil von deckshand 
sondern davon völlig losgelöst.
Du musst die Segel in die Klasse deckshand verschieben. Siehe Anhang.

von Reiner D. (dollreiner)


Lesenswert?

Was hab ich bei der Übertragung des Beispiels von Stefan auf meinen Code 
falsch gemacht ?

Ich hab versucht, die Strutur so einzubauen, wie ich es bei Stefan 
verstanden habe....


(btw. nix copy+paste, alles selber zusammengefrickelt)

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Was hab ich bei der Übertragung des Beispiels von Stefan auf meinen Code
> falsch gemacht

Habe ich gerade erklärt, vermutlich hat sich meine Antwort mit deiner 
Frage zeitlich überschnitten. Scrolle mal nach oben.

von Wilhelm M. (wimalopaan)


Lesenswert?

Gute Güte; hast Du jemals in irgendeiner Sprache programmiert?

Und C++ lernt man nicht in einem µC Projekt. Nimm ein C++ Buch und fange 
ganz einfach auf dem PC bei Null an.

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> Du musst die Segel in die Klasse deckshand verschieben. Siehe Anhang.


Ich habe versucht, deine Struktur :

class Winde {
  public:
    int fallinkrement;
};
class Schiff {
  public:
    Winde fockfallwinde;
    Winde grossfallwinde;
    Winde besanfallwinde;
};
Schiff schiff;
ISR whatever() {
    schiff.fockfallwinde.fallinkrement++;
    schiff.grossfallwinde.fallinkrement++;
    schiff.besanfallwinde.fallinkrement++;
}

...auf die Meine zu übertragen.

Winde wird segel, schiff wird deckshand. In der ISR dann die 
entsprechenden Angabe.

Oh weh, ich kapier's nicht ...

von Stefan F. (Gast)


Lesenswert?

Weiter oben hat jemand bemängelt, dass hier das Schiff und die Matrosen 
zu sehr miteinander vermischt werden. Da hat er wohl Recht.

Die Matrosen sollten auf/mit dem Schiff arbeiten, aber nicht Bestandteil 
des Schiffes sein. Ebenso ist das Schiff kein Körperteil der Matrosen.

Das sollte man nochmal gründlich umstrukturieren.

von Jens R. (tmaniac)


Lesenswert?

Hmm deine Segel sind ja auch eigenschändig und schwirren irgendwo in 
deiner Welt herum.


Wenn du die Segel als Objekte deines Matrosen haben willst, dann 
solltest du das auch machen.

Das in deckshand.cpp
1
segel Fock;
2
segel Gross;
3
segel Besan;

muss dazu in deine Klasse deckshand hinein. also in deckshand.h
1
class deckshand
2
{
3
[.. hier dein ganzer anderer Kram]
4
5
segel Fock;
6
segel Gross;
7
segel Besan;
8
}

Aber man sollte auf Klassenmember nur über Methoden zu greifen. Also 
alles das was du da drin hast, sollte private sein.
Und nur die Methoden sollten public sein.

Wie schon gesagt, OO heißt auch dass man sich Gedanken über den Blick 
auf seine Welt macht. ;-)

[hui, sind hier einige schnell]

: Bearbeitet durch User
von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Reiner D. schrieb:
> Oh weh, ich kapier's nicht

Anbei die korrigierten Dateien.

Anderes Thema:
Füge bei Gelegenheit Include Guards in alle deine Header Dateien ein, 
damit sie keine Probleme machen, wenn sie mehrfach eingebunden werden. 
Beispiel:

schweinesteak.h
1
#ifndef SCHWEINESTEAK_H
2
#define SCHWEINESTEAK_H
3
4
class Schweinesteak {
5
    ...
6
}
7
#endif /* von SCHWEINESTEAK_H */

von Jens R. (tmaniac)


Lesenswert?

Reiner D. schrieb:
> Winde wird segel, schiff wird deckshand. In der ISR dann die
> entsprechenden Angabe.
>
> Oh weh, ich kapier's nicht ...

Dann solltest du aber auch beachten das Stefan die Winden-Objekte in der 
Klasse Schiff erzeugt hat. Und eben nicht im Luftleeren Raum einer 
anderen Datei.

von Sheeva P. (sheevaplug)


Lesenswert?

Stefan F. schrieb:
> Weiter oben hat jemand bemängelt, dass hier das Schiff und die Matrosen
> zu sehr miteinander vermischt werden. Da hat er wohl Recht.

Definitiv.

> Die Matrosen sollten auf/mit dem Schiff arbeiten, aber nicht Bestandteil
> des Schiffes sein. Ebenso ist das Schiff kein Körperteil der Matrosen.

Richtig, das Schiff hat mehrere Matrosen und ein Matrose hat maximal ein 
Schiff. Die können aber wechseln, dann hin und wieder geht so ein 
Matrose über Bord und muß im nächsten Hafen durch einen neuen ersetzt 
werden.

> Das sollte man nochmal gründlich umstrukturieren.

Ähnlich ist es mit den Aufgaben der einzelnen Matrosen. Die können auch 
nicht statisch verteilt werden, denn mitunter werden auch erfahrene 
Segler seekrank, verletzen sich, oder fallen anderweitig aus. Und wer 
Törns über längere Strecken fährt, braucht irgendwann einen 
Wachwechsel... auch dann müssen die Aufgaben neu verteilt werden.

von Wilhelm M. (wimalopaan)


Lesenswert?

Alles, was hir bisher geschrieben wurde, sind die absoluten Basics von 
OOP - eigentlich nicht mal das.

Ich steige mal an anderer Stelle: was soll denn die Klasse i2c 
modellieren? Ok, die TWI-Schnittsteller als I2C. Aber was erwartest Du 
von dem Konstruktor. Was passiert, wenn Du mehr als i2c-Objekt erzeugts?
Das ist übrigens bei allen Deine HW-Abstraktionen so.

von Reiner D. (dollreiner)


Lesenswert?

@Stefan (und die anderen Konstruktiven) :

Zuerst : DANKE !!

Beim Einbau deines Codes gabs zunächst Probleme, weil Code::Blocks sich 
daran stört, daß die Klasse und ein Attribut beide "segel" heißen.
Kein Problem, Attribut in "segelbefehl" umbenannt.

Läuft immer noch nicht. Die Definitionszeile "class segel" wird 
bemängelt :
segel.h|1|error: redefinition of 'class segel'|

Wenn ich jetzt "#include segel.h" aus der main nehme, gehts.
Wieso ? Die include-Zeile ist doch keine Definition der class segel, 
oder ?

Also : jetzt ist der Compiler zufrieden.
Hätte ich ohne eure Hilfe so nicht hingekriegt.
Und vor Allem : sowohl über Modellierung als auch über Pointer viel 
gelernt !!

von Sheeva P. (sheevaplug)


Lesenswert?

Reiner D. schrieb:
> Wenn ich jetzt "#include segel.h" aus der main nehme, gehts.
> Wieso ? Die include-Zeile ist doch keine Definition der class segel,
> oder ?

Bitte beachte Stefans Ausführungen zum Thema "Include Guards". Diese 
verhindern, daß dieselbe Datei mehrmals inkludiert wird, und es zu 
Fehlern wie "redefinition of 'class segel'" kommt.

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> Alles, was hir bisher geschrieben wurde, sind die absoluten Basics von
> OOP - eigentlich nicht mal das.

Das ist mir klar. Vor langer Zeit war das mal ein Versuch, die 
grundlegendsten Basics von Objektorientierung auszuprobieren.
Im Kern sollten nur die Begriffe : Klasse, Objekt, Methode, Attribut am 
Beispiel genutzt werden, völlig ohne Mdellierung usw...

So wie :

Klasse ist Obst
Objekt ist Apfel
Methode ist faulen
Attribut ist Farbe (Wert ist rot)

Na ja, und viel weiter bin ich dann in der Anwendung auch nicht 
gekommen.
Ich hab zwar mit Lasal und Codesys automatisiert und ein paar solche 
Modellprojekte programmiert, aber im strikt low(est) level.

Bin aber eben auch kein Programmierer ...

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Läuft immer noch nicht. Die Definitionszeile "class segel" wird
> bemängelt : > segel.h|1|error: redefinition of 'class segel'|
> Wenn ich jetzt "#include segel.h" aus der main nehme, gehts.
> Wieso ?

Weil die

Stefan F. schrieb:
> Include Guards

fehlen.

> Die include-Zeile ist doch keine Definition der class segel, oder ?

Die include Zeile nicht, aber der Inhalt der Datei die du an dieser 
Stelle includierst. Bevor dein Quelltext compiliert wird, wird die Zeile

> #include "segel.h"

durch den Inhalt der genannten Datei ersetzt. Du inkludierst aber auch

> #include "deckshand.h"

welche wiederum

> #include "segel.h"

includiert. Nun hast du den Inhalt der Datei segel.h zweimal in main.cpp 
eingefügt. Man kann halt nicht zwei (oder mehr) Klassen mit gleichem 
Namen haben.

von Jens R. (tmaniac)


Lesenswert?

Reiner D. schrieb:
> Wenn ich jetzt "#include segel.h" aus der main nehme, gehts.
> Wieso ? Die include-Zeile ist doch keine Definition der class segel,
> oder ?

Wie der Stefan dir vorgeschlagen hat solltest du deine Header mit 
include Guards versehen.

Ja die include-Zeile erzeugt eine Definition der class segel jedesmal 
wenn sie includiert wird.

wenn deine include.h so aussieht:
1
class segel
2
{
3
[irgendwas]
4
}

dann wird genau dieser Text bei jedem #inculde segel.h eingefügt.
Also im einfachsten Fall wird aus:
1
#include "segel.h"
2
[irgendwas anderes]
3
#include "segel.h"
folgendes:
1
class segel
2
{
3
[irgendwas]
4
}
5
[irgendwas anderes]
6
class segel
7
{
8
[irgendwas]
9
}

also füge in deiner segel.h ein
1
#ifdef SEGEL_INCLUDE
2
#define SEGEL_INCLUDE
3
4
class segel
5
{
6
[irgendwas]
7
}
8
#endif // ende von SEGEL_INCLUDE

Damit verhinderst du dass es mehrmals eingefügt wird
Das sind aber absolute Basics in der ganzen C-Welt

von Stefan F. (Gast)


Lesenswert?

Ich kann dir auch nur dringend empfehlen, die Programmiersprache auf 
einem PC zu lernen/üben.

Mikrocontroller legen da noch einiges an Komplexität oben drauf und sind 
schwerer zu debuggen. Es ist gut, wenn man die Sprache dann schon in den 
Grundzügen verstanden hat und wenigstens ein bisschen Erfahrung 
gesammelt hat.

Du könntest z.B. mein Tutorial durch gehen, und danach ein Program,m 
schreiben, dass ein Schiff auf den Bildschirm malt. Natürlich indem du 
es schön aus Objekten zusammen setzt. Du wirst dabei viel lernen.

Siehe http://stefanfrings.de/qt_lernen/index.html

von Reiner D. (dollreiner)


Lesenswert?

Sheeva P. schrieb:
> Bitte beachte Stefans Ausführungen zum Thema "Include Guards"

Im Eifer des Gefechts vernachlässigt.
Hab jetzt erst mal nachgelesen, was das tut.

Bisher hab ich diese Zeilen immer aus neuen class-Definitionen 
rausgelöscht, weil ich bloß Code haben will, den ich auch verstehe. Rein 
zufällig gabs bisher damit keine Probleme. Conclusio : nochmal was 
gelernt !

von Veit D. (devil-elec)


Lesenswert?

Hallo,

Hinweis am Rande. Verwende gleich pragma in den Headerfiles.
1
#pragma once
2
3
class segel
4
{
5
  // ... irgendwas etwas sinnvolles ...
6
}

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Reiner D. schrieb:
> Klasse ist Obst
> Objekt ist Apfel

Schon falsch.

Apfel ist auch eine Klasse, und zwar von Obst abgeleitet. Das Bild zeigt 
drei Instanzen von der Klasse Apfel, oder anders gesagt, drei Objekte 
oder drei Ausprägungen.

Ein Objekt ist ein Ding, das man erzeugen, anfassen und benutzen kann. 
Eine Klasse beschreibt nur die Eigenschaften einer Klasse von Objekten, 
ist aber keine konkrete Ausprägung.

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> Siehe http://stefanfrings.de/qt_lernen/index.html

Ein Traum.
Kleiner bescheidener Satz : Ihr würdet nicht glauben, wie weit man mit 
so einer Murkserei kommt. Hab bisher noch alles zum Laufen gekriegt, 
aber (wichtig !) nie in professionellem (!) Kontext von 
Softwareentwicklung.
Ich sehe das wie meinen Fernseher : da kapier ich 90% vom Menü auch 
nicht

von Veit D. (devil-elec)


Lesenswert?

Veit D. schrieb:

Korrektur. Segel als Klassenname sollte Groß geschrieben werden.

> Hallo,
>
> Hinweis am Rande. Verwende gleich pragma in den Headerfiles.
1
#pragma once
2
 
3
class Segel
4
{
5
   // ... irgendwas etwas sinnvolles ...
6
}

Ansonsten empfehle ich Reiner sich nochmal im Kleinen mit Klassen zu 
beschäftigen. Man sieht ja das du in deinen eigenen Klassen nicht 
durchblickst. Nochmal paar Schritte zurückgehen und den Aufbau 
überdenken.

: Bearbeitet durch User
von Reiner D. (dollreiner)


Lesenswert?

Hatte ich irgendwann im PHP-Zusammenhang zitiert :

Classes are nothing without objects! We can create multiple objects from 
a class. Each object has all the properties and methods defined in the 
class, but they will have different property values.
$apple and $banana are instances of the class Fruit

Auch "godfather of education", (die Uni Harvard), nimmt dieses Beispiel 
in der Einführungsvorlesung "Objektorientierung"

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Ihr würdet nicht glauben, wie weit man mit
> so einer Murkserei kommt

Oh doch. Ich (bzw mein Chef) hat damit gut Geld verdient.

Ich sage immer: Softwareentwicklung ist wie ein Adventure spiel. Zuerst 
muss man herausfinden, was überhaupt machen soll, was das Ziel ist. Dann 
muss man heraus finden, wie man da hin kommt. Dabei macht man viele 
Fehler, manche mehrfach. Und wenn man es dann am Ende geschafft hat, 
kommt schon das nächste Projekt mit neuen Herausforderungen.

von Reiner D. (dollreiner)


Lesenswert?

Zur Abrundung sei noch der Gegenstand gezeigt, damit man sehen kann, 
wovon hier geredet wird :

https://www.schiffsmodell.net/index.php?/forums/topic/18743-baubericht-eines-anf%C3%A4ngers-hf31-maria/

Beitrag #7384998 wurde vom Autor gelöscht.
von Hans-Georg L. (h-g-l)


Lesenswert?

Das Konzept ist ja auch wirr ;-)

Wenn du eine Simulation schreiben wolltest und Kapitän, Matrosen usw 
wären Spielfiguren dann wären Klassen dafür sinnvoll.
Aber für ein Modellschiff mit einem AVR zu steuern ???

Du bist der Kapitän mit deiner Fernsteuerung in der Hand, der Empfänger 
mit dem AVR sind deine Offiziere die deine Befehle als Aktionen an die 
Matrosen(Servo) weiter geben.

von Reiner D. (dollreiner)


Lesenswert?

Weit gefehlt ! Der AVR ist sogar eigentlich zu klein, mir gehen sowohl 
die externen Interrupts (deshalb die PCINT) als auch die Timer aus, ich 
muß sogar Timer multiplexen... Wenn ichs nochmal bauen würde, würde ich 
die Navigation und den Skipper wohl mit einem Raspi unter Python machen, 
zwecks der Gaudi.

Das Ding soll :

Ferngesteuert fahren (na ja, kein Ding, da hast du recht..).
Alle Segel bergen und setzen können (kann kaum ein Modellboot).
Auf Wunsch viele Waypoints (GPS-Koordinaten) unter Motor anfahren können 
mit FPV, also einer Funkkamera, die zeigt, was da zu sehen ist.
Bei Senderausfall (oder einfach ausschalten) automatisch Segel bergen 
und zum Ausgangspunkt ("home") unter Motor zurückfahren.

Die härteste Forderung, nämlich unter Segeln Waypoints anzufahren, habe 
ich zurückgestellt. Einen reibungsfreien Verklicker habe ich zwar 
gebaut, aber die Kreuz gegen den Wind macht Schwierigkeiten.

von Stefan F. (Gast)


Lesenswert?

Ich habe das Gefühl, dass du zu viel mit Interrupts umsetzen willst.

Man kann Eingänge auch nacheinander abfragen. Multitasking kann man mit 
mehreren parallel ablaufenden Zustandsautomaten erreichen.

Interrupts benutzt man typischerweise nur dort, wo es unbedingt 
notwendig ist, die laufende Arbeit sofort zu unterbrechen um auf das 
Ereignis schnellstmöglich (binnen weniger Millisekunden oder noch 
schneller) zu reagieren.

Zum Beispiel nutzt man eine ISR, um seriell empfangene Bytes in einen 
Puffer zu übertragen. Schließlich wartet der Sender der Daten nicht den 
Moment ab, wo du empfangsbereit ist. Die Verarbeitung der Daten sollte 
aber nicht in der ISR stattfinden.

Einen Schaltkontakt sollte man aber normalerweise nicht an eine ISR 
koppeln, sondern aktiv abfragen.

Mit zu vielen Interrupts verzettelt man sich ganz schnell. Bedenke, dass 
dein AVR sowieso nur eine ISR gleichzeitig ausführen kann. Alle anderen 
Interrupts müssen eh warten, bis er wieder ins Hauptprogramm 
zurückgekehrt ist. Durch viele Interrupts wird die Abarbeitung von 
Ereignissen unter Umständen sogar langsamer, als eine sequentielle 
Abfrage der Eingänge im Hauptprogramm.

Wenn man mal bedenkt, dass kein Motor so schnell anlaufen und stoppen 
kann, frage ich mich, was das in deiner Anwendung wohl sein mag. 
Empfangene Kommandos in einen Puffer eintragen wäre ein Fall. Und sonst? 
Wofür brauchst du Interrupts?

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Weit gefehlt ! Der AVR ist sogar eigentlich zu klein, mir gehen sowohl
> die externen Interrupts (deshalb die PCINT) als auch die Timer aus, ich
> muß sogar Timer multiplexen...

Dann ist was falsch an Deinem Konzept.

Den Empfänger hast Du bestimmt über SBus, IBus oder Hott angeschlossen, 
das ist eine serielle Schnittstelle -> UART

Das hast Du ggf. Telemetrie über SPort, IBus oder Hott-Sensor, ebenfalls 
seriell -> der 2. UART

Dann liest Du GPS -> der 3. Uart

Dann produzierst Du PWM für die Servos -> 1 Timer (bis zu 16 Servos)

Was brauchst Du noch?

von Reiner D. (dollreiner)


Lesenswert?

//Timer 0 : PPM-Generator (für Servos und RC-Winden)
//Timer 1 : 10HZ-Generator für NPRM-Scheduler
//Timer 2 : PWM-Generator (CompA für Maschine )
//Timer 3 : PPM-Decoder (vom RC-Sender)
//Timer 4 : PWM für Fall-Winden in Gruppen
//Timer 5 : Entprellung der Inkrementgeber
//UART0 : USB zum PC
//UART1 : GPS

Klar könnte ich z.b. die Motorsteuerung mit nem Brushless und einem 
Stellerl machen, oder ein "Fahrtregler" für den DC-Motor. Aber warum 
kaufen, wenn das auch mit Software geht. Mein Empfänger kann nicht 
seriell, also Auswertung des PPM-Summensignals. Die Winden brauchen 
Inkrementgeber, weil ich die Wege und die Geschwindigkeit steuern will, 
also Interrupts. Die Inkrementgeber "prellen" beim 1/0-Übergang, wohl 
optische Gründe, könnte man auch filtern, aber SW ist lustiger. Und für 
Regler und digitale Filter brauche ich harte Echtzeit, also der 
Scheduler.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Ich steuere dir mit einem einzigen 8 Bit Timer 10 Servos an. Jemandem, 
der in Software nicht nicht so fit ist, würde ein PC9685 Modul 
empfehlen.

> Timer 1 : 10HZ-Generator für NPRM-Scheduler
> Timer 5 : Entprellung der Inkrementgeber

Ich würde wie bei Arduino einen millis() Timer und alle andere Zeiten 
per Software davon ableiten.

von Reiner D. (dollreiner)


Lesenswert?

Ein paar andere Spielsachen wären noch in der Queue :

Ein Katamaran, der geregelt auf einer Kufe fährt
Eine Modellrakete, die wie ein Cruise-missile fliegt

immer mit nem Arduinio nano denke ich ...

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Ein Katamaran, der geregelt auf einer Kufe fährt
> Eine Modellrakete, die wie ein Cruise-missile fliegt

Werde nicht albern, lerne erst mal programmieren.

Hast du eigentlich einen Debugger? Wenn nicht, dann ist jetzt vielleicht 
noch eine gute Gelegenheit, den ATmega 2560 (?) durch ein STM32 Nucleo 
Board zu ersetzen, da hast du den Debugger direkt mit drauf.

von MaWin O. (mawin_original)


Lesenswert?

Ja, also das wird sicher mit AVR machbar sein.
Aber ich würde mir das in diesem Fall heute auch nicht mehr mit AVR 
antun, wenn es nicht unbedingt sein muss.
Da würde ich eher einen billigen 32-Bit Mikrocontroller wie z.B. den 
ESP32 nehmen. Die maximal paar Milliwatt Mehrverbrauch fallen hier gar 
nicht ins Gewicht.
Den kann man dann auch in Python programmieren, wenn man das möchte. 
Oder halt auch in vielen compilierten Sprachen wie C, C++ und Rust.

AVR nutze ich eigentlich nur noch da, wo es auf absolut geringen 
Energieverbrauch ankommt, oder wo die Anwendung trivial ist.

Außerdem würde ich unabhängig vom Controller so wenig Hardwaretimer wie 
möglich einsetzen. Ein simples Realtime-Scheduling mit festen 
Zeitscheiben ist viel einfacher und IMO auch robuster als etliche 
Interrupts, die sich ständig unterbrechen können. Das Scheduling kann 
von einem HW-Timer ableiten.

Die restlichen HW-Timer dann für z.B. PWM, was autonom in HW generiert 
wird.

Außerdem würde ich die Aktivitäten in den verbliebenen Interrupt Service 
Routinen auf das absolute Minimum beschränken.

Einfacher ist besser.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Einfacher ist besser.

Definitiv. KISS

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Eine Modellrakete, die wie ein Cruise-missile fliegt

Na klar. Raketentechnik.
Wenn das mal kein Anfängerprojekt ist.

von Stefan F. (Gast)


Lesenswert?

MaWin O. schrieb:
> Na klar. Raketentechnik.
> Wenn das mal kein Anfängerprojekt ist.

Die Ariane 5 konnte fliegen, leider nur ein Stück weit.
https://www.golem.de/news/softwarefehler-in-der-raumfahrt-in-den-neunzigern-stuerzte-alles-ab-1511-117537-3.html

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> Ich steuere dir mit einem einzigen 8 Bit Timer 10 Servos an.

Ja, ich auch. Brauche aber nicht so viele ;-)

ISR(TIMER0_COMPA_vect)
{
    TCCR0B = 0;                     //zähler aus
    PORTA = PORTA & 248;            //alle Pins auf 0
    servo = servo + 1;
    if (servo > 4)
    {
        servo = 1;
    }
    //--------------------------------------
    if (servo == 1)
    {
        PORTA |= 1;                 //Pin 22, Port A0 -> Ruder ist servo 
1
        OCR0A = Matrose.ruderwinkelsollwert;
        TCCR0B = 4;                 //timer zählt los mit prescaler 256 
(16us)
    }
    if (servo == 2)
    {
        PORTA |= 2;                 //Pin 23, Port A1 -> Gaffel ist 
servo 2
        OCR0A = Matrose.gaffelschotsollwert;
        TCCR0B = 4;                 //timer zählt los mit prescaler 256 
(16 us)
    }
    if (servo == 3)
    {
        PORTA |= 4;                 //Pin 24, Port A2 -> Fock ist servo 
3
        OCR0A = Matrose.fockschotsollwert;
        TCCR0B = 4;                 //timer zählt los mit prescaler 256 
(16 us)
    }
    //-----------------------------------------
    if (servo == 4)
    {
        OCR0A = 255;                //Maximalwert, rund 13 ms Pause
        TCCR0B = 5;                 //timer zählt los mit prescaler 1024 
(80us)
    }
}

von Stefan F. (Gast)


Lesenswert?

Reiner D. schrieb:
> Ja, ich auch.

Gut, hätte ich ähnlich gemacht.

von Reiner D. (dollreiner)


Lesenswert?

Bei all diesen Projekten ist der uC nicht das Problem, oder ob das 
schönes C wird, sondern eher die Regelungstechnik (und bei der Rakete 
vielleicht die Servogeschwindigkeit). Versuche sind schon gelaufen.

Andere Beispiele für echt harte Regelprojekte : Quadrocopter oder 
self-balancing (siehe segway).

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> Gut, hätte ich ähnlich gemacht.

versteh mich nicht falsch. du kannst das 10mal besser.

von M. K. (sylaina)


Lesenswert?

Reiner D. schrieb:
> ...
>         OCR0A = Matrose.ruderwinkelsollwert;
>         TCCR0B = 4;                 //timer zählt los mit prescaler 256
> ...

Mich würden da ja die Magic Numbers stören. Aber sonst schauts 
eigentlich OK aus.

von Reiner D. (dollreiner)


Lesenswert?

Stefan F. schrieb:
> Gut, hätte ich ähnlich gemacht.

das ehrt mich ..

von Reiner D. (dollreiner)


Lesenswert?

M. K. schrieb:
> Mich würden da ja die Magic Numbers stören. Aber sonst schauts
> eigentlich OK aus.

weiß schon, ist halt ne alte angewohnheit aus maschinensprache-tagen

von Hans-Georg L. (h-g-l)


Lesenswert?

Überschrift war OO mit C++
Wahrscheinlich wird dieses Kapitän-Matrosen Pattern in die Software 
Geschichte eingehen .... ;-)

Beitrag #7385223 wurde vom Autor gelöscht.
von Sheeva P. (sheevaplug)


Angehängte Dateien:

Lesenswert?

Hans-Georg L. schrieb:
> Überschrift war OO mit C++

Bitte entschuldige, was möchtest Du uns damit sagen?

> Wahrscheinlich wird dieses Kapitän-Matrosen Pattern in die Software
> Geschichte eingehen .... ;-)

Ja, vermutlich, vor allem, wenn es jemand in C++ sauber implementiert 
und seine Lösung hier zeigt (ich persönlich würde ja auf Wimalopaan 
tippen).

Nun, ich hab's mal in Python gebastelt, nur so aus Spaß, und natürlich 
ist das ein totaler Pipifax. Trotzdem: HF und YMMV.

PS: Sorry für das off-topic, lieber TO. Viel Glück und Erfolg bei Deinem 
spannenden und interessanten Segelprojekt! ;-)

PPS: Verdammt, jetzt aber... ;-)

: Bearbeitet durch User
von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> //Timer 0 : PPM-Generator (für Servos und RC-Winden)
> //Timer 1 : 10HZ-Generator für NPRM-Scheduler
> //Timer 2 : PWM-Generator (CompA für Maschine )
> //Timer 3 : PPM-Decoder (vom RC-Sender)
> //Timer 4 : PWM für Fall-Winden in Gruppen
> //Timer 5 : Entprellung der Inkrementgeber
> //UART0 : USB zum PC
> //UART1 : GPS

Timer5 brauchst Du nicht bzw. kannst das mit Deinem Timer1 
zusammenfassen.

Und warum brauchst Du so viele externe PinChange-Interrupts?

von Wilhelm M. (wimalopaan)


Lesenswert?

Wilhelm M. schrieb:
> Ich steige mal an anderer Stelle: was soll denn die Klasse i2c
> modellieren? Ok, die TWI-Schnittsteller als I2C. Aber was erwartest Du
> von dem Konstruktor. Was passiert, wenn Du mehr als i2c-Objekt erzeugts?
> Das ist übrigens bei allen Deine HW-Abstraktionen so.

Diesem Problem solltest Du Dich auch noch mal stellen (s.a. scheduler).

: Bearbeitet durch User
von Reiner D. (dollreiner)


Lesenswert?

Sheeva P. schrieb:
> Nun, ich hab's mal in Python gebastelt

@sheeva :

Find ich extrem spannend. Ich hab die letzten Jahre viel mir Python 
gespielt, natürlich nicht auf deinem Niveau, und rumgesucht, ob das auch 
auf dem AVR möglich ist. Ich hab leider nix vernünftiges gefunden.
Wenn du erlaubst, stelle ich dir dazu später ein paar Fragen. Soll ich 
da ein extra topic machen, oder wie geht das ?

von Reiner D. (dollreiner)


Angehängte Dateien:

Lesenswert?

Wilhelm M. schrieb:
> brauchst Du so viele externe PinChange-Interrupts?

Ich hab aktuell 5 Winden, es sind aber noch drei Segel ausstehend 
(nochmal  Winden) jede Winde einen Inkrementgeber, weil ich nicht bloß 
ein/aus steuern möchte.

Die normalen externen Interrupts sind schon überwiegend belegt an den 
Ports, und umlöten tun ich da nix mehr (du kannst dir vermutlich 
vorstellen, wie die Platine von hinten aussieht, wenn ein 65-jähriger 
mit Zitterfingern so einen Haufen Zeug mit Draht frei verlötet ;-).

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> Timer5 brauchst Du nicht bzw. kannst das mit Deinem Timer1
> zusammenfassen.

Das Problem liegt andersrum.

Ich habe da einen Fehler im System : die Inkrementgeber "prellen", 
wahrscheinlich springt die Optik kurz nach der Kante ein paarmal hin-und 
her.
Wenn ich nur einen Timer dafür benutze (klassische bounce-Lösung mit 
Totzeit),
kann nur eine Winde zu einer Zeit laufen : sehr unsportlich !
Ich bräuchte im Kern sehr viele Timer um parallel setzen/bergen/reffen 
zu können, einen pro aktiver Winde.

Grübel. Hardwarelösung, also rummessen, analogen Filter entwerfen, oder 
einen Coprozessor (AtMegas hab ich genug). Weiß nicht. uP ist lustiger.

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> Diesem Problem solltest Du Dich auch noch mal stellen (s.a. scheduler).

Ich weiß. Die OO für die HW-Komponenten kommt aus einem anderen (alten) 
Projekt, und passt nicht ins Modell, das ist mir klar. Damals hatte ich 
einfach ausprobiert, ob ich die SW-Struktur mit Objekten, Methode usw. 
überhaupt zum Laufen kriege.

von Wilhelm M. (wimalopaan)


Lesenswert?

Vielleicht nochmal grundsätzlich: der Titel ist "C++ 
Objektorientierung". Dir sollte bewusst sein, dass C++ keine rein 
objektorientierte Programmiersprache ist. Sondern C++ ist eine Sprache, 
mit der man auch(!) objektorientiert programmieren kann. Aber auch 
anders: imperativ-prozedural, funktional, generisch, 
meta-programmatisch, ...

Und der Code, den Du vorgestellt hast, ist mitnichten OOP. Denn die 
Grundprinzipien von OOP sind Kapselung in Klassen, Vererbung, 
Polymorphie und spätes Binden. Von diesen Prinzipien hast Du nichts 
umgesetzt.

Außerdem ist Deine Anwendung wohl so, dass Du auch nicht direkt OOP 
benötigst, da so ziemlich alles statisch.

Aber auch ist Dein Ansatz noch nicht einmal konsequent objektbasiert.

Zudem hast Du auch Klassen die etwas der internen Peripherie modellieren 
sollen. Hier ist es konzeptionell falsch, Instanzen von Klassen zu 
erzeugen, es sei denn, Du verwendest ein Muster zur Kapselung von 
globalen Zuständen in multiplen Instanzen wie etwas das 
Monostate-Pattern.

Also alles in allem: so wie Du das anfängst, hast Du keinerlei Vorteile 
gegenüber rein imperativ-prozeduraler Vorgehensweise. Und OOP lernt man 
nicht mit µC, sondern ganz normal auch dem PC. Aber da wiederhole ich 
mich.

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> Hier ist es konzeptionell falsch, Instanzen von Klassen zu
> erzeugen,

Wieso ?
Daß es zum Modell nicht passt ist eine Sache, aber warum darf eine 
funktionierende Programmiertechnik quasi "grundsätzlich" nicht für dies 
oder das benutzt werden ?

Ähnlich Frage :
(Ich weiß, ist sakrosankt) Wieso immer Kapselung ? Ich verstehe die 
Vorteile in entsprechendem Kontext. Aber in so einem kleinen 
Projektchen, das nicht im Team entwickelt wird ? so what ? alles public 
und fertig ...

Laß mich ein Beispiel geben : wenn ich am Holm eines großen 
Segelflugzeuges klebe, nehme ich das beste Epoxi und mache vorher einen 
Klebekurs.
Bei Spielzeug klebe ich mit Uhu, fertig.

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Wieso ?
> Daß es zum Modell nicht passt ist eine Sache, aber warum darf eine
> funktionierende Programmiertechnik quasi "grundsätzlich" nicht für dies
> oder das benutzt werden ?

Stellt Dir vor, Du erzeugst an unterschiedlichen Stellen in Deinem Code 
mehrere Instanzen der Klasse "scheduler" oder "i2c". Was erwartest Du, 
was dann passiert?

Ich habe nicht gesagt "grundsätzlich" falsch, sondern konzeptionell 
falsch.

von Reiner D. (dollreiner)


Lesenswert?

Das ist jetzt Nachhilfe pur, und ich danke dir dafür !

Ich schätze mal, mehrere Instanzen von I2C werden rein softwaremäßig 
funktionieren.( Wobei ich das Problem, das bei mehrmaligem include einer 
.h passiert, und mit "Include Guards" gelöst wird, noch nicht so genau 
verstanden habe)

Wenn dann aber die verschiedenen Objekte auf die nur einmal vorhandene 
Hardware zugreifen, knirscht es aber. Es mag mulitinstanzfähige Lösungen 
geben, die auf dem AVR ist es sicher nicht.

So war es aber auch nie gedacht, es ging damals nur um die 
Funktionsfähigkeit des Syntax-Gebäudes "Klasse-Objekt-Attribut usw...".

Und, auch akzeptiert : das muß raus aus dem Schifferl ;-)

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Ich schätze mal, mehrere Instanzen von I2C werden rein softwaremäßig
> funktionieren.( Wobei ich das Problem, das bei mehrmaligem include einer
> .h passiert, und mit "Include Guards" gelöst wird, noch nicht so genau
> verstanden habe)

Hier verwechselst Du "nicht compilieren" mit "zur Laufzeit was Falsches 
machen".

Das Thema "include guard" ist ein simples Thema der Strukturierung des 
Codes innerhalb der Übersetzungseinheiten. Hier hast Du in C++ alle 
Freiheiten, Hauptsache Du machst es richtig. Trotzdem gibt es ein 
übliches Verfahren, etwa die Klassendefinition und Definition der 
Elementfunktionen in Header und Implementierungsdatei zu unterteilen. 
Zusammen mit include-guards hilft dies zuverlässig, die ODR einzuhalten 
und Mehrfachdefinitionen innerhalb einer Übersetzungseinheit 
auszuschließen.

Das hat aber nicht mit dem Laufzeitproblem zu tun, was ich angesprochen 
habe.

Mehrere Exemplare des Typ i2c werden natürlich irgendwie 
"funktionieren", aber nicht das tun, was Du willst. Das ist dann ein 
semantisches Problem. Und ja, Du hast es erkannt: Objekte, die nicht 
ihren eigenen Zustand, sondern einen globalen Zustand (der, der internen 
Peripherie) modellieren sollen, benötigen besonderes Augenmerk. Eine 
Lösung ist das Monostate-Pattern. Eine andere ist es, eine Klasse nur 
mit static Elementen zu schreiben und es zu verbieten, Objekte davon zu 
erzeugen.

von Hans-Georg L. (h-g-l)


Lesenswert?

Sheeva P. schrieb:
> Hans-Georg L. schrieb:
>> Überschrift war OO mit C++
>
> Bitte entschuldige, was möchtest Du uns damit sagen?
>
Das die Überschrift mit dem Thread nichts mehr zu tun hat.

> Ja, vermutlich, vor allem, wenn es jemand in C++ sauber implementiert
> und seine Lösung hier zeigt (ich persönlich würde ja auf Wimalopaan
> tippen).
Auch dann wird es kein OO und kein C++ sein ;-)

Das Thema selbst ist sehr interessant und ich wünsche viel Erfolg !

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Es mag mulitinstanzfähige Lösungen
> geben, die auf dem AVR ist es sicher nicht.

Mit AVR hat das nichts zu tun: es ist einfach ein konzeptionelles 
Problem, also wie modelliere ich was.

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> So war es aber auch nie gedacht, es ging damals nur um die
> Funktionsfähigkeit des Syntax-Gebäudes "Klasse-Objekt-Attribut usw...".

Auch hat das nichts mit Syntax zu tun. Bitte kläre einige Begriffe, 
bevor Du sie benutzt.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Reiner D. schrieb:
> Laß mich ein Beispiel geben : wenn ich am Holm eines großen
> Segelflugzeuges klebe, nehme ich das beste Epoxi und mache vorher einen
> Klebekurs.
> Bei Spielzeug klebe ich mit Uhu, fertig.

Ob Hobbybastler oder Profi....
Beide wollen am Ende eine funktionierende/stabile Software.
So verwenden auch beide die gleichen Techniken.
Manches mal sind die Hobby Leute gar noch verbissener.

Reiner D. schrieb:
> alles public und fertig ...
Herrlich!

Natürlich kann man mit einer Tasse einen Nagel in die Wand hauen.
Es zumindest versuchen.
Oder bei einem Auto 3 Türen zuschweißen.

Einer der gewichtigsten Gründe für OOP ist eben die Kapselung. Die 
hoffentlich damit einhergehende leichte Wiederverwend-, Test- und 
Wartbarkeit.

Natürlich darfst du das in den Wind schlagen.

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> Mit AVR hat das nichts zu tun:

Im Sinne der Nachhilfe nachgefragt :

Ich kenne aus der Industriewelt multiinstanzfähige HW, die also mehrere 
"gleichzeitige" Requests auffangen und geordnet abarbeiten kann. Hätte 
der I2C-Teil im AVR diese Fähigkeit, wären die parallelen Instanzen wohl 
möglich, oder ?

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Wilhelm M. schrieb:
>> Mit AVR hat das nichts zu tun:
>
> Im Sinne der Nachhilfe nachgefragt :
>
> Ich kenne aus der Industriewelt multiinstanzfähige HW, die also mehrere
> "gleichzeitige" Requests auffangen und geordnet abarbeiten kann. Hätte
> der I2C-Teil im AVR diese Fähigkeit, wären die parallelen Instanzen wohl
> möglich, oder ?

Die hast Du ja auch bei AVR: es gibt mehrere HW-Instanzen eines UART ;-)

Jetzt benötigst Du idealerweise eine Lösung, die es Dir erlaubt, passend 
zu den 3 HW-Uarts auch drei unterschiedliche Instanzen zu erzeugen: 
Instanz 1 bezieht sich auf Uart 1, Instanz 2 bezieht sich auch Uart 2, 
u.s.w., Instanz 42 bezieht sich auf ... was? Und idealerweise sollte 
dies Problem nicht erst zur Laufzeit auftauchen, sondern zur 
Compilezeit.

In C++ gibt es noch eine Art von "Instanz", und zwar wenn man aus einem 
Template eine Klasse erzeugt spricht man auch von Instanziieren eines 
Templates. Denn instanziieren bedeutet nur, aus etwas Abstraktem etwas 
Konkretes zu erzeugen: aus einer Klasse ein Objekt, oder aus einem 
Template eine Klasse.
Der Template-Instanziierungsprozess läuft zur Compilezeit, und deswegen 
kann man hier dann die obige Prüfung einbauen, damit eine fehlerhafte 
Parametrierung gar nicht erst compiliert. Laufzeitfehler zu suchen is 
hässlich ;-)

von Εrnst B. (ernst)


Lesenswert?

Reiner D. schrieb:
> Hätte
> der I2C-Teil im AVR diese Fähigkeit, wären die parallelen Instanzen wohl
> möglich, oder ?

Auch mit nur einem Hardware-I2C steht dir frei, weitere 
(Software-Simulierte) I²C-Busse zu instanziieren, bei Arduino: "class 
SoftWire".

Und bei AVRs mit mehreren UARTs ist es auch üblich, dass da mehrere 
Serial-Objekte (+ ggfs. SoftSerial) instanziiert sind.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Reiner D. schrieb:
> die also mehrere
> "gleichzeitige" Requests auffangen und geordnet abarbeiten kann. Hätte
> der I2C-Teil im AVR diese Fähigkeit,
Hätte hätte Fahrradkette ....

I2C kann genau das, was im I2C Standard beschreiben ist
Mehrere I2C Ports, dann auch mehrere z.B. Wire Instanzen.

: Bearbeitet durch User
von Reiner D. (dollreiner)


Lesenswert?

Arduino F. schrieb:
> Mehrere I2C Ports, dann auch mehrere z.B. Wire Instanzen.

nochmal nachgefragt : Ich kann z.B auf dem AtMega256 aus zwei Instanzen 
"gleichzeitig" (also innerhalb des Befehlszyklus) auf die 
I2C-Schnittstelle zugreifen (also z.b. zwei verschiedene 
Peripheriegeräte abfragen) ??

von M. K. (sylaina)


Lesenswert?

Reiner D. schrieb:
> alles public
> und fertig ...

Also mal ein recht simples Beispiel: Wie sinnvoll wäre es bei deinem 
Segelschiff, wenn das Focksegel dem Kapitän sagen kann: Alle über Board?

Wenn du alles public machst ist es nur eine Frage der Zeit bis dein 
Schoner auf Grund läuft.

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Arduino F. schrieb:
>> Mehrere I2C Ports, dann auch mehrere z.B. Wire Instanzen.
>
> nochmal nachgefragt : Ich kann z.B auf dem AtMega256 aus zwei Instanzen
> "gleichzeitig" (also innerhalb des Befehlszyklus) auf die
> I2C-Schnittstelle zugreifen (also z.b. zwei verschiedene
> Peripheriegeräte abfragen) ??

I2C ist "single master / multiple client".

Also Dein AVR kann viele Clients abfragen.

von Oliver S. (oliverso)


Lesenswert?

Reiner D. schrieb:
> Ich kann z.B auf dem AtMega256 aus zwei Instanzen
> "gleichzeitig" (also innerhalb des Befehlszyklus) auf die
> I2C-Schnittstelle zugreifen

Kannst du, das wird aber Chaos verursachen.
Du kannst entweder nacheinander auf eine I2C-Schnittstelle zugreifen, 
oder gleichzeitig auf verschiedene. Alles weitere bliebt dir überlassen.

Oliver

von Reiner D. (dollreiner)


Lesenswert?

M. K. schrieb:
> Wenn du alles public machst ist es nur eine Frage der Zeit bis dein
> Schoner auf Grund läuft.

Danke für das schöne Bild ;-)
Ich weiß, ich kämpfe gegen Windmühlen, trotzdem :

Ich brauche keine getter/setter, wenn ich eh keine Fehlerprüfung mache.
Was hat ein setter dann für einen Sinn ?

Wiederverwendbarkeit und sowas ist gut für Profi-Projekte, ich brauch 
das nicht in meinem Spielzeugkontext.

Trotzdem bin ich brennend an diesen Aussagen interessiert, weil mir ja 
gerade der professionelle Blick auf das Thema fehlt !

von Reiner D. (dollreiner)


Lesenswert?

Wilhelm M. schrieb:
> I2C ist "single master / multiple client".

.. wie wohl jedes Bussystem. Aber deshalb ist der Master "nach hinten" 
noch lange nicht multiinstanzfähig.

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> M. K. schrieb:
>> Wenn du alles public machst ist es nur eine Frage der Zeit bis dein
>> Schoner auf Grund läuft.
>
> Danke für das schöne Bild ;-)
> Ich weiß, ich kämpfe gegen Windmühlen, trotzdem :
>
> Ich brauche keine getter/setter, wenn ich eh keine Fehlerprüfung mache.
> Was hat ein setter dann für einen Sinn ?

In C++ sagt man auch nicht unbedingt getter/setter. Die Unterscheidung 
kann hier der Compiler anhand des const-Attributes machen.

"Setter" haben die Aufgabe, nicht vorgesehene Objektzustände in Form von 
Zusicherungen auszuschließen und ggf. Abbildungen zwischen extern 
sichtbarem und intern modelliertem Zustand zu machen.

Stell Dir vor eine Klasse Point, die intern die Koordinaten in 
Polarkoordinaten modelliert, jedoch nach außer auch Cartesische 
Koordinaten anbietet.

>
> Wiederverwendbarkeit und sowas ist gut für Profi-Projekte, ich brauch
> das nicht in meinem Spielzeugkontext.

Dur wirst Dich freuen, wenn Du nach 2 Wochen Pause Deinen eigenen Code 
wieder anschaust.

von Wilhelm M. (wimalopaan)


Lesenswert?

Reiner D. schrieb:
> Wilhelm M. schrieb:
>> I2C ist "single master / multiple client".
>
> .. wie wohl jedes Bussystem. Aber deshalb ist der Master "nach hinten"
> noch lange nicht multiinstanzfähig.

Nö. Es gibt Multi-Master Busse.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Reiner D. schrieb:
> nochmal nachgefragt :

Eigentlich dachte ich, dass ich mich deutlich ausgedrückt hätte!
Das war ein Irrtum....

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Wilhelm M. schrieb:
> I2C ist "single master / multiple client".

I2C ist Multimaster fähig.

von Hans-Georg L. (h-g-l)


Lesenswert?

Du könntest dir auch das Leben leichter machen und Platinchen (Matrosen) 
bauen. Ein kleiner MC und die Motortreiber darauf. Das würde dein 
Softwareproblem und den Kabelverhau reduzieren und skalierbar sein.

von Wilhelm M. (wimalopaan)


Lesenswert?

Arduino F. schrieb:
> Wilhelm M. schrieb:
>> I2C ist "single master / multiple client".
>
> I2C ist Multimaster fähig.

Da hast Du natürlich recht!

von MaWin O. (mawin_original)


Lesenswert?

Reiner D. schrieb:
> Ich brauche keine getter/setter, wenn ich eh keine Fehlerprüfung mache.
> Was hat ein setter dann für einen Sinn ?
>
> Wiederverwendbarkeit und sowas ist gut für Profi-Projekte, ich brauch
> das nicht in meinem Spielzeugkontext.

Es geht ja weder darum, dass man so etwas zwingend braucht oder ob etwas 
ein "Profiprojekt" ist. Natürlich kann man ohne auskommen.
Aber insgesamt lebt es sich mit einer sauberen Datenkapselung 
(getter/setter) deutlich einfacher, je größer das Projekt wird. Die 
mentale Last wird sehr reduziert, wenn du dir nicht ständig Gedanken 
darüber machen musst, wer denn jetzt wieder von wo direkt auf irgendeine 
Variable zugreifen könnte. Was heute eine einfache Variable ist, kann 
morgen komplexer sein. Und mit einer sauberen Kapselung sind solche 
Anpassungen meist Klasseninterna.

Außerdem finde ich es lustig, wie zwischen Hobby- und Profiprojekt 
unterscheidest. :)
Ich kann dir versichern, dass so manches Profiprojekt aussieht, als wäre 
es von Amateuren zusammengestümpert worden.
Wenn ich eins gelernt habe, dann: Überall wird gefrickelt. Nirgendwo 
wird alles perfekt oder nach der "reinen Lehre" gemacht. Und am Ende 
funktioniert es dann meistens doch irgendwie zuverlässig.
Man kann sich aber sehr sehr viel Arbeit sparen, wenn man einige Dinge 
von vorne herein richtig macht. Und da gehört eine vernünftige 
Datenkapselung IMO mit an die erste Stelle.

Beitrag #7385405 wurde vom Autor gelöscht.
von Reiner D. (dollreiner)


Lesenswert?

Nochmal : ok, ihr habt mit den meisten Aussagen wohl recht
Nochmal : danke !

Verzeiht provozierende Rückfragen, ich versuche nur, den Kern der 
jeweiligen Thematik freizulegen.

Wie ist das allgemein hier ?
Technisches Forum mit möglichst knapper, präziser Info, oder ist auch 
Geplauder erlaubt ? Wenn nicht erwünscht, sollten wir das 
Kaffeekränzchen stoppen, ansonsten macht's Spaß.

von M. K. (sylaina)


Lesenswert?

Geplauder (Abschweifungen und ähnliches) gehört IMHO immer dazu wenn man 
tiefer ins Thema einsteigt und sich auch prima austauscht so wie das 
hier im Thread grade der Fall ist. Wichtig ist eigentlich nur, dass man 
auch den Bogen zum Threadthema wieder zurück findet.

: Bearbeitet durch User
von Reiner D. (dollreiner)


Lesenswert?

Hans-Georg L. schrieb:
> Du könntest dir auch das Leben leichter machen und Platinchen (Matrosen)
> bauen. Ein kleiner MC und die Motortreiber darauf. Das würde dein
> Softwareproblem und den Kabelverhau reduzieren und skalierbar sein.

Da hast du mit Sicherheit recht.
Wär ja auch spaßig, jede relevante Arbeit von nem kleinen Nano oder 
sowas machen lassen, quasi "Hardwareobjekte", und das über ein Bussystem 
zu vernetzen.

(Sowas hatte ich schon mal : ein Raspi mit Python hat kommuniziert 
(OPCuA)und gerechnet, ein Ardu seriell dran hat eine Delta-HW gesteuert.

Aber Hardware ist aktuell nicht mein Ding, ich tippe grad lieber und 
gehe auf die Reise durch die neue Welt der Objektorientierung. Den 
Python-Gedanken hat keiner aufgegriffen : AVR und Python, geht das ?

von Εrnst B. (ernst)


Lesenswert?

Reiner D. schrieb:
> AVR und Python, geht das ?

Das Plenken solltest du dir wirklich abgewöhnen.

Ansonsten schau dich hier um:

https://micropython.org/

-> Sollte wohl etwas "dicker" als ein kleiner AVR werden.

von Reiner D. (dollreiner)


Lesenswert?

aufgegriffen :

ist das "Plenken" ?

von Εrnst B. (ernst)


Lesenswert?

Reiner D. schrieb:
> ist das "Plenken" ?

Reiner D. schrieb:
> um das zu lösen ??

Reiner D. schrieb:
> Was tun ?

Reiner D. schrieb:
> Stück Beispielcode zu zeigen ?

Reiner D. schrieb:
> der dann dem Objekt zugeordnet ist ?

usw.

von Reiner D. (dollreiner)


Lesenswert?

In meinem Alter nehme ich mir das Recht auf "ästhetische 
Rechtschreibung".
Und dazu zählt das, was du "Plenken" nennst.

Mal ehrlich, schaut das gut aus :

Beispiel: das ist nicht geplenkt!

Ist doch geplenkt viel schöner :

Beispiel : das ist geplenkt !

Ich hab doch Platz, wieso sollte ich das schöne Satzzeichen da 
dranquetschen ?

(Und wieder : beim Komma passt das finde ich, beim Fragezeichen nicht 
!!)

Ich hab hier eh schon nachgegeben, und verwende Großbuchstaben. Einer 
hat geschrieben, er kann das nicht lesen ...




Aber jetzt gleiten wir echt krass vom Thema ab ;-)

von M. K. (sylaina)


Lesenswert?

Reiner D. schrieb:
> Großbuchstaben. Einer

Du plenkst aber nicht konsequent ;)

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.