2017-05-17 4 views
0

Ich versuche, meine Arduino-Klasse String-Nachrichten mit allen Arten von Informationen für die Protokollierung zurückzugeben. Mit viel Versuch und Irrtum gelang es mir, einen Verweis auf die Logging-Funktion an die Klasse zu übergeben, aber ich kann nur ein char *, aber keinen String bekommen, und ich möchte Strings senden können, was es so viel einfacher macht, alles zurückzusenden Arten von Daten.Arduino: Funktion an Klasse übergeben, Rückgabe String

Ich habe den ersten Teil bereits funktioniert. Die Skizze:

#include <Test.h> 
#include <string.h> 

void setup() { 
    Serial.begin(115200); 
    Test t; 
    t.setLogging(writeLog); 
    writeLog("Test message!" + String(" .... ")); 
    t.doSomething("This is useful."); 
    t.doSomething("This as well.\n"); 
    t.doSomething("This is even more useful.\n"); 
    bool b = true; 

} 

void loop() { 
} 

void writeLog (char* message) { 
    Serial.print("char function: "); 
    Serial.print(message); 
} 

void writeLog (String message) { 
    Serial.print("String function: "); 
    Serial.println(message); 
} 

Die Header-Datei:

#ifndef TEST_h 
#define TEST_h 

class Test 
{ 
    public: 
    Test();  // The constructor. 
    void setLogging(void (*)(char*)); // Takes function setting where to log. 
    void doSomething(char*); 
}; 

#endif 

Die Klasse:

#include <Test.h> 

typedef void (*LogFunction)(char*); 
LogFunction writeLog; 

Test::Test() { 
} 

void Test::doSomething (char* s) { 

    // Do something useful and log the result. 
    writeLog(s); 
} 

void Test::setLogging (void (*f)(char*)) { 
    writeLog = f; 
    return; 
} 

Nun, was ich meine Klasse wollen, ist zu tun, um der Lage sein, Informationen wie diese senden, wie String, nicht char * (Ich habe auch keinen einfachen Weg gefunden, "alles" in char * umzuwandeln und dann die zwei oder mehr Strings zu verketten):

writeLog ("HydroMonitorECSensor::setCalibration Receiving calibration - haveCalibration = " + String(haveCalibration)); 
writeLog ("HydroMonitorECSensor::setCalibration calibratedSlope = " + String(calibratedSlope)); 
writeLog ("HydroMonitorECSensor::setPins capPos set to " + String(capPos)); 

Wo haveCalibration ist ein bool (die als String wird entweder "wahr" oder "falsch"), ein calibratedSlopedouble und capPos ist ein int. So kann ich einfach und sauber komplette Zeilen an den Logger senden. Funktioniert super innerhalb des Hauptskriptes - nicht von der Klasse.

Ich versuchte einfach, die char* zu String zu ändern und #include <string.h> zu den Bibliotheksdateien hinzuzufügen, aber es funktioniert nicht.

In Test.cpp ich dann void Test::setLogging (void (*f)(String)) { und in Test.h void setLogging(void (*)(String)); und ich bekomme jetzt Fehlermeldungen:

In file included from /home/wouter/Arduino/libraries/Test/Test.cpp:1:0: 
/home/wouter/Arduino/libraries/Test/Test.h:10:29: error: expected ',' or '...' before '(' token 
    void setLogging(void (*)(String)); // Takes function setting where to log. 
          ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:40: error: variable or field 'setLogging' declared void 
void Test::setLogging (void (*f)(String)) { 
             ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:31: error: 'f' was not declared in this scope 
void Test::setLogging (void (*f)(String)) { 
          ^
/home/wouter/Arduino/libraries/Test/Test.cpp:16:34: error: 'String' was not declared in this scope 
void Test::setLogging (void (*f)(String)) { 
           ^
exit status 1 
Error compiling for board NodeMCU 1.0 (ESP-12E Module). 

Verbesserungsvorschläge?

Zusätzliche Informationen, vielleicht wichtig: Ich verwende die Arduino IDE und kompiliere für ESP8266.

Antwort

2

Sie verwenden die Arduino-String-Klasse, aber nicht die Arduino.h-Header in Ihrer test.h Header-Datei. Das führt dazu, dass die Klasse String nicht gefunden wird und die Kompilierung fehlschlägt.

Die folgenden Werke:

main.cpp:

#include <Arduino.h> 
#include <test.hpp> 

void writeLog (char* message); 
void writeLog (String message); 

void setup() { 
    Serial.begin(115200); 
    Test t; 
    t.setLogging(writeLog); 
    writeLog("Test message!" + String(" .... ")); 
    t.doSomething("This is useful."); 
    t.doSomething("This as well.\n"); 
    t.doSomething("This is even more useful.\n"); 
    bool b = true; 

} 

void loop() { 
} 

void writeLog (char* message) { 
    Serial.print("char function: "); 
    Serial.print(message); 
} 

void writeLog (String message) { 
    Serial.print("String function: "); 
    Serial.println(message); 
} 

test.hpp:

#ifndef TEST_h 
#define TEST_h 

#include <Arduino.h> //for "String" class 

//Typdef for the log function. Takes a String, returns nothing 
typedef void (*LogFunction)(String); 

class Test 
{ 
    public: 
    Test();  // The constructor. 
    // void setLogging(void (*)(char*)); // Takes function setting where to log. 
    void setLogging(LogFunction); //use the typedef here 
    void doSomething(char*); 
}; 

#endif 

test.cpp:

#include <test.hpp> 


LogFunction writeLog; 

Test::Test() { 
} 

void Test::doSomething (char* s) { 

    // Do something useful and log the result. 
    writeLog(s); 
} 

//void Test::setLogging (void (*f)(char*)) { 
void Test::setLogging (LogFunction f) { //also use typedef here 
    writeLog = f; 
    return; 
} 
+0

Ja, das funktioniert! Ich habe tatsächlich versucht, die Arduino.h zuvor hinzufügen, aber muss etwas anderes falsch gemacht haben, da es nicht funktioniert hat. In meiner Hauptskizze habe ich auch das nicht einschließen, aber es kompiliert noch, brauchte nie dieses Arduino.h, weiß nicht, wie das funktioniert ... Danke für die schnelle Antwort. – Wouter

+0

Wenn ich darüber nachdenke, habe ich vielleicht nicht versucht, 'Arduino.h' einzubeziehen, nicht allzu sicher, da ich viel probiert habe und am Ende total frustriert war, dies und das zu versuchen und nichts hat funktioniert, aber ich habe es mit Sicherheit versucht um 'string.h' einzuschließen. Letzteres ist nach allem, was ich in meinen normalen Skizzen brauche, um die 'String'-Typen verwenden zu können. – Wouter

0

Der Compiler teilt Ihnen unter anderem mit, dass er den Bezeichner String nicht auflösen kann. Dies kann mehrere Gründe haben: Erstens schreiben Sie String, und nicht string (beachten Sie den Großbuchstaben in Ihrem Schreiben). Zweitens, wenn Sie string und nicht std::string schreiben, kann es nicht aufgelöst werden, es sei denn, Sie haben entweder using namespace std deklariert (was aus verschiedenen Gründen nicht die bevorzugte Variante ist) oder using std::string. Drittens ist die Klasse std::string im Header <string> deklariert, was etwas anderes ist als <string.h>.

Also würde ich #include <string> schreiben und dann std::string verwenden.

+2

Dies verwendet die Arduino 'String' Klasse, keine' std :: string'. –

+1

Das ist ein Unterschied zwischen Standard C/C++ und Arduino (der gepostete Code kompiliert in der Arduino IDE). String ist die Arduino-Version, std :: string ist die C-Version und die beiden sind nicht kompatibel. Ich habe tatsächlich std :: string versucht und es nicht zum Laufen gebracht. – Wouter

+0

@Maximilian Gerhardt: OK; Ich dachte OP zielt auf die C++ - String-Klasse. +1, um darauf hingewiesen zu haben. BTW: Warum würde nicht std :: string nicht funktionieren? –

Verwandte Themen