Ich wollte gerade meine eigene Klasse schreiben, die über I2C Daten an einem Raspberry zur Verfügung stellen soll. Allerdings Scheiter ich wohl schon an den Basics.
Kann mir hier jemand weiter helfen?
Der Fehler ist folgendes (übrigens das gilt das selbe für die onRequest Funktion, wenn diese nicht auskommentiert ist):
src/I2C_transmitter.h: In member function 'virtual void I2C_transmitter::setup()':
src/I2C_transmitter.h:11:32: error: invalid use of non-static member function
Wire.onRequest(requestEvent); // register event
^
*** [.pioenvs\suzs\src\main.cpp.o] Error 1
Mein Code (erst einmal die Basics
class I2C_transmitter : public Component {
public:
void setup() override {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
// Wire.onReceive(receiveEvent);
}
void loop() override {
}
void requestEvent() {
Wire.write("hello "); // respond with message of 6 bytes
// as expected by master
}
void receiveEvent(int howMany) {
myRegisterAddress = Wire.read();
}
};
Das include ändert leider nichts. Liegt es daran, dass es eine "externe" Klasse ist? Denn sonst habe ich es immer so genutzt und im " Master Reader/Slave Sender" Beispiel ist es auch so implementiert.
Du hast den Unterschied zwischen Methoden ("member function") und Funktionen nicht verstanden
Anderes Stichwort: this-Zeiger
Und auch mal darüber nachdenken was "static" in Klassen macht. Dann verstehst du auch weshalb das in der Fehlermeldung erwähnt wird
Du sollst das ja auch nicht nur hinschreiben, sondern nachschauen wie man es verwendet. Dazu musst du aber erst mal verstehen wieso es so nicht geht.
Man kann kann das per Hand machen. Mit einer Wrapper- und/oder Labmda-Funktion. Functional nimmt einem lediglich etwas von der Arbeit ab. Wobei es gut es zu wissen was da geschieht
Und wenn es wie hier nur um ein einzelnes statisches (globales) Objekt geht, braucht man ja gar keine Methode als callback, sondern schreibt eine simple Funktion.
Das sind keine Funktionen, sondern virtuelle Methode, welche die (leeren) Methoden der "pure abstract" Basisklasse überschreiben.
Sowas gibts nicht, void heißt "unbestimmt" oder "nicht vorhanden". Womit hier gemeint ist, dass diese Methoden keinen Wert zurückgeben.
Das bleibt dir überlassen.......
Habe nur dein, bis zur untestbarkeit verstümmeltes, Beispiel lauffähig gemacht.
Was du da in den Methoden erledigen willst, davon habe ich überhaupt keine Ahnung.
Einfacher geht es doch kaum. Das einzige was sich unterscheidet ist die Übergabe der Adresse der Funktion/Methode. Der Rest ist nur Teil des Beispiels. Du brauchst da keine virtuellen Methoden, aber es kann ja niemand wissen wie Component bei dir aussieht.
Lambda-Funktion sind letztlich auch nicht so kompliziert wie sie aussehen. Siehe hier:
Die eckigen Klammern geben nur an welche Variablen in der Lamda-Funktion sichtbar sind. Eben keine.
Das ist aber sehr schön, weil man es sich sparen kann eine extra Wrapper-Funktion schreiben. Dadurch ist es eben einfacher als andere Optionen
Ich halte C++ (auch) für eine recht "hässliche" Sprache.
Aber andererseits auch für sehr mächtig.
Es ist ein knackiges Werkzeug mit vielen Ecken und scharfen Kanten.
Zudem ist die Anzahl der Alternativen im Arduino Umfeld sonst eher nahe Null. C++, C und ASM, das wars.
ASM und C sind auch nicht wirklich "schöner", als C++
Eigentlich ist es schon etwas traurig, dass Wire kein Interface für sowas bereit stellt. z.B. in einer vereinfachten Form des:
Die Lamda Funktionen sind nur ein ganz naiver Abklatsch des:
Der Hinweis auf den Unterschied zwischen Methode und Funktion scheint untergegangen zu sein.
Wenn dir (@tsaG1337) alles zu kompliziert vorkommt, schreib eine einfache Funktion als callback, die bei Bedarf das I2C_transmitter-Objekt trans verwendet (evtl. eine dessen Methoden aufruft).
Genau wie Wire ein Singleton-Objekt ist, könntest du das auch mit deinem I2C_transmitter machen, aber das wird dann wieder verwirrend, fürchte ich.
Ja, ich habe gerade mit meinen eigenen Klassen angefangen und ich komme auch nicht aus dem IT Sektor, daher sind das für mich alles noch Böhmische Dörfer.
Werde versuchen mich mal schlau zu lesen.
Was ich wollte, war eigentlich nur eine eigene Klasse um ein paar Variable von ESPhome über I2C Zugänglich zu machen.
Damit wollte ich nur sagen, dass ich mich gewundert habe, das in deinem obigen Beispiel die "normalen voids" sowohl als auch die overrides dazu drin waren.
Hier weiss ich leider nicht was Du meinst. Ich scheiterte schon daran die "on Receive" und "on Request" Funktion zu implementieren. Verstümmelt habe ich da nichts, da es bisher auch nicht mehr gab
Dann lass mal die overrides weg und sehe was passiert. Abstrakte Methoden ("pure virtual function" in C++; mit dem =0) muss man implementieren. Das ist anders als bei einfachen virtuellen Methoden keine Option.
#include <Wire.h>
class Component
{
public:
virtual void setup() = 0;
virtual void loop() = 0;
};
class I2C_transmitter : public Component
{
public:
I2C_transmitter trans;
void setup()
{
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest([](){trans.requestEvent();});
Wire.onReceive([](int howMany){trans.receiveEvent(howMany);});
}
void loop()
{
}
Fehlermeldung:
In file included from src/main.cpp:124:0:
src/I2C_transmitter.h:11:32: error: reference to 'Component' is ambiguous
class I2C_transmitter : public Component
^
src/I2C_transmitter.h:4:7: note: candidates are: class Component
class Component
^
In file included from src/esphome\components\adc\adc_sensor.h:3:0,
from src/esphome.h:2,
from src/main.cpp:3:
src/esphome/core/component.h:58:7: note: class esphome::Component
class Component {
^
In file included from src/main.cpp:124:0:
src/I2C_transmitter.h:17:17: error: field 'trans' has incomplete type 'I2C_transmitter'
I2C_transmitter trans;
^
src/I2C_transmitter.h:11:7: note: definition of 'class I2C_transmitter' is not complete until the closing brace
class I2C_transmitter : public Component
^
src/main.cpp:127:6: error: 'void I2C_transmitter::setup()' cannot be overloaded
void setup() {
^
In file included from src/main.cpp:124:0:
src/I2C_transmitter.h:19:6: error: with 'void I2C_transmitter::setup()'
void setup()
^
c:\Dropsbpox\Elektronik\Lichterfest\Firmware\ESPHome\Config.yaml:407:6: error: 'void I2C_transmitter::loop()' cannot be overloaded
In file included from src/main.cpp:124:0:
src/I2C_transmitter.h:26:6: error: with 'void I2C_transmitter::loop()'
void loop()
^
c:\Dropsbpox\Elektronik\Lichterfest\Firmware\ESPHome\Config.yaml:409:1: error: expected '}' at end of input
In file included from src/main.cpp:124:0:
src/I2C_transmitter.h: In lambda function:
src/I2C_transmitter.h:22:23: error: 'this' was not captured for this lambda function
Wire.onRequest([](){trans.requestEvent();});
^
src/I2C_transmitter.h:22:23: error: invalid use of non-static data member 'I2C_transmitter::trans'
src/I2C_transmitter.h:17:17: note: declared here
I2C_transmitter trans;
^
src/I2C_transmitter.h: In lambda function:
src/I2C_transmitter.h:23:34: error: 'this' was not captured for this lambda function
Wire.onReceive([](int howMany){trans.receiveEvent(howMany);});
^
src/I2C_transmitter.h:23:34: error: invalid use of non-static data member 'I2C_transmitter::trans'
src/I2C_transmitter.h:17:17: note: declared here
I2C_transmitter trans;
^
c:\Dropsbpox\Elektronik\Lichterfest\Firmware\ESPHome\Config.yaml: At global scope:
c:\Dropsbpox\Elektronik\Lichterfest\Firmware\ESPHome\Config.yaml:409:1: error: expected unqualified-id at end of input
*** [.pioenvs\suzs\src\main.cpp.o] Error 1
======================================================= [FAILED] Took 4.02 seconds =======================================================
PS C:\Dropsbpox\Elektronik\Lichterfest\Firmware\ESPHome>
Nein. So nicht. Jetzt hast du die Klasse völlig verstümmelt und der Compiler weiß nicht mehr was was ist. Das meiste sind lediglich Folge-Fehler weil die schließende Klammer der Klasse fehlt
Du verwendest die Worte falsch. Ich kenne weder "voids", so auch keine "normalen voids" oder "anormale voids", und auch keine "overrides".
Falls du die beiden override Statements/Attribute in meiner Klasse meinst, sorry, aber die sind auf deinen Mist gewachsen. Für die muss ich sämtliche Verantwortung ablehnen, außer, dass ich es lauffähig gemacht habe.
setup() und loop() hast du in die Klasse eingeführt. Also habe ich sie auch da gelassen! Die onRequest() und onReceive() willst du ja auch in deiner Klasse haben. Die habe ich nur nutzbar gemacht.
Also:
Ich verstehe nicht, dein Wundern.
(frei nach Joda)