PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bibliothek mit Referenzen



frabe
29.04.2020, 13:18
Hallo zusammen.
Nachdem ich dank einiger Forenmitglieder eine wunderbar, multible Kontaktentprellung hin bekommen habe, möchte ich meine Funktionen als Bibliotheken auslagern.

Hierzu vorab die Frage1:
Müssen meine Bib zwingend in dem Arduino-Bib-Verzeichnis hinterlegt sein?
Ich würde gerne meinen Bib-Ordner direkt an dem Anwendungs-Patch mitführen.

Frage2:
Finde die Bearbeitung von *.h und *.cpp im Win-Editor, oder Word-Pad unübersichtlich.
Kennt ihr einen übersichtlicheren Editor, ähnlich dem Arduino-IDE?

Frage3:
Meine Kontaktentprellung funktioniert prima! Derzeit seht alles in einem Patch.
Meine Entprellfunktion besteht aus 2 Funktionsblöcken;
1 Zwischenspeicher für jeden einzelnen Kontakt/Taster/Schalter
und einen universellen, der die eigentliche Entprellung überwacht. Der letzt genannte arbeitet mit Referenzen.
Leider funktioniert das bei mir nicht...
Sind Referenz-Übergaben überhaupt möglich?

200425_KontEntpr_Bib.ino


#include "Entprellung.h"

void loop(){
switch (Taste1(Taste1Pin)){...}
...
}

int Taste1(int KontPin) { // Funktion als Zwischenspeicher für jeden Einzel-Kontakt
static unsigned long StartZeit = 0;
static int KontZustAlt = digitalRead(KontPin);
static int EntprellStatus = digitalRead(KontPin);
return Entprellung(KontPin, StartZeit, KontZustAlt, EntprellStatus);
}


Entprellung.h


#include "Arduino.h"
int Entprellung(int KontaktPin, unsigned long &StartZeit, int &KontaktZustandAlt, int &EntprellStatus); // Funktions-Prototyp


Entprellung.cpp


#include "Arduino.h" // Arduino einschließen
#include "Entprellung.h"
int Entprellung(int KontaktPin, unsigned long &StartZeit, int &KontaktZustandAlt, int &EntprellStatus) {...}

HaWe
29.04.2020, 13:49
mit code:: blocks oder Notepad++ kannst du sehr gut .h und .c files erstellen, du kannst sie sogar als externen Editor für Arduino benutzen.
Oder du erstellt es erst als .ino file in der Arduino-IDE und benennst es anschließend in .h oder .c etc. um.

frabe
29.04.2020, 13:53
PS:
Die Fehlermeldung beim compilieren:


Arduino: 1.8.5 (Windows 10), TD: 1.47, Board: "Teensy 3.2 / 3.1, Serial, 24 MHz, Faster, German"
...
Bibliothek Entprellung im Ordner: C:\Program Files (x86)\Arduino\libraries\Entprellung (legacy) wird verwendet
Fehler beim Kompilieren für das Board Teensy 3.2 / 3.1.

HaWe
29.04.2020, 14:12
wenn deine #includeten files im selben Ordner direkt "neben" deinem ino file sind, geht es (kein weiterer Unterordner nötig).
Oder im Library-Ordner, aber dann innerhalb eines identisch benannten Unterordners.

(also libraries/Entprellung/Entprellung.h und libraries/Entprellung/Entprellung.cpp)

frabe
29.04.2020, 14:26
Danke HaWe
Notpad++ ist toll!

libraries/Entprellung/Entprellung.h und
libraries/Entprellung/Entprellung.cpp habe ich - läuft dennoch nicht.

Gibt es auch eine relative Ordnerzuordnungsmöglichkeit die ich zB. in
#include "\xxx\yyyy\Entprellung.h"
verweise?

HaWe
29.04.2020, 14:31
Danke HaWe
Notpad++ ist toll!

libraries/Entprellung/Entprellung.h und
libraries/Entprellung/Entprellung.cpp habe ich - läuft dennoch nicht.

Gibt es auch eine relative Ordnerzuordnungsmöglichkeit die ich zB. in
#include "\xxx\yyyy\Entprellung.h"

wenn du es so machst, wie ich schrieb, funktioniert es, das mache ich auch ständig so.
Es müssen dann ntl alle lib files hinein, mit dem korrekten gegenseitigen #include für .h und .cpp

frabe
29.04.2020, 15:07
wenn du es so machst, wie ich schrieb, funktioniert es, das mache ich auch ständig so.
Es müssen dann ntl alle lib files hinein, mit dem korrekten gegenseitigen #include für .h und .cpp

Sehe ich das richtig, würde der Sketch-Ordner dann so aussehen?

...\xxx\
sonstwas.ino
Entprellung.h
Entprellung.cpp
noch_mal_bib.h
noch_mal_bib.cpp
usw.h
usw.cpp
etc.h
etc.cpp

HaWe
29.04.2020, 15:25
ja, grundsätzlich richtig!

------v
..\sonstwas\

sonstwas.ino
Entprellung.h
Entprellung.cpp
noch_mal_bib.h
noch_mal_bib.cpp
usw.h
usw.cpp
etc.h
etc.cpp

ist aber umständlich, wenn du dein ino mal irgendwann unter einem neuen Namen speicherst.
guck dir mal in einer "professionellen" lib an, wie .h und .cpp sich gegenseitig #includen, inkl #ifdef oder #pragma once.
wenn es dann erstmal läuft, verrate ich dir noch nen zusätzlichen Trick - das verwirrrt aber momentan noch... 8)

frabe
29.04.2020, 16:10
...da sind wir wieder bei meinem Urproblem -> der Sketch lässt sich immer noch nicht comp.
"Fehler beim Kompilieren für das Board Teensy 3.2 / 3.1."

Hat das mit den Referenzen "&" in Entprellung.h, Entprellung.cpp zu tun?


int Entprellung(int KontaktPin, unsigned long &StartZeit, int &KontaktZustandAlt, int &EntprellStatus);


- - - Aktualisiert - - -

PS:
Es wird noch komplizierter für mich;
Habe im x.ino eine "const int Entprellzeit;", die in y.cpp verwendet werden soll.
Hier meckert der Compiler aber...

Sisor
29.04.2020, 16:23
Vielleicht kannst du hieraus Nutzen ziehen:
Tutorial-Erstellen-einer-Arduino-Bibliothek (https://www.roboternetz.de/community/threads/65187-Tutorial-Erstellen-einer-Arduino-Bibliothek)

frabe
29.04.2020, 17:52
Kenne ich - steht leider nichts von &Referenzen.
Klassen wäre mein nächster Schritt, nachdem Bibliothek sauber läuft.

Sisor
29.04.2020, 20:40
Die "const int Entprellzeit;" wäre etwas, was als Argument in den Konstruktor eines Objekts gehört.

HaWe
29.04.2020, 21:40
falls es dich interessiert, wie ich es gelöst habe (sicher noch suboptimal):
https://github.com/dsyleixa/Arduino/tree/master/libraries/ButtonClass

PS
ich habe alle Funktionen samt Code in das .h file geschrieben, nicht nur die Prototypen - das ist zwar nicht ganz regeltypisch, aber deutlich einfacher zu warten 8)

frabe
30.04.2020, 08:27
Die "const int Entprellzeit;" wäre etwas, was als Argument in den Konstruktor eines Objekts gehört.
DANKE, genau hierrüber war ich mir unsicher; welche Var gehören in den Global-Bereich, in die Funktion als static und in die Objekte?

Ist es selbstverständlich, dass bei der Verwendung einer Bibliothek erst einmal dessen Parameter/const Variablen angepasst werden?
Oder muss ein Objekt so universell sein, dass das Objekt nicht angefasst/angepasst wird?
Bsp: LEDs werden angesteuert, steht sie Output-Zuordnung im Sketch oder im Objekt?

- - - Aktualisiert - - -


falls es dich interessiert, wie ich es gelöst habe (sicher noch suboptimal):
https://github.com/dsyleixa/Arduino/tree/master/libraries/ButtonClass

Moin HaWe - ist mir derzeit noch zu kompliziert...

HaWe
30.04.2020, 11:57
welche Var gehören in den Global-Bereich, in die Funktion als static und in die Objekte?
"Objekte" sind Instanzen von "Klassen", und die haben eine vorgeschriebene Struktur in C++,
"normale" prozedurale Funktionen kennen oder haben keine Objekte, C kennt überhaupt keine Objekte.

Betr. Klassen und davon instantiierte Objekte:
Alles, was an die Klassen und ihre dann instantiierte Objekte an Werten übergeben wird und was sie als (veränderte, berechnete) Werte zurückgeben, ist "public",
alles was nur intern für Umrechnungen benötigt wird, ohne dass von außen darauf zugegriffen werden soll, ist "private".
"static" in Klassen sind Werte, die auch zwischen den Objekt-Instanzen ausgetauscht werden.

ich bin mir daher nicht sicher, ob du wirklich überhaupt von "Objekten" sprichst, oder ob du etwas ganz anderes meinst.

Moppi
30.04.2020, 12:27
Kenne ich - steht leider nichts von &Referenzen.
Klassen wäre mein nächster Schritt, nachdem Bibliothek sauber läuft.

Du brauchst für den Minicode keine "&Referenzen" (dieser Ausdruck existiert in der Form noch nicht einmal). Du benötigst hier gar keine Referenzen oder gar explizite Zeiger. Wenn Du der Meinung bist, hast Du eine Menge falsch gemacht.

MfG

- - - Aktualisiert - - -

Bei einem Objekt werden die Variablen in bestimmten Abschnitten deklariert.
Somit sind sie methodenübergreifend erreichbar.
Wenn Variablen in einer Methode deklariert und definiert werden, dann sollte
man dies nur tun, wenn die Variable nur innerhalb dieser Methode gebraucht wird.


Variablen, die ausschließlich nur in einer einzigen Methode benötigt werden:
Deklaration + Definition innerhalb dieser Methode.


Nicht öffentliche Variablen, die methodenübergreifend benötigt werden,
aber nicht außerhalb des Objektes:
Deklaration, innerhalb "class ...", wie ich schon am Beispiel zeigte, unter "privat"


Öffentliche Variablen, auf die auch außerhalb des Objektes zugegriffen werden soll:
Deklaration, innerhalb "class ...", wie ich schon am Beispiel zeigte, unter "public"


Zum schlechten Programmierstil gehört z.B.:
Variablen, die methodenübergreifend benötigt werden,
in einer Methode deklarieren und mit Referenz oder anderen Tricks an andere Methoden übergeben.


Nicht alles, was irgendwie möglich ist, ist auch sinnvoll, geschweige denn notwendig.
Was bestimmte Sonderfälle nicht einschließt. Davon kann hier aber keine Rede sein.

frabe
30.04.2020, 16:40
Hallo Leute.
Meine Entprellung() Funktion klappt prima innerhalb eines Sketch.
Hier benutze ich Referenzen mit einem Zeiger auf eine Var. (Bsp: int &KontZustandAlt).
Mein Vorteil ist die gleichzeitige Funktionsrückgabe mehrerer Parameter. Unsauber?
Klappt prima!

Schritt2 ist die Auslagerung der Funktion Entprellung() in eine Bibliothek. Hier komme ich scheinbar mit den Referenzen nicht weiter...
Daher meine Frage: kann man überhaupt mit Referenzen zw. Sketch und Bib. arbeiten?

Daher meine Zusatzfragen: mit static Var. und const Var. Auf welche Var. innerhalb des Sketch kann eine Bib. zu greifen?

Schritt3 wäre dann die Umwandlung von C-Bib. in eine C++-Standardbibliothek (habe ich fälschlich als Objekt oder Klasse bezeichnet).
Hier sehe ich mich aber noch lange nicht.

HaWe
01.05.2020, 17:32
- - - Aktualisiert - - -
Moin HaWe - ist mir derzeit noch zu kompliziert...
war auch vorwiegend zum einfach-Installieren und -Benutzen gedacht.

frabe
05.05.2020, 12:31
war auch vorwiegend zum einfach-Installieren und -Benutzen gedacht.
Danke! Möchte aber erst einmal meinen eigenen Weg finden.

Zum Thema Bibliotheken habe ich nur sehr oberflächliche Infos im Netz gefunden.
Veraltete, unpraktische Technik?

(Den Klassen widme ich mich, sobald ich Bib und dessen Var verstanden habe - ist vermutlich der praxisnaheste Weg)

Mich interessier primär, wie innerhalb einer Bib mit Variablen aus dem Sketch umgegangen wird.
Kann die Bib überhaupt auf globale Var aus dem Sketch zugreifen?
Oder auf static Var aus einer Funktion (innerhalb des Sketch), aus der die Bib aufgerufen wird?
Somit käm ich mit die Frage nach "Variable als Referenz" (int &Zustand) innerhalb einer Bib schon mal weiter.

derzeit Entprellung.h, Entprellung.cpp


int Entprellung(int KontaktPin, unsigned long &StartZeit, int &KontaktZustandAlt, int &EntprellStatus);

HaWe
05.05.2020, 13:18
1 globale Variable kann immer nur 1 Wert speichern, nicht verschiedene, und dasselbe gilt für jede lokale Variable.
kA wie du das mit Referenzen für verschiedene Buttons lösen willst.
Der einzige Weg geht mE über Strukturtypen, wobei du dann im Sketch davon je 1 als neue Strukturvariable pro Button im Sketch neu einzeln instanziierst.


// das gehört in die Lib
typedef struct{
int var1;
int var2;
int var3;
}
myBtnStruct;

// das gehört in den Sketch
myBtnStruct btn1, btn2, btn3;

Ein Objekt ist prinzipiell nichts anderes, nur dass noch zusätzlich Funktionen drin gekapselt sind.
Ich halte daher deinen bisherigen Ansatz für mindestens suboptimal wenn nicht für sogar für nicht zielführend.

frabe
05.05.2020, 15:19
1 globale Variable kann immer nur 1 Wert speichern, nicht verschiedene, und dasselbe gilt für jede lokale Variable.

uiuiui, da hast du mich vollkommen falsch verstanden.



kA wie du das mit Referenzen für verschiedene Buttons lösen willst.

Es geht darum aus einer Funktion mehrere Werte zurück zu geben.



void loop() {
if (Kontakt01 == 1){...mach was...}
if (Kontakt02 == 0){...mach was...}
}

int Kontakt01(int KontPin) { //Prüfung; gibt 4 Zustand zurück; 0...Entprellt+LOW, 1...Entprellt+HIGH, 2...IN Entprellung, 3...keine Zustandsänderung
static unsigned long StartZeit = 0;
static int KontZustAlt = digitalRead(KontPin);
static int EntprellStatus = digitalRead(KontPin);
return Entpreller(KontPin, StartZeit, KontZustAlt, EntprellStatus);
}

//Kontakt-Entprellung; gibt 4 Zustände zurück; 0...Entprellt+LOW, 1...Entprellt+HIGH, 2...derzeit in Entprellung, 3...keine Zustandsänderung
int Entpreller(int KontPin, unsigned long &StartZeit, int &KontZustAlt, int &EntprellStatus) {
int KontZustNeu = 0;
if((KontZustNeu = digitalRead(KontPin)) == EntprellStatus) {
return 3;
}
//...usw...
}

Hier werden in Kontak01() bei jedem Durchlauf, aktuelle Var-Werte für den Kontakt01 zwischengespeichert.
Die 3Stk "&Var" werden durch Entpreller() berechnet, dann die neuen Werte wieder in Kontakt01 gespeichert --- bis zum nächsten Durchlauf...
Somit muss für jeden Eingangs-Kontakt/Taster eine eigene Funktion, als Zwischenspeicher(!), bestehen Kontakt01..0n() --- der einzige Wehrmutstropfen.
Funktioniert aber sehr gut!


--2--
A| Nun möchte ich erst Entpreller() in eine Bib verschieben. Daher meine nervigen Fragen nach &Var (Referenz-Variablen).
Und ob ich von einer Bib aus auf zB. die global Var zB. "KontPin" zugreifen kann.
B| Danach bekommt jeder Kontakt0n() eine eigene Bib.
C| Danach wollte ich mich mit Klassen, Objekten, Methoden beschäftigen. Sozusagen als Erweiterung und Verbesserung einer C-Bib.

HaWe
05.05.2020, 15:41
sry, deine Konstruktion verstehe ich nicht, ich würde es ganz anders machen - da muss dann jemand anders 'ran 8)

frabe
05.05.2020, 16:25
Wie wäre dein Prinzip um meherer Kontakte gleichzeitig auf Zustandsänderung, Entprellung und neuem Zustand (ohne delay) zu überprüfen?

Hierbei wird bei jedem loop-Durchlauf,
1. auf Zustandsänderung geprüft; if((KontZustNeu = digitalRead(KontPin)) == EntprellStatus) return 3;
2. wenn sich der Kontaktzustand ändert, wird das bei jedem loop-Durchlauf neu geprüft
3. sollte sich der Kontaktzustand innerhalb von 5ms ändern, wird die Startzeit resetet
4. sollten dann >=5ms keine Zustandänderungen passieren, wird je nach Zustand 0(LOW) oder 1(HIGH) zurück gegeben.
5. und das für beliebig viele Kontakte und ohne delay()

PS: Entprellzeit = 5ms ist eine globale Variable und als Beispiel zu verstehen

HaWe
05.05.2020, 17:10
ich würde alle Einzel-Variablen in einen struct type packen,
dann mehrere Variablen von dem struct type davon im aktuellen Sketch erzeugen,
und dann eine beliebige dieser struct-Variablen an eine spezielle Funktion aus der Lib by reference übergeben, die die Einzelwerte ändert,
zB so



#include "structlib.h"

// das folgende steht in der structlib.h
/*

#pragma once


typedef struct { // struct type
int var1=0;
int var2=0;
int var3=0;
} myBtnStruct;

void modifyStruct(myBtnStruct & Btn) {
// erhält eine Variable vom struct type by reference und gibt deren Werte geändert zurück
Btn.var1=1;
Btn.var2=2;
Btn.var3=3;
}

*/

void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println("Serial() started");

myBtnStruct btn1, btn2, btn3; // erzeuge mehrere Variablen vom struct type

// vor Funktionsaufruf
Serial.println();
Serial.println(btn1.var1);
Serial.println(btn1.var2);
Serial.println(btn1.var3);

Serial.println();

// nach Funktionsaufruf

modifyStruct(btn1);
Serial.println();
Serial.println(btn1.var1);
Serial.println(btn1.var2);
Serial.println(btn1.var3);

Serial.println();

}


void loop() {
}

frabe
06.05.2020, 17:56
OhMann - irgendwie komme ich nicht weiter mit dem Verständniss um Bib.

Um den Sketch klein zu halten, möchte erste einmal alle Funktionen aus einem Sketch in jeweilige Bib verteilen.
Nun bekomme ich dauernd Fehlermeldungen, wenn ich aus einer Bib eine Sketch-Funktion aufrufen möchte.
Geht das gar nicht?

Später wollte ich von einer Bib aus eine andere Bib aufrufen usw.
Ist eine Bib überhaupt dafür gedacht?

Wie bereits geschrieben, steht im Netz leider nur sehr oberflächliches zu Bibliothken.

HaWe
06.05.2020, 18:07
Nun bekomme ich dauernd Fehlermeldungen, wenn ich aus einer Bib eine Sketch-Funktion aufrufen möchte.
Geht das gar nicht?
nein, das geht nicht, denn das .h/.cpp file der Library weiß ja nichts von deinem Sketch, also wie soll eine Library eine Sketch Funktion kennen?
- anders herum geht es ntl schon.


Später wollte ich von einer Bib aus eine andere Bib aufrufen usw.
Ist eine Bib überhaupt dafür gedacht?
sagen wir so: ja, das geht, wenn man es richtig macht.

Die Funktionen etc der Library müssen nur sehr allgemein gehalten sein und in sich abgeschlossen sein.

frabe
06.05.2020, 18:31
nein, das geht nicht, denn das .h/.cpp file der Library weiß ja nichts von deinem Sketch,

Daher kann die Lib auch nicht auf globale Var. aus dem Sketch zugreigen.
Anders herum schon? Könnte ich dann eine Lib aus "globalen Variablen" für den Sketch verwalten?



Die Funktionen etc der Library müssen nur sehr allgemein gehalten sein und in sich abgeschlossen sein.

... nicht sonderlich mächtig...
Das würde bedeuten, wenn in 2 unterchiedlichen Lib ein und die gleiche LED angesteuert werden soll, müsste der Pin in jedem Lib separat deklariert werden. Oder?
Ganz schön aufwendig (und Fhelerbehaftet).



sagen wir so: ja, das geht, wenn man es richtig macht.

Wie?

HaWe
06.05.2020, 18:40
ich kann dir hier leider kein Tutorial bieten, versuche das Beispiel aus #24 zu verstehen, kopiere es, spiel damit herum und versuche deine Btn-Funktionen entsprechend umzuarbeiten. (Oder versuche meine Btn-Lib zu verstehen ;) )

frabe
06.05.2020, 19:32
Ich vestehe das meine Fragen nerven - mich nervt das Thema, da kein Fortschritt.
Hatte gedacht, dass Bibliotheken, Sketch flexiber machen - funktionierende Funktionen für weitere Sketch leichter verwendbar machen.
ABER, auch ohne Bib klappts mit bestehenden Funktionen - copy/paste ist angesagt.

Da ich derzeit keine wesentlichen Vorteile sehr, werde ich erst einmal die Bib´s zurück stellen!

HaWe
06.05.2020, 20:03
Lib-Funktionen müssen alle wesentlichen Variablen vom aufrufenden Sketch erhalten und sollten daher am besten auch in einer Structure gekapselt sein, wenn mehr als 1 Wert verändert wird - alles andere ist unübersichtlich, verwurschtelt und schlecht zu warten. Deine Funktionen und Variaben sind viel zu sehr ineinander verschachtelt, als dass man sie unproblematisch und sauber in eine Lib auslagern könnte: daher wäre IMO eine komplette Neuprogrammierung deiner btn-Funktionen und -Variablen notwendig, mit völlig gegeneinander abgeschlossenen Typen, Parametern und Scopes.
Siehe Beisp. in #24.
Wenn du das sauber trennen kannst, wäre eine solche Lib durchaus eine deutliche Erleichterung und Vereinfachung.