Forum: Compiler & IDEs Lib für Arduino Giga machen


von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Guten Tag!
Leider fehlen mir noch viele Kenntnisse. Früher habe ich einiges auf C 
gemacht, aber C++ Variante, die Arduino 2 benutzt, ist für mich 
Neufeld...

Die Frage: wie können verschiedene Libs miteinander kommunizieren?
Ich habe nun universelle Scala gemacht, und zwar in zwei Varianten: auf 
C und als C++ Classe. Mit C ist mir einigermaßen klar, was ich weiter 
machen muß. Aber in C++ braucht Scala einige Funktionen von 
Arduino_GigaDisplay_GFX, die die Funktionen von Adafruit_GFX benutzt.

Um Rechtecke und Text in Scala zu benutzen, brauche ich Ein C++-Objekt, 
das erst in Hauptprogramm (*.ino) geschafft wird. D.h. Lib kann das 
Objekt nicht benutzen?

Jetzt ist alles in Hauptfile und funktioniert wie erwartet. Wenn ich 
aber versuche, class separat in *.h und *.cpp zu speichern, und in *.cpp 
besondere Objekt für Benutzen mit Scala zu machen, bekomme ich zwar 
keine Fehlermeldungen von Compiler, aber die Platine Arduino Giga 
blockiert sich (blinkt rot, so daß ich dann sie entsperren muß. Ich 
wiederhole - und wieder das Gleiche).

Was mache ich falsch?

Hier sind beide Varianten von Lib.

von Hans W. (hanswieland)


Lesenswert?

Maxim B. schrieb:
> wie können verschiedene Libs miteinander kommunizieren?

Falss du das Zusammenspiel von C mit C++ meinst: 
https://isocpp.org/wiki/faq/mixing-c-and-cpp

von Harald K. (kirnbichler)


Lesenswert?

Maxim B. schrieb:
> D.h. Lib kann das
> Objekt nicht benutzen?

Doch, natürlich kann eine "Lib" das tun. Sie muss die Klassendeklaration 
kennen, und ihr muss ein Pointer auf die Objektinstanz übergeben werden. 
Dann kann die "Lib" munter Funktionen aufrufen, die das Objekt zur 
Verfügung stellt.

Mit Deiner Fehlerbeschreibung kann und mag ich hingegen nichts anfangen.

von Maxim B. (max182)


Lesenswert?

Hans W. schrieb:
> Falss du das Zusammenspiel von C mit C++ meinst:

Nicht ganz. Interessant, wie ich ein Lib aus anderem Lib benutzen kann. 
In einem Lib brauche ich Funktionen aus anderem Lib, und im 
Hauptprogramm muß Objekt erst gemacht werden. Wie bekommt diese 
Funktionen Class aus Lib?

Also, im Hauptprogramm sind beide Lib deklariert.
Dann sind Objekte aus beiden gemacht.
Was sollte ich weiter tun, um Objekte aus dem ersten Lib für Objekte aus 
dem zweiten Lib sichtbar zu machen?
In Lib selbst etwas vorbereiten? Zeiger auf Funktionen, die in 
Hauptprogramm auf Objekte aus dem 1.Lib zeigen?

: Bearbeitet durch User
von Hans W. (hanswieland)


Lesenswert?

Ich verstehe die Frage nicht.

Libraries sollten niemals direkt auf Objekte des Hauptprogramms 
zugreifen. Es geht, aber ich weigere mich, dir diesen schmutzigen Trick 
zu zeigen.

Funktionen und Methoden in Libraries sollten immer nur auf die Dinge 
Zugreifen, die man ihr als Argument übergeben hat.

Wenn deine Skala z.B. eine Instanz der I2C Schnittstelle braucht, dann 
erzeuge im Hauptprogramm zuerst die I2C Instanz und übergebe diese dann 
der Skala Klasse im Konstruktor. Die Skala Klasse kann die Referenz auf 
die I2C in eine eigene Member Variable kopieren, um sie später wieder zu 
verwenden.

Vielleicht solltest du erst mal C++ auf dem PC lernen, bevor du es auf 
einem Mikrocontroller anwendest. Auf dem PC lernt man die Sprache viel 
leichter.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Hans W. schrieb:
> Funktionen und Methoden in Libraries sollten immer nur auf die Dinge
> Zugreifen, die man ihr als Argument übergeben hat.

D.h. sollte ich in meinem Lib Zeiger auf Funktionen vorbereiten, die 
dann in Hauptprogramm mit entsprechenden Set-Funktionen aus meinem Lib 
eingestellt werden?

Hans W. schrieb:
> Wenn deine Skala z.B. eine Instanz der I2C Schnittstelle braucht, dann
> erzeuge im Hauptprogramm zuerst die I2C Instanz und übergebe diese dann
> der Skala Klasse im Konstruktor. Die Skala Klasse kann die Referenz auf
> die I2C in eine eigene Member Variable kopieren, um sie später wieder zu
> verwenden.

Ich versuche gleich diesen Weg.

: Bearbeitet durch User
von Hans W. (hanswieland)


Lesenswert?

In C++ arbeitet man mit Referenzen auf Klassen und ruft darüber die 
Methoden der Klasse auf.

Deine Fragen sind zu unklar. Du benutzt falsche Begriffe und der Kontext 
fehlt. So kann man nicht vernünftig helfen. Das hier wird endlos dauern. 
Das ist mir zu anstrengend.

von Hans W. (hanswieland)


Lesenswert?

Hier mal ein Beispiel:
https://github.com/RobTillaart/PCF8574/blob/master/PCF8574.h

PCF8574 ist ein Mikrochip mit I2C Schnittstelle. Er dient dazu, den 
Mikrocontroller mit mehr I/O Pins zu erweitern.

Der Konstruktor von der PCF8574 Klasse kann mit einem Zeiger auf eine 
Instanz der I2C Schnittstelle (Twowire) aufgerufen werden. (Ich hätte 
eine Referenz genommen, aber ein Zeiger geht auch). Diese wird von fast 
allen anderen Funktionen benutzt, um mit dem Chip über die I2C 
Schnittstelle zu kommunizieren.

Die Twowire Klasse wird in einer anderen Lib von Arduino bereit 
gestellt.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Hans W. schrieb:
> und der Kontext
> fehlt.

Ich habe am Anfang meine *.ino - File gezeigt.
Aus Hauptfunktion void Maxim_scala::scala(uint16_t xx, uint8_t rahmen); 
werden Funktionen
void Maxim_scala::scala_rahmen(uint8_t einaus);
void Maxim_scala::scala_m_metka(uint8_t einaus);
void Maxim_scala::scala_metka(uint8_t einaus); gerufen, die alle eine 
Funktion aus anderem Lib display.fillRect(x,y,br,h,farbe); aufrufen.
Außerdem braucht meine Funktion void Maxim_scala::scala_ziffer(uint8_t 
einaus); Funktionen aus anderem Lib für Textausgabe:
display.setFont(NULL);
display.setTextSize(2);
display.setTextColor(farbe,hintergrundfarbe);
display.setCursor(x,y);
display.print(x);

Und das ist für mich gerade unklar: solange alles in *.ino bleibt, 
funktioniert das. Wie mache ich richtige Aufrufe von Funktionen
display.fillRect(x,y,br,h,farbe);
display.setFont(NULL);
display.setTextSize(2);
display.setTextColor(farbe,hintergrundfarbe);
display.setCursor(x,y);
display.print(x);
aus anderem Lib, wenn ich meine classe mit Funktionen aus dem +.ino-File 
in separate Files *.h und *.cpp auslagere?

Hans W. schrieb:
> Hier mal ein Beispiel:
> https://github.com/RobTillaart/PCF8574/blob/master/PCF8574.h
Danke! Nun versuche ich das zu verstehen...

Hans W. schrieb:
> Vielleicht solltest du erst mal C++ auf dem PC lernen
Für mich ist einfacher zu lernen, wenn es um etwas geht, was ich 
benutzen kann. Leider sind alle Schulbücher mit absolut irrelevanten 
Beispielen gefuttert, so wie Databank von Personen und so etwas, was ich 
wahrscheinlich nie im Leben brauchen werde. Und dort geht alles am Ende 
immer mit "print" aus, das stört auch enorm, um alles richtig zu 
verstehen...

Aber ich glaube, die Idee habe ich verstanden. Nun muß ich das in Code 
ausprobieren... Ich habe gerade das Buch von Torsten T. Will gekauft und 
lese das...

: Bearbeitet durch User
von Hans W. (hanswieland)


Lesenswert?

Vorschlag mit Referenz:
1
#include <Arduino_GigaDisplay_GFX.h>
2
3
class Maxim_scala{
4
  public:
5
6
  // Konstruktor
7
  Maxim_scala(int16_t _xo, int16_t _yo, int16_t _xu, int16_t _yu, boolean _verthor, boolean _nulluo, GigaDisplay_GFX &ein_display);
8
9
  // Rahmen zeichnen
10
  void scala_rahmen(uint8_t einaus);
11
12
  private:
13
    GigaDisplay_GFX &mein_display;
14
};
15
16
// Objekte erzeugen
17
GigaDisplay_GFX display;
18
Maxim_scala scala_links(630, 35, 655, 475, 0, 0, display); 
19
Maxim_scala scala_rechts(750, 35, 775, 475, 0, 0, display);
20
Maxim_scala scala_unten(200, 420, 550, 445, 0, 0, display);
21
22
Maxim_scala::Maxim_scala(int16_t _xo, int16_t _yo, int16_t _xu, int16_t _yu, boolean _verthor, boolean _nulluo, GigaDisplay_GFX &ein_display) 
23
: mein_display(ein_display)
24
{
25
   // ...
26
}
27
28
void Maxim_scala::scala_rahmen(uint8_t einaus){
29
  // ...
30
  mein_display.fillRect(1,2,3,4,5);
31
  // ...
32
}
33
34
void setup() {
35
  // ...
36
}
37
38
void loop() {
39
  // ...
40
}

Vorschlag mit Zeiger:
1
#include <Arduino_GigaDisplay_GFX.h>
2
3
class Maxim_scala{
4
  public:
5
6
  // Konstruktor
7
  Maxim_scala(int16_t _xo, int16_t _yo, int16_t _xu, int16_t _yu, boolean _verthor, boolean _nulluo, GigaDisplay_GFX *ein_display);
8
9
  // Rahmen zeichnen
10
  void scala_rahmen(uint8_t einaus);
11
12
  private:
13
    GigaDisplay_GFX *mein_display;
14
};
15
16
// Objekte erzeugen
17
GigaDisplay_GFX display;
18
Maxim_scala scala_links(630, 35, 655, 475, 0, 0, &display); 
19
Maxim_scala scala_rechts(750, 35, 775, 475, 0, 0, &display);
20
Maxim_scala scala_unten(200, 420, 550, 445, 0, 0, &display);
21
22
Maxim_scala::Maxim_scala(int16_t _xo, int16_t _yo, int16_t _xu, int16_t _yu, boolean _verthor, boolean _nulluo, GigaDisplay_GFX *ein_display) {
23
  mein_display=ein_display;
24
   // ...
25
}
26
27
void Maxim_scala::scala_rahmen(uint8_t einaus){
28
  // ...
29
  mein_display->fillRect(1,2,3,4,5);
30
  // ...
31
}
32
33
void setup() {
34
  // ...
35
}
36
37
void loop() {
38
  // ...
39
}

von Maxim B. (max182)


Lesenswert?

Vielen, vielen Dank!!!

von Hans W. (hanswieland)


Lesenswert?

Maxim B. schrieb:
> Leider sind alle Schulbücher mit absolut irrelevanten
> Beispielen gefuttert, so wie Databank von Personen und so etwas, was ich
> wahrscheinlich nie im Leben brauchen werde. Und dort geht alles am Ende
> immer mit "print" aus, das stört auch enorm

Das machen die so, damit du dich auf das eigentliche Thema konzentrieren 
kannst und nicht gleichzeitig noch 5 andere Baustellen hast, wo etwas 
schief gehen kann.

> um alles richtig zu verstehen...

Brauchst du Zeit. Die Sprache C++ war schon am Anfang so komplex, das 
viele sie damals abgelehnt hatten. Sowohl Linux als auch Windows wurden 
ganz bewusst in C programmiert, obwohl C++ da schon lange existierte.

Die Sprache ist 40 Jahre lang gewachsen. Ich habe in den 90er drei Jahre 
lang mit C++ gearbeitet und später noch ein paar Jahre als Hobby. Doch 
ich hatte nie das Gefühl, sie vollständig zu beherrschen. Und 
mittlerweile fühle ich mich sogar abgehängt. Liegt wohl zu Teil daran, 
dass ich seit dem mit vielen anderen Sprachen arbeiten musste. 
Irgendwann vergisst man Sprachen wieder, die man nicht ständig benutzt.

Nach dem Umbau kannst du deine Skalen übrigens auf mehreren Displays 
verteilt darstellen. Zum Beispiel
1
GigaDisplay_GFX vorderes_display;
2
GigaDisplay_GFX hinteres_display;
3
4
Maxim_scala scala_vorne_links(..., vorderes_display); 
5
Maxim_scala scala_vorne_rechts(..., vorderes_display);
6
7
Maxim_scala scala_hinten_links(..., hinteres_display); 
8
Maxim_scala scala_hinten_rechts(..., hinteres_display);

So macht OOP erst richtig Sinn.

: Bearbeitet durch User
von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Hans W. schrieb:
> So macht OOP erst richtig Sinn.

Das funktioniert!!! Noch einmal vielen, vielen Dank!!!

Ich habe die Variante mit Zeiger gemacht. Später mache ich als Training 
auch die Referenz-Variante.

Hans W. schrieb:
> Die Sprache ist 40 Jahre lang gewachsen.

Und ich bin schon 55. Wir passen zusammen :)

Hans W. schrieb:
> und später noch ein paar Jahre als Hobby

Für mich bleibt das als Hobby: ich bin ein Kirchenmusiker und lebe von 
Musik. Und alles, was ich auch als Hobby mache, ist irgendwie mit Musik 
verbunden.

: Bearbeitet durch User
von Hans W. (hanswieland)


Lesenswert?

Ich habe als Kind mit alten Telefonen experimentiert, und ich wusste 
theoretisch wie ein Computer funktioniert, lange bevor ich selbst einen 
hatte.

So landete ich zur Ausbildung bei der Bundespost-Telekom, und arbeitere 
danach bei Vodafone. Danach habe ich Backend Software für Smartphone 
Dienste geschrieben, dann für einen online Händler. Heute baue ich eine 
Cloud Plattform für den Handel von Dienstleistungen (z.B. DSL und 
Mobilfunkverträge).

So baut halt eins aufs andere auf. Ich hatte immer das Glück, in einem 
Bereich arbeiten zu dürfen, der sich mit privaten Interessen überlappte.

Apropos Kirchenmusik: Ich liebe Orgelkonzerte - auch wenn sie "nur" 
elektrisch ist. Das ist ein mächtiges Instrument. Wer es beherrscht hat 
meinen vollen Respekt.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Als Kind hatte ich zuerst Interesse für Elektronik, wie ich in der 
Musikschule war. Für Musikgeschichte brauchte man Schallplatten zu 
hören, aber damals war nicht möglich, einen Schalplattenspieler zu 
kaufen, das war Defizit (ich komme aus Rußland). Ich habe schließlich 
eins selber gemacht, fertige Mechanik gefunden und primitive Elektronik 
selber gebaut. Das dauerte aber lange...

Dann brauchte ich für Musikunterricht ein Metronom, und gleiche 
Geschichte: nicht möglich zu kaufen. Ich habe selber mehrere Versionen 
gebaut, zuerst primitiv mit 1x Analog von 4069, dann auch kompliziertere 
mit digitaler Anzeige, mit K561-Serie (Analog 4000B ). So blieb ich auch 
weiter dran: es gibt immer Kleinigkeiten, die man in Einzelzahl braucht 
und die für Wirtschaft wegen kleinen Bedarf nicht interessant sind... 
Nur war eine Pause, wie ich in Dresden studierte: kein Platz für 
Basteln. Trotzdem auch dort habe ich ein Box für Phantomspeisung für 6 
Mikrofone gemacht :)

Die Orgeln: für mich ist am wichtigsten, daß eine Orgel gut 
funktioniert. Deshalb spiele ich lieber intakte Elektronik als 
mangelhafte Pneumatik. Obwohl manche Kollegen Elektronik strickt 
ablehnen. Im Sommer 2024 habe ich für Ebersdorf eine 3-man. Viscount 
Cantorum Trio Plus gekauft, mit Pedal. Dort sollte ich viel selber 
nachfeilen.

Also, einige Elektronikkenntnisse können einem Kirchenmusiker kaum 
stören :)
Jetzt bastele ich einen MIDI-Rekorder, da mit Orgel gekaufte nicht so 
funktioniert wie erwünscht. Langsam, Modul für Modul, Funktion um 
Funktion.  Ich lerne dabei auch viel.

Wichtige Merkmale, die ich unbedingt brauche:
1. Tempowechsel, schnell, ohne in Menu gehen zu müssen (hier wird auch 
Scala-Funktion benutzt). Wahrscheinlich wird x1,6 in beide Seiten 
ausreichend.
2. Während "Note ein" und "Note aus" in MIDI standartisiert, mit 
Registerwechsel macht jeder Hersteller wie er will. Das Gerät sollte mit 
bestimmten Orgeln arbeiten können und auch Register- und Manualwechsel 
betätigen können.
3. Es sollte im Lauf Wiederholungen von Strophen anzugeben möglich sein, 
auch Vorspiel und Nachspiel. Daraus sollte Menu für bestimmten 
Gottesdienst  machbar sein.
4. Das Gerät sollte leicht die Tonhöhe ändern können. +-6HT sollte 
ausreichend sein, vielleicht sogar +3-6HT. In Praxis spiele ich oft 
etwas tiefer als geschrieben, aber ich kann nicht erinnern, daß ich 
höher spielen sollte.

Da Registerwechsel in MIDI-Format sowieso nicht standartisiert, überlege 
ich, die Stücke statt in MIDI-Format in einem Text-Format zu speichern: 
so wird es leichter, später kleine Anpassungen per Hand zu machen. 
Kompatibilität mit anderen MIDI-Geräten ist hier nicht wichtig, da 
sowieso alles selber einzuspielen ist.

Aber der Weg ist noch weit.

: Bearbeitet durch User
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.