RFM26 Funkmodul - Fragen zur Zeichenkette

Hallo Community,

ich verwende aktuell zwei Arduino Nano R3 mit jeweils einem RF26W Funkmodul. Die Funkverbindung (test mit dem Beispielsketch) funktioniert hervorragend.

Ich stehe gerade nur etwas auf dem Schlauch, wenn ich Messdaten (liegen als Float vor) versenden will. Ich bekomme die Floatvariable nicht als uint8_t konvertiert. Mein Beispielcode sieht wie folgt aus:

uint8_t data[] = "Testnachricht";

 
rf24.send(data, sizeof(data));

Dieser Ausschnit aus dem Quellcode funktioniert sehr gut. Ich habe aber mehrere Sensoren, die ich in einem String versenden möchte. Kann mir jemand von euch mitteilen, wie ich in das data[] array die Strings speichern kann?

Exemplarisch würden die Floatvariablen wie folgt vorliegen:

float Messwert1 = 24.5;
float Messwert2 = 25.5;
float Messwert3 = 26.5;


String datastring = String(Messwert1)+String(Messwert2)+String(Messwert3);
uint8_t data[] = {datastring};

 
  rf24.send(data, sizeof(data));

Die Fehlermeldung ist

error: cannot convert 'String' to 'uint8_t {aka unsigned char}' in initialization

Wie kann man nun einen String in unint8_t konvertieren?

Besten Dank!

Ich hätte da snprintf() im Angebot:

void setup()
{
  char data[100];
  float Messwert1 = 24.5;
  float Messwert2 = 25.5;
  float Messwert3 = 26.5;
  int m1 = Messwert1 * 10;
  int m2 = Messwert2 * 10;
  int m3 = Messwert3 * 10;
  Serial.begin(9600);
  Serial.println("Anfang");
  snprintf(data, sizeof(data), "Messwert1=%3d.%1d&Messwert2=%3d.%1d&Messwert3=%3d.%1d", m1 / 10, abs(m1 % 10), m2 / 10, abs(m2 % 10), m3 / 10, abs(m3 % 10));
  Serial.print("data ");
  Serial.println(data);
}

void loop() {}

Das stammt aus der Trickkiste von jurs :slight_smile:

Die String Klasse sollte auf einem Arduino möglichst nicht verwendet werden, die üblichen C strings (char[]) funktionieren da besser.

Willst Du die Werte binär oder als Text übertragen? Für binär reicht ein typecast in ein Byte array, für Text kann sowas wie atof() und ftoa() zur Konvertierung verwendet werden.

Am besten wie gesagt direkt C strings verwenden. Ist mit Float etwas schwierig wegen der Limitation von printf(), aber wie oben gezeigt geht es über Umwege.

Ansonsten kommst du mit c_str() an das interne Array eines String Objekts. Nur für Lese-Zugriff aber es reicht für die Übergabe an eine Funktion die einen C String erwartet:

rf24.send(datastring.c_str(), datastring.length());
  • 1 wenn du den Null-Terminator auch senden willst.

Hi und sorry für die verspätete Antwort meinerseits.

Wenn ich das mit einem char Array versuche, erhalte ich folgende Fehlermeldung:

rror:   initializing argument 1 of 'virtual bool RH_RF24::send(const uint8_t*, uint8_t)' [-fpermissive]
     bool        send(const uint8_t* data, uint8_t len);

... Ich gehe stark davon aus, dass die Funktion ein uint8_t erwartet?

Ich verstehe aktuell nicht den Vorteil davon, ein uint8_t zu verwenden ....

Ich verwende folgende Bibliothek: RadioHead: RH_RF24 Class Reference

Ich stehe damit momentan echt auf dem Schlauch .. :confused:

Gruß

Die Funktion erwartet ein uint8_t Array, kein char Array. Versuchs mal mit einem entsprechenden Typecast (uint8_t*).

Hi,

ich habe es mit dieser Anleitung hinbekommen (für alle die ggf. auf das gleiche Problem stoßen)
https://forum.arduino.cc/index.php?topic=313587.0

Vielen Dank an euch!!

Wer zu spät kommt ...

Von Serenifly habe ich was über union gelernt, spart eigentlich nur das Kopieren. Da ich es aber schonmal gemacht habe, gebe ich auch diese Variante zum Besten:

void setup()
{
  union d_u {
    char d[100];
    uint8_t data[100];
  };
  d_u daten;
  float Messwert1 = 24.5;
  float Messwert2 = 25.5;
  float Messwert3 = 26.5;
  int m1 = Messwert1 * 10;
  int m2 = Messwert2 * 10;
  int m3 = Messwert3 * 10;
  Serial.begin(9600);
  Serial.println("Anfang");
  snprintf(daten.d, sizeof(daten.d), "Messwert1=%3d.%1d&Messwert2=%3d.%1d&Messwert3=%3d.%1d", m1 / 10, abs(m1 % 10), m2 / 10, abs(m2 % 10), m3 / 10, abs(m3 % 10));
  Serial.print("daten.d:   \t");
  Serial.println(daten.d);
  Serial.print("daten.data:\t");
  for (byte j = 0; j < sizeof(daten.data); j++) {
    if ((char) daten.data[j] == '\0')break;
    Serial.print((char) daten.data[j]);
  }
  Serial.println();
}

void loop() {}

Aber Latte und Kuchen waren auch lecker und die "Verspätung" wert :wink:

Das ist in diesem Fall viel zu weit ausgeholt. C/C++ ist nur schwach typisiert. Man kann also vieles einfach durch Casts erschlagen (auch Float nach Byte Array kann man durch Casts erledigen, auch wenn es nicht so sauber ist).

Man kann einfach char* auf unsigned char* oder const char* auf const unsigned char* casten.

Hier einfacher Test Code:

void setup() 
{
  String test = "test";

  func((const unsigned char*)test.c_str());
}

void loop() 
{
}

void func(const unsigned char* s)
{
  Serial.println((const char*)s);
}

Die Funktion hat const unsigned char* als Parameter. c_str() liefert einen const char*. Also einfach casten und gut ist.

Wenn man einen C String hat (d.h. ein char Array) hat, dann ist die Array Variable schon eine Adresse und diese kann dann natürlich auch auf unsigned char* gecastet werden.

uint_8t = unsigned char falls das immer noch nicht klar ist.

Ich verstehe aktuell nicht den Vorteil davon, ein uint8_t zu verwenden ....

Damit man auch einfach Binär-Daten verschicken kann. Dadurch dass Casts so simpel sind geht dann sowohl das als auch C Strings. Beides sind Arrays aus Bytes. Der winzige Unterschied ist signed oder unsigned.

Warum einfach, wenn es auch kompliziert geht :o

Na gut, ich habe noch Serial.begin ergänzt:

void setup()
{
  char buf[100];
  float Messwert1 = 24.5;
  float Messwert2 = 25.5;
  float Messwert3 = 26.5;
  int m1 = Messwert1 * 10;
  int m2 = Messwert2 * 10;
  int m3 = Messwert3 * 10;
  Serial.begin(9600);
  Serial.println("Anfang");
  snprintf(buf, sizeof(buf), "Messwert1=%3d.%1d&Messwert2=%3d.%1d&Messwert3=%3d.%1d", m1 / 10, abs(m1 % 10), m2 / 10, abs(m2 % 10), m3 / 10, abs(m3 % 10));
  Serial.println(buf);
  func((uint8_t *)buf);
}

void loop() {}

void func(uint8_t * s)
{
  Serial.println((char*)s);
}