Float array über NRF24L01 senden und empfangen

Hallo,

ich will einen Datensatz von 10 float Werten mit einem float array von einem Arduino Zero zu einem Mega senden. (über einen NRF24L01)
Dabei handeltes sich um 8 Temp. Werte von einem MAX31856 Sensor und den Temp. und Feuchte Wert von einem HYT939 Feuchtesensor.

Mein Problem ist, dass nur 8 Wert korrekt ausgegeben werden, beim Wert 9 und 10 bekomme ich nur 0.00.

Hier meine Sketches:

TX (Zero):

// TX für Daten


#include <Wire.h>
#include <Adafruit_MAX31856.h>
#include <RF24.h>

#define HYT939_ADDR 0x28

RF24 radio(6,7);
const byte address[6] = "00001";

Adafruit_MAX31856 tc1 = Adafruit_MAX31856(A3, 1, 2, 3);
Adafruit_MAX31856 tc2 = Adafruit_MAX31856(A2, 1, 2, 3);
Adafruit_MAX31856 tc3 = Adafruit_MAX31856(A1, 1, 2, 3);
Adafruit_MAX31856 tc4 = Adafruit_MAX31856(A0, 1, 2, 3);
Adafruit_MAX31856 tc5 = Adafruit_MAX31856(5, 1, 2, 3);
Adafruit_MAX31856 tc6 = Adafruit_MAX31856(4, 1, 2, 3);
Adafruit_MAX31856 tc7 = Adafruit_MAX31856(A5, 1, 2, 3);
Adafruit_MAX31856 tc8 = Adafruit_MAX31856(A4, 1, 2, 3);



void setup() {
  Serial.begin(115200);

  tc1.begin();
  tc1.setThermocoupleType(MAX31856_TCTYPE_K);
  tc2.begin();
  tc2.setThermocoupleType(MAX31856_TCTYPE_K);
  tc3.begin();
  tc3.setThermocoupleType(MAX31856_TCTYPE_K);
  tc4.begin();
  tc4.setThermocoupleType(MAX31856_TCTYPE_K);
  tc5.begin();
  tc5.setThermocoupleType(MAX31856_TCTYPE_K);
  tc6.begin();
  tc6.setThermocoupleType(MAX31856_TCTYPE_K);
  tc7.begin();
  tc7.setThermocoupleType(MAX31856_TCTYPE_K);
  tc8.begin();
  tc8.setThermocoupleType(MAX31856_TCTYPE_K);
  
  Wire.begin();

  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_HIGH);     //Transmit Power (MAX,HIGH,LOW,MIN)
  radio.setDataRate( RF24_250KBPS );  //Transmit Speeed (250 Kbits per second, maximal 2 Mb/s)
  //radio.enableDynamicPayloads();
}

void loop() {

#define TFACTOR 99.2909       //Skalierungsfaktoren laut Datenblatt
#define TDELTA  40.0
#define HFACTOR 163.83

  unsigned int traw;
  unsigned int hraw;
    
  float temp;
  float hum;
  int i;
  unsigned char buffer[4];
  
 Wire.beginTransmission(HYT939_ADDR);
 Wire.endTransmission();
 
  delay(100);   //100ms warten
  
  Wire.requestFrom(HYT939_ADDR, 4,true);     //4 Bytes vom Sensor lesen
  
  i=0;
  
while(Wire.available()) {
    
    char c = Wire.read();
  
    buffer[i]=c;
        
    i++;
  
    }
   
  traw=buffer[2]*256+buffer[3];     //Rohdaten aus Puffer lesen
  hraw=buffer[0]*256+buffer[1];
  
 
traw&=0xfffc;
hraw&=0x3fff;        //Daten laut Datenblatt maskieren
traw>>=2;

/*
//Rohdaten ausgeben, zur eventuellen Fehlersuche
Serial.print("\r\nTemp Raw:");
Serial.println(traw);
Serial.print("Hum Raw:");
Serial.println(hraw);
*/

//Rohdaten Umrechnen

temp=(float)traw/TFACTOR;
temp=temp-TDELTA;

hum=(float)hraw/HFACTOR;


  float dataout[10];
  float j;
  
  dataout[0] = temp;
  dataout[1] = hum;
  dataout[2] = tc1.readThermocoupleTemperature(); 
  dataout[3] = tc2.readThermocoupleTemperature();
  dataout[4] = tc3.readThermocoupleTemperature();
  dataout[5] = tc4.readThermocoupleTemperature();
  dataout[6] = tc5.readThermocoupleTemperature();
  dataout[7] = tc6.readThermocoupleTemperature();
  dataout[8] = tc7.readThermocoupleTemperature();
  dataout[9] = tc8.readThermocoupleTemperature();
  

  radio.write(dataout, sizeof(dataout));
}

RX (Mega):

// RX für Daten


#include <RF24.h>

RF24 radio(6, 7);                    // CNS, CE

const byte address[6] = "00001";


void setup() {
  
  Serial.begin(115200);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_HIGH);       //Transmit Power (MAX,HIGH,LOW,MIN)
  radio.setDataRate( RF24_250KBPS );    //Transmit Speeed (250 Kbits per second, maximal 2Mb/s)
  //radio.enableDynamicPayloads();
  radio.startListening();
}


void loop() {

float got_dataout[10];

float j;

if (radio.available()) {
  radio.read(got_dataout, sizeof(got_dataout));

for (byte j = 0; j < 10; ++j ) {
  Serial.print(got_dataout[j]);
  Serial.print("\t");
}

Serial.println("");
}

}

hat vll jemand eine Idee wo mein Fehler ist?

LG

hat vll jemand eine Idee wo mein Fehler ist?

Ja, eine Ahnung....

Die Payloadsize ist maximal 32 Byte.
Ein float ist 4 Byte groß
Also passen exakt 8 float Values in ein Datenpaket.

:o :o :o :o :o :o

Aaah, ja das macht Sinn..

Dann müsste ich einen zweiten array senden.. oder hättest du irgend eine idee wie ich die Daten gemeinsam als "Datenpaket" senden kann?

LG

Tja....
Diese RF24Network Library kann mit Fragmentierungen umgehen

Ok.. und wie müsste ich da vorgehen?

Hmmm....

Programmieren?

Beispiele anschauen, analysieren, nachdenken, umsetzen.

struct Paket {
  byte ersterIndex;
  byte anzahlElemente;
  float element[7];
};

Damit könntest du Arrays bis zu 256 Elementen in bis zu 7 Element langen Stücken übertragen.
Wenn du nur jetzt mal schnell 10 Elemente haben willst, ist das vielleicht praktischer

struct Paket {
  bool ersterTeil;
  float element[5];
};

Ich glaube, ihm haben Eure Antworten nicht gefallen. Crossposting.

Gruß Tommy

Vielleicht hat ja sonst jemand etwas davon. :wink:

Hi

HotSystems ... im Nachbar-Universum:
Aber wenn man fertige Lösungen haben möchte, ist doch Mikrocontroller.net das richtige Forum, oder ?

Du böhöser Mensch, Du :slight_smile:
Ich höre schon den Teer blubbern :wink:

MfG

Tommy56:
Ich glaube, ihm haben Eure Antworten nicht gefallen. Crossposting.

Ja, das tut mir auch ein bisschen leid.

Aber nun, wenn denn meine Wühlkiste sowas nicht ad hoc hergibt, dann mache ich mir auch nicht unbedingt die Arbeit.

Zumal der Vorschlag von Whandall mit etwas Überlegung durch den TO auch direkt einsetzbar ist.

Gruß Tommy

durch den TO auch direkt einsetzbar

Glaube ich eher nicht....

ca 5 Minuten hat der TO benötigt um festzustellen, das er mit der von mir genannten Lib nicht weiterkommt. Das reicht noch nicht mal um die Doku zu finden und die erste Seite zu lesen.

Schade eigentlich ...

Ja, da war mein Ansatz mit Überlegung von seiner Seite wohl zu optimistisch.

Gruß Tommy

Wie auch immer, ist ja ein ganz interessantes Problem das einigermaßen effizient zu lösen.

Ein Sender könnte z.B. so aussehen:

// TX

#include <Wire.h>
#include <Adafruit_MAX31856.h>
#include <RF24.h>

struct TwoPackets {
  bool ersterTeil;
  float data[10];
  void swapData() {
    for (byte i = 0; i < 5; i++) {
      float swp = data[i];
      data[i] = data[i + 5];
      data[i + 5] = swp;
    }
  }
  bool send(RF24& radio) {
    bool result = true;
    ersterTeil = true;
    if (!radio.write(this, 5 * sizeof(float) + 1)) {
      result = false;
      Serial.println(F("tx part 1 failed"));
    }
    swapData();
    ersterTeil = false;
    if (!radio.write(this, 5 * sizeof(float) + 1)) {
      result = false;
      Serial.println(F("tx part 2 failed"));
    }
    swapData();
    return result;
  }
} pack;

#define HYT939_ADDR 0x28

RF24 radio(6, 7);
const byte address[6] = "00001";

Adafruit_MAX31856 tSensors[] = {
  {A3, 1, 2, 3}, {A2, 1, 2, 3}, {A1, 1, 2, 3}, {A0, 1, 2, 3},
  {5, 1, 2, 3}, {4, 1, 2, 3}, {A5, 1, 2, 3}, {A4, 1, 2, 3},
};
const byte numSensors = sizeof(tSensors) / sizeof(tSensors[0]);

void setup() {
  Serial.begin(250000);
  for ( auto& tc : tSensors) {
    tc.begin();
    tc.setThermocoupleType(MAX31856_TCTYPE_K);
  }
  Wire.begin();
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setDataRate(RF24_250KBPS);
  radio.enableDynamicPayloads();
}

void loop() {
  static uint32_t lastSample;
  if (millis() - lastSample >= 1000) {
    lastSample = millis();
    getTempAndHum(pack.data[0], pack.data[1]);
    for (byte i = 0; i < numSensors; i++) {
      pack.data[i + 2] = tSensors[i].readThermocoupleTemperature();
    }
    pack.send(radio);
  }
}

void getTempAndHum(float& temperatur, float& feuchtigkeit) {

#define TFACTOR 99.2909       //Skalierungsfaktoren laut Datenblatt
#define TDELTA  40.0
#define HFACTOR 163.83

  uint8_t buffer[4];

  Wire.beginTransmission(HYT939_ADDR);
  Wire.endTransmission();
  delay(100);   //100ms warten
  Wire.requestFrom(HYT939_ADDR, 4, true);
  for (byte i = 0; Wire.available() && i < 4; i++) {
    buffer[i] = Wire.read();
  }
  uint16_t traw = buffer[2] * 256 + buffer[3];
  //traw &= 0xfffc; // warum maskieren um sie dann rauszushiften?
  traw >>= 2;

  uint16_t hraw = buffer[0] * 256 + buffer[1];
  hraw &= 0x3fff;      // laut Datenblatt
  temperatur = (float)traw / TFACTOR - TDELTA;
  feuchtigkeit = (float)hraw / HFACTOR;
}

Der Empfänger sollte natürlich etwas anders vorgehen, d.h. den Array aus den Paketen füllen,
dort kommt man um einen zusätzlichen Paketpuffer nicht herum.

Vielen Dank Whandall für deine Vorschläge aber ich habe eine für mich einfacherer Lösung gefunden.
Sende die Werte jetzt als short.. und multipliziere die Werte davor mit 10 und dividiere nach dem senden durch 10.
Beim Feuchtesensor mit 100. Die Genauigkeit genügt mir und es funktioniert einfach und gut.

Für deinen Ansatz fehlt mir das nötige Know How um das ordentlich durchführen zu können.

Trotzdem Danke!

LG

Wie du dem Sketch ansehen kannst, ist auch ein Versenden von 10 floats ohne Probleme möglich.

Wenn du jetzt 16 ints sendest passt das natürlich und man muss es nicht komplizierter machen als es ist.

Ich würde dir dennoch empfehlen nicht nur die Sensoren zum Bremsen von loop zu benutzen,
mit millis ist das viel sauberer und auch kontrollierter.

Alles klar. Vielen Dank für den Hinweis!
LG Flo