Forum: Compiler & IDEs Arduino IDE: Init-Ort von Lib/Device


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 Nik A. (nik_a)


Lesenswert?

Hallo alle!

Ich bin mit den Fachbegriffen nicht so vertraut, ich hoffe, ich kann das 
Problem verständlich beschreiben :)

Die Frage ist sicher schnell beantwortet:
Ich versuche gerade, ein ESP32-Sketch auf Atmega umzuschreiben bzw zum 
Laufen zu bekommen.
Ich habe einen Sensor (BL0940), der eine eigene Bibliothek hat, die ich 
im Sketch-Verzeichnis liegen habe, in Form von cpp/h-Dateien.

Ich habe herausgefunden, dass es mit der Initialisierung zu tun hat. Die 
-h-Datei ist wie üblich mit include ganz am Anfang.
Beim ESP steht vor dem Setup(void)-Block: BL0940 bl0940;
Im Setup(void)-Block steht dann z.B. bl0940.Reset();

Wenn ich das gleiche für Atmega644 kompiliere, hängt sich der µC sofort 
auf, sobald BL0940 bl0940; aufgerufen wird.
Ich habe jeden Block in der .cpp-Datei auskommentiert, um zu sehen, ob 
es irgendein Teil vom Code ist, der das Problem verursacht. Nichts 
gefunden.

Schiebe ich die Init BL0940 bl0940; IN den Setup-Block, also z.B. direkt 
über bl0940.Reset(); funktioniert alles.
Allerdings, sobald bl0940 in anderen Funktionen/Blöcken aufgerufen wird, 
kommt der compile-error, dass dies nicht definiert sei.
Logisch, die Definition steht ja nur im Setup-Block.

Wie löse ich das Problem? Ich will nicht mal wissen, warum es diesen 
Unterschied zwischen ESP32 und Atmega(mightycore) gibt, aber ich würde 
es gern zum Laufen bringen.

Ein Blick in andere Libs hat mir aktuell noch nicht weitergeholfen.

Mein Sketch basiert quasi auf diesem Beispiel bzw kann fast direkt so 
probiert werden:
https://github.com/mcmchris/BL0940-Energy-Meter-w-Arduino/tree/main/BL0940-ESP32
Lediglich die serielle Schnittstelle ist eine andere (cpp-Datei).

Reine Vermutung: gibt es einen Unterschied, an welcher Stelle die 
seriellen Schnittstellen initialisiert werden müssen? Normalerweise 
macht man das ja im Setup-Block, wenn die Init aber vor diesem schon die 
Schnittstelle initialisiert, gibt es da ein Problem beim Atmega?

edit: ich vermute, BL0940 bl0940 ist eine Klasseninitialisierung?
edit2: alternativ wäre auch eine Änderung der Lib auf Atmega hilfreich, 
aber ich weiss halt nicht, an welcher Stelle sich was beisst :)

Danke für kurze Hilfe oder eine Lösung :)
Nik

: Bearbeitet durch User
von Harald K. (kirnbichler)


Lesenswert?

Nik A. schrieb:
> Wenn ich das gleiche für Atmega644 kompiliere, hängt sich der µC sofort
> auf, sobald BL0940 bl0940; aufgerufen wird.

Du wirst Dir den Konstruktor der Klasse BL0940 ansehen müssen. Dessen 
Deklaration wirst Du in der zugehörigen *.h-Datei finden, und dessen 
Definition entweder auch dort oder in der zugehörigen *.cpp-Datei.

Der Konstruktor einer Klasse wird aufgerufen, sobald ein Objekt dieser 
Klasse angelegt wird.

Legst Du Deine Objektinstanz als globale Variable (d.h. außerhalb eines 
Funktionsrumpfes) an, wird der Konstruktor aufgerufen, bevor irgendeine 
andere Funktion Deines Programmes aufgerufen wird.

von Veit D. (devil-elec)


Angehängte Dateien:

Lesenswert?

Hallo,

im Ordner "Sketchbook" gibt es einen Unterordner "libraries". Dorthin 
gehören alle neu hinzugefügten Libs. Installiere eine über die IDE 
Bibliotheksmanager, dann siehst du das Schema F.

> Wenn ich das gleiche für Atmega644 kompiliere, hängt sich der µC sofort
> auf, sobald BL0940 bl0940; aufgerufen wird.

Der µC kann sich nicht aufhängen, weil der dein Programm noch nicht hat.
Du meinst bei der Kompilierung bekommst du Fehlermeldungen? Schön.

Das nackte #include funktioniert?
1
BL0940 bl0940;
Hiermit erzeugst du eine Instanz. Ob das so richtig ist weiß ich nicht. 
Ich weiß ja nicht einmal was du alles geändert hast. Eigentlich weiß ich 
gar nicht was du überhaupt gemacht hast. Viel Text ohne eine wirklich 
verwertbare Information. Mit geänderten IDE Einstellungen siehst du mehr 
was schief läuft.

Gegenfrage. Wenn du nicht beteiligt bist und du liest deinen eigenen 
Text, weißt du dann Bescheid was der TO meint und was er so gemacht hat?

von Nik A. (nik_a)


Lesenswert?

@Harald K.: uff :) ich hab die 2 files in der IDE offen, aber warum 
funktioniert es denn für ESP32 und nicht für atmega(mightcore)?

@Veit D.: nein, ich meinte den µC. Beim Compilen hängt sich nix auf, das 
läuft perfekt durch.
Die Lib kann ich über den Manager nicht laden und will ich auch nicht, 
da ich für jeden µC den Code darin anpassen muss, da die entsprechende 
UART z.B. unterschiedlich ist.

Noch mal um Missverständnisse zu beseitigen: unter o.g. URL findet sich 
das Beispiel, das habe ich testweise einmal für ESP32 und einmal für 
atmega644 kompiliert, aber jeweils die richtige UART eingetragen.

Beides kompiliert, aber der atmega hängt sich auf. (kann man ja schön 
mit seriellen Test-Ausgaben rausfinden. Diese habe ich auch in jeder 
Funktion in der Lib eingebaut und da triggert keine einzige, wenn beim 
Atmega die Instanzerzeugung vor der Setup-Routine steht. Sobald die dort 
drin steht, sieht man, welche Funktionen ausgelöst werden.)

Schreibe ich den Konstruktor/die Erzeugung der Instanz aber in die 
Setup-Routine, (inclusive der Zeilen für Reset und Netzfrequenz, die im 
Beispiel stehen), dann läuft es.
Aber nur solange, wie ich in der Loop dann nicht Abfragen starte, denn 
dort existiert dann die Instanz nicht mehr, die nur im Setup-Block 
steht.

Es muss also irgendwo einen Unterschied zwischen ESP32 und mightycore 
geben.

Soweit ich sehen kann, wird die Setup-Routine nicht ausgelöst, wenn beim 
atmega die Instanzerzeugung vor dem Setup steht, wie es im Beispielcode 
für ESP32 der Fall ist.

Ganz ausführlich: Steht im Setup nur

Serial.begin(115200);
Serial.println("blah");

dann erscheint kein blah, wenn die Instanzerzeugung außerhalb steht. 
Steht sie drin, geht es, ebenso auch die Kommunikation mit dem BL0940.

von Sebastian W. (wangnick)


Lesenswert?

Nik A. schrieb:
> Ganz ausführlich: Steht im Setup nur
> Serial.begin(115200);
> Serial.println("blah");
> dann erscheint kein blah, wenn die Instanzerzeugung außerhalb steht.
> Steht sie drin, geht es, ebenso auch die Kommunikation mit dem BL0940.

Die Bibliothek ist so geschrieben, dass der uC mit dem BL0940 über eine 
serielle Schnittstelle mit 4800 Baud kommuniziert. Der Atmega644 hat nur 
eine solche Schnittstelle. Wenn diese eine Schnittstelle für die 
Kommunikation mit dem Sensor benutzt wird, dann darfst du sie nicht auch 
noch für Testausgaben benutzen.

LG, Sebastian

von Nik A. (nik_a)


Lesenswert?

@Sebastian: stimmt, ich hab ein Detail vergessen zu erwähnen: es ist ein 
atmega644A, der hat 2 UARTS und die gehen beide.

Wie gesagt, ich hab die Uarts und alle Code-Teile getestet.
Die gehen, lediglich die Instanzerzeugung für den BL0940 macht Probleme.

Die ESP32-Schaltung mit Code funktioniert perfekt, ich will das nur auf 
atmega644A portieren, den ich auch immer wieder verwende (mit 2 
hardware-UARTS) und besser schützen kann. Ich hatte nur noch nie das 
beschriebene Problem in den letzten >18 Jahren :>
Vorallem, weil es keine Compile-Fehler gibt :o

von Ein T. (ein_typ)


Lesenswert?

Nik A. schrieb:
> Wie gesagt, ich hab die Uarts und alle Code-Teile getestet.
> Die gehen, lediglich die Instanzerzeugung für den BL0940 macht Probleme.

Vielleicht hülfe ja ein Zeiger?
1
BL0940* bl0940 = NULL; 
2
3
void setup() {
4
    bl0940 = new BL0940();
5
    bl0940->Reset();
6
}

von Harald K. (kirnbichler)


Lesenswert?

Ein T. schrieb:
> Vielleicht hülfe ja ein Zeiger?

Das setzt eine dynamische Speicherverwaltung auf dem AVR voraus, und 
ohne sich den Konstruktor der Klasse anzusehen, weiß man nicht, 
wieviel Speicher diese Klasse benötigt.

Vielleicht einfach zu viel für den AVR?

von Sebastian W. (wangnick)


Lesenswert?

Nik A. schrieb:
> Wie gesagt, ich hab die Uarts und alle Code-Teile getestet.
> Die gehen, lediglich die Instanzerzeugung für den BL0940 macht Probleme.

Der Konstruktor BL0940::BL0940 ruft Serial2.begin(4800) auf. Was 
passiert, wenn du im Bibliothekscode diese Zeile in die 
BL0940::Reset-Methode verschiebst?

LG, Sebastian

von Wastl (hartundweichware)


Lesenswert?

Harald K. schrieb:
> ohne sich den Konstruktor der Klasse anzusehen, weiß man nicht,
> wieviel Speicher diese Klasse benötigt

Es gibt eine Fehlerbehandlung. Im einfachsten Fall bekommt man
bei new einen Nullpointer zurück der einem mitteilt dass etwas
schief geaufen ist.

Also ob es funktioniert (passt) oder nicht bekommt man durch
die trial-and-error-Methode heraus.

von Harald K. (kirnbichler)


Lesenswert?

..

(Streichen)

: Bearbeitet durch User
von Nik A. (nik_a)


Lesenswert?

Ich hab weiter experimentiert:

ich habe die Inhalte der cpp/h-Dateien einfach unten an den Sketch 
angehangen und entsprechend umbenannt.
also alles BL0940:: wurde zu BL0940_

die Funktionen entsprechend angepasst und die Variablen/Defs ganz nach 
oben an den Anfang.

Was ist passiert? Die Comm mit dem IC funktioniert auf einmal ...
Ich hab keine Erklärung.

Wie es aussieht, kommt es gar nicht erst bis zum .reset(), da passiert 
schon nichts mehr :o

von Nik A. (nik_a)


Lesenswert?

warum der Downvote auf ein Posting mit Fakten bzw. Beobachtungen?
typisch mikrocontroller.net XD

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Nik A. schrieb:
> warum der Downvote auf ein Posting mit Fakten bzw. Beobachtungen?
> typisch mikrocontroller.net XD

Das ist ein Bot, einfach nicht beachten.

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.