NRF24L01 mehrere Sender, ein Empfänger

Hallo,

ich habe ein Problem beim Senden von Daten mit dem NRF24L01 Modul.
Ich möchte von zwei Arduino ZEROS zu einem MEGA senden.

Dazu möchte ich 2 der 6 möglichen Pipes nutzen.

Beide Zeros zeichnen Temperatur und Feuchtedaten auf. Mit einem Zero auf den Mega senden funktioniert ohne Probleme doch wenn ich eine zweite Addresse hinzufüge und von beiden senden möchten kommen die Daten teilweise durcheinander und ich weiß leider nicht warum bzw. kann ich den Fehler nicht finden.

Hier sind meine Codes:

TX1:

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

#define HYT939_ADDR1 0x28
#define HYT939_ADDR2 0x31

RF24 radio(6,7);
//const byte address[6] = "00001";
//const uint64_t pipes[3] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL };
//const byte pipes[2] = { 00001, 00002 };
unsigned char ADDRESS0[5] = {0xb1,0x43,0x88,0x99,0x45};

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.openWritingPipe(ADDRESS0);
  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)
}

void loop() {

#define TFACTOR 99.2909       //Skalierungsfaktoren laut Datenblatt
#define TDELTA  40.0
#define HFACTOR 163.83
unsigned char buffer[4];

//Erster Feuchtesensor, Addresse 0x28
  unsigned int traw1;
  unsigned int hraw1;   
  float temp1;
  float hum1;
  int i;
  
  Wire.beginTransmission(HYT939_ADDR1);
  Wire.endTransmission();
  delay(100);   //100ms warten
  Wire.requestFrom(HYT939_ADDR1, 4,true);     //4 Bytes vom Sensor lesen
  
  i=0;
  
while(Wire.available()) {
    char c = Wire.read();
    buffer[i]=c;   
    i++;}
   
  traw1=buffer[2]*256+buffer[3];     //Rohdaten aus Puffer lesen
  hraw1=buffer[0]*256+buffer[1];
  
  traw1&=0xfffc;
  hraw1&=0x3fff;        //Daten laut Datenblatt maskieren
  traw1>>=2;
  
//Zweiter Feuchtesensor, Addresse 0x31
  unsigned int traw2;
  unsigned int hraw2;   
  float temp2;
  float hum2;
  int j;
  
  Wire.beginTransmission(HYT939_ADDR2);
  Wire.endTransmission();
  delay(100);   //100ms warten
  Wire.requestFrom(HYT939_ADDR2, 4,true);     //4 Bytes vom Sensor lesen
  
  j=0;
  
while(Wire.available()) {
    char c = Wire.read();
    buffer[j]=c;   
    j++;}
   
  traw2=buffer[2]*256+buffer[3];     //Rohdaten aus Puffer lesen
  hraw2=buffer[0]*256+buffer[1];
  
  traw2&=0xfffc;
  hraw2&=0x3fff;        //Daten laut Datenblatt maskieren
  traw2>>=2;

//Rohdaten Umrechnen

temp1=(float)traw1/TFACTOR;
temp1=(temp1-TDELTA)*100;
hum1=(float)hraw1/HFACTOR*100;

temp2=(float)traw2/TFACTOR;
temp2=(temp2-TDELTA)*100;
hum2=(float)hraw2/HFACTOR*100;

short temp12 = (short)temp1;
short hum12 = (short)hum1;
short temp22 = (short)temp2;
short hum22 = (short)hum2;



  short dataout1[12];
  short k; 
  dataout1[0] = tc1.readThermocoupleTemperature()*10;
  dataout1[1] = tc2.readThermocoupleTemperature()*10;
  dataout1[2] = tc3.readThermocoupleTemperature()*10;
  dataout1[3] = tc4.readThermocoupleTemperature()*10;
  dataout1[4] = tc5.readThermocoupleTemperature()*10;
  dataout1[5] = tc6.readThermocoupleTemperature()*10;
  dataout1[6] = tc7.readThermocoupleTemperature()*10;
  dataout1[7] = tc8.readThermocoupleTemperature()*10;
  dataout1[8] = temp12;
  dataout1[9] = hum12;
  dataout1[10] = temp22;
  dataout1[11] = hum22;
  
  radio.write(dataout1, sizeof(dataout1));
}

TX2:

#include <Wire.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define HYT939_ADDR1 0x28
#define HYT939_ADDR2 0x31

RF24 radio(6,7);
unsigned char ADDRESS1[5] = {0xb2,0x43,0x88,0x99,0x45};

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

  radio.begin();
  radio.openWritingPipe(ADDRESS1);
  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)
}

void loop() {

#define TFACTOR 99.2909       //Skalierungsfaktoren laut Datenblatt
#define TDELTA  40.0
#define HFACTOR 163.83
unsigned char buffer[4];

//Erster Feuchtesensor, Addresse 0x28
  unsigned int traw3;
  unsigned int hraw3;   
  float temp3;
  float hum3;
  int i;
  
  Wire.beginTransmission(HYT939_ADDR1);
  Wire.endTransmission();
  delay(100);   //100ms warten
  Wire.requestFrom(HYT939_ADDR1, 4,true);     //4 Bytes vom Sensor lesen
  
  i=0;
  
while(Wire.available()) {
    char c = Wire.read();
    buffer[i]=c;   
    i++;}
   
  traw3=buffer[2]*256+buffer[3];     //Rohdaten aus Puffer lesen
  hraw3=buffer[0]*256+buffer[1];
  
  traw3&=0xfffc;
  hraw3&=0x3fff;        //Daten laut Datenblatt maskieren
  traw3>>=2;
  
//Zweiter Feuchtesensor, Addresse 0x31
  unsigned int traw4;
  unsigned int hraw4;   
  float temp4;
  float hum4;
  int j;
  
  Wire.beginTransmission(HYT939_ADDR2);
  Wire.endTransmission();
  delay(100);   //100ms warten
  Wire.requestFrom(HYT939_ADDR2, 4,true);     //4 Bytes vom Sensor lesen
  
  j=0;
  
while(Wire.available()) {
    char c = Wire.read();
    buffer[j]=c;   
    j++;}
   
  traw4=buffer[2]*256+buffer[3];     //Rohdaten aus Puffer lesen
  hraw4=buffer[0]*256+buffer[1];
  
  traw4&=0xfffc;
  hraw4&=0x3fff;        //Daten laut Datenblatt maskieren
  traw4>>=2;

//Rohdaten Umrechnen

temp3=(float)traw3/TFACTOR;
temp3=(temp3-TDELTA)*100;
hum3=(float)hraw3/HFACTOR*100;

temp4=(float)traw4/TFACTOR;
temp4=(temp4-TDELTA)*100;
hum4=(float)hraw4/HFACTOR*100;

short temp32 = (short)temp3;
short hum32 = (short)hum3;
short temp42 = (short)temp4;
short hum42 = (short)hum4;


  short dataout2[4];
  short l; 
  dataout2[0] = temp32;
  dataout2[1] = hum32;
  dataout2[2] = temp42;
  dataout2[3] = hum42;
  
  radio.write(dataout2, sizeof(dataout2));
}

RX:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

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

unsigned char ADDRESS0[5] = {0xb1,0x43,0x88,0x99,0x45};
unsigned char ADDRESS1[5] = {0xb2,0x43,0x88,0x99,0x45};

int period = 2000;
unsigned long time_now = 0;

void setup() {
  
  Serial.begin(115200);
  radio.begin();
  radio.openReadingPipe(0, ADDRESS0);
  radio.openReadingPipe(1, ADDRESS1);
  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.startListening();
}


void loop() {

time_now = millis();

short got_dataout1[12];
short got_dataout2[4];

float data1[16];
float m;

if (radio.available()) { 

  radio.read(got_dataout1, sizeof(got_dataout1));    
    data1[0] = (float)got_dataout1[0]/10;
    data1[1] = (float)got_dataout1[1]/10;
    data1[2] = (float)got_dataout1[2]/10;
    data1[3] = (float)got_dataout1[3]/10;
    data1[4] = (float)got_dataout1[4]/10;
    data1[5] = (float)got_dataout1[5]/10;
    data1[6] = (float)got_dataout1[6]/10;
    data1[7] = (float)got_dataout1[7]/10;
    data1[8] = (float)got_dataout1[8]/100;
    data1[9] = (float)got_dataout1[9]/100;
    data1[10] = (float)got_dataout1[10]/100;
    data1[11] = (float)got_dataout1[11]/100;

  radio.read(got_dataout2, sizeof(got_dataout2));
    data1[12] = (float)got_dataout2[0]/100;
    data1[13] = (float)got_dataout2[1]/100;
    data1[14] = (float)got_dataout2[2]/100;
    data1[15] = (float)got_dataout2[3]/100;
  
  for (byte m = 0; m < 16; ++m ) {
  Serial.print(data1[m]);
  Serial.print("\t");}
  Serial.println("");
  while(millis() < time_now + period){}}}

Falls jemand eine Idee hätte, was ich hier falsch mache bin ich sehr dankbar.
LG Flo

Wenn die Daten durcheinander kommen, liegt es evtl. daran, das die Sender gleichzeitig senden.

Das musst du verhindern.
Ein Empfänger kann immer nur ein Signal zur Zeit empfangen.

Damit das sicher funktioniert, musst du vom Empfänger (Master) ein Signal an die einzelnen Sender (Slave) schicken, welcher jeweils seine Daten senden soll.
Da du Transceiver verwendest, sollte das mit entsprechender Programmierung auch funktionieren.

Suchtipp: "nRF24L01 mesh"

Alles klar, danke für die Hinweise.
Dann schau ich mal was ich da so finde.
LG Flo

Du solltest

byte pipe;

  if (radio.available(&pipe)) {

benutzen, damit kannst du die beiden Pakete/Quellen problemlos unterscheiden und auswerten.

Also etwa so:

#include <RF24.h>

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

unsigned char ADDRESS0[5] = {0xb1, 0x43, 0x88, 0x99, 0x45};
unsigned char ADDRESS1[5] = {0xb2, 0x43, 0x88, 0x99, 0x45};

void setup() {
  Serial.begin(115200);
  radio.begin();
  radio.openReadingPipe(0, ADDRESS0);
  radio.openReadingPipe(1, ADDRESS1);
  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.startListening();
}

void loop() {
  short got_dataout1[12];
  short got_dataout2[4];
  float data1[16];
  byte pipe;

  if (radio.available(&pipe)) {
    if (pipe == 0) {
      radio.read(got_dataout1, sizeof(got_dataout1));
      data1[0] = (float)got_dataout1[0] / 10;
      data1[1] = (float)got_dataout1[1] / 10;
      data1[2] = (float)got_dataout1[2] / 10;
      data1[3] = (float)got_dataout1[3] / 10;
      data1[4] = (float)got_dataout1[4] / 10;
      data1[5] = (float)got_dataout1[5] / 10;
      data1[6] = (float)got_dataout1[6] / 10;
      data1[7] = (float)got_dataout1[7] / 10;
      data1[8] = (float)got_dataout1[8] / 100;
      data1[9] = (float)got_dataout1[9] / 100;
      data1[10] = (float)got_dataout1[10] / 100;
      data1[11] = (float)got_dataout1[11] / 100;
      for (byte m = 0; m < 12; m++ ) {
        Serial.print(data1[m]);
        Serial.write('\t');
      }
      Serial.println();
    } else {
      radio.read(got_dataout2, sizeof(got_dataout2));
      data1[12] = (float)got_dataout2[0] / 100;
      data1[13] = (float)got_dataout2[1] / 100;
      data1[14] = (float)got_dataout2[2] / 100;
      data1[15] = (float)got_dataout2[3] / 100;
      for (byte m = 12; m < 16; ++m ) {
        Serial.print(data1[m]);
        Serial.write('\t');
      }
      Serial.println();
    }
  }
}

Der große Array ist etwas unglücklich, verarbeite die Pakete besser einzeln.

Nur zum Drucken braucht man die Floats sowieso nicht, das sollte auch so gehen:

#include <RF24.h>

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

unsigned char ADDRESS0[5] = {0xb1, 0x43, 0x88, 0x99, 0x45};
unsigned char ADDRESS1[5] = {0xb2, 0x43, 0x88, 0x99, 0x45};

void setup() {
  Serial.begin(115200);
  radio.begin();
  radio.openReadingPipe(0, ADDRESS0);
  radio.openReadingPipe(1, ADDRESS1);
  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.startListening();
}

void loop() {
  byte pipe;
  if (radio.available(&pipe)) {
    if (pipe == 0) {
      short got_dataout1[12];
      radio.read(got_dataout1, sizeof(got_dataout1));
      for (byte m = 0; m < 12; m++ ) {
        Serial.print(got_dataout1[m] / 10);
        Serial.write('.');
        Serial.print(got_dataout1[m] % 10);
        Serial.write('0');
        Serial.write('\t');
      }
    } else {
      short got_dataout2[4];
      radio.read(got_dataout2, sizeof(got_dataout2));
      for (byte m = 0; m < 4; ++m ) {
        Serial.print(got_dataout2[m] / 100);
        Serial.write('.');
        byte rest = got_dataout2[m] % 100;
        if (rest < 10) {
          Serial.write('0');
        }
        Serial.print(rest);
        Serial.write('\t');
      }
    }
    Serial.println();
  }
}

Deine Problem waren

  • zwei read für ein available
  • das Annehmen einer festen Paketreihenfolge
  • das Annehmen eines festen Timings
  • keine Auswertung der RX-Pipe

Hallo Whandall,

vielen Dank für deine Hilfe. Hab meinen Code angepasst und es hat funktioniert. :slight_smile:

Das heißt also ich könnte auf diese Weise von 6 verschiedenen Sendern die Daten empfangen wenn jeder eine eigene Adresse hinterlegt hat und ich die pipes immer seperat anspreche. Falls ich das jetzt richtig verstanden habe?

LG

Ja, das wäre eine Methode, limitiert dich aber auf 6 Knoten
und die verwendeten Adressen von Pipe 1 bis 5 dürfen sich nur im untersten Byte unterscheiden.

Ich ließe alle Knoten auf die gleiche Adresse senden.

Um die Pakete weiterhin unterscheiden zu können,
braucht man dann natürlich zusätzliche Absender/Pakettype Infos in jedem Paket

Ach ja, die Verwendung von short bringt dir einen Haufen Portabilitätsprobleme, int16_t ist besser.

Oke, alles klar.
Vielen Dank für die Infos!
LG Flo