Problem mit nRF24L01 Acknowledge

Hallo zusammen,

ich entwickle derzeitig einen kleinen Handsender und Empfänger.
Beide nutzen einen nRF24L01 als Sender/Empfänger.

Es funktioniert eigentlich auch alles einwandfrei, ich kann Daten hin und her senden.

Nun möchte ich aber, da ich mehrere Handsender + Empfänger betreibe, eine automatisch generierte Sende/Empfangsadresse einprogrammieren.
Und hier liegt irgendwie mein Problem, ich weiß einfach nicht was ich falsch mache.

Sender sendet beim Start auf einer festen Sendeadresse und sendet die Zahl 50 an den Empfänger.
Empfänger hört während dieses “Pairvorgangs” auf der festen Adresse und empfängt die Daten.
Sobald die Daten angekommen sind und die Daten der Zahl 50 entsprechen,
generiert der Empfänger per RandomSeed eine Zufallszahl (16-Bit).
Diese Sendet er per Acknowledge an den Sender zurück.
Nun packt sich der Empfänger die 16-Bit Zufallszahl in 2x 8-Bit Zahlen und speichert diese in einem Array.
Das Array ist dann die Zufallsadresse.
Der Sender empfängt das Acknowledge (gleiche Zufallszahl wie der Empfänger hat) und packt sich diese ebenfalls in ein Array für die Zufallsadresse.

Nun startet der Empfänger auf der Zufallsadresse zu hören und der Sender auf der Adresse zu senden.

Doch leider bekomme ich nichts passendes im Serial Monitor angezeigt.
Könnte von euch mal jemand über den Code schauen, und mir sagen, was ich da falsch mache?

Sender:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <EEPROM.h>
RF24 radio(18,17); // CE, CSN

const byte address[6] = "00001";  //Feste Adresse für einen anderen Slave
const byte plugfixaddress[6]={'255','255','201','0','15'}; //Feste Adresse für Kommunikation
byte plugpairaddress[6] =	 {'0','0','201','0','15'};          //Adresse, in der Array 0 und 1 geändert werden (Zufallsadresse)
const int M1_UP = 1;          //Taster an I/O 1
unsigned char data=0;        //Variable für data, Daten welche gesendet werden
unsigned int randnumberplug=0; //Zufallszahl welche per Acknowledge vom Slave zu Master gesendet wird
boolean plugteachflag=false; //bool für Pairflag

void setup()
{
        pinMode(M1_UP, INPUT);      //PD1 -> Input 1 -> Drives Motor 1 upwards
        digitalWrite(M1_UP, HIGH);  //Internal PullUp activated.
        radio.begin();
	radio.openWritingPipe(address); //Starte auf Adresse 00001 zu senden für anderen Slave
	radio.setDataRate( RF24_250KBPS ); //250KBPS übertragungsrate
	radio.setPALevel(RF24_PA_MAX);    
	radio.setRetries(15,15);
	radio.setChannel(108);   //Kanal 108
	radio.enableAckPayload(); //Acknowledge aktivieren
	radio.stopListening();  
}

void loop()
{
        plugteach(); //Führe die Funktion plugteach aus.
        if(plugteachflag==true) //nach dem teachen (Pairen) ist das flag true, also wird diese Schleife ausgeführt.
	{
                if(digitalRead(M1_UP)==LOW)  //Falls der Taster M1_UP low ist
		{
			data=1;
			radio.write(&data, sizeof(data)); //Sende die Zahl 1
		}
         }


}
void plugteach(void)      //Führt den Pairingmodus aus, direkt wenn der Handsender eingeschaltet wird
{
	if(plugteachflag==false) //Da das Flag false ist, wird diese Schleife ausgeführt
	{
		radio.openWritingPipe(plugfixaddress);  //Starte auf Kanal plugfixaddress zu senden (Feste Adresse)
		boolean tx_sent;
		data = 50;
		tx_sent = radio.write(&data, sizeof(data));
		if(tx_sent)          //Falls die Daten "50" erfolgreich an die feste Adresse gesendet wurden
		{
			if(radio.isAckPayloadAvailable())  //Falls ein Acknowledge verfügbar ist
			{
				radio.read(&randnumberplug, sizeof(randnumberplug)); //Lese die generierten Zufallszahlen vom Empfänger
				plugpairaddress[0]= highByte(randnumberplug); //Speichere das Highbyte der 16-Bit Zahl in Array platz 0 
				plugpairaddress[1]= lowByte(randnumberplug);  //Speichere das Lowbyte der 16-Bit Zahl in Array platz 1
				radio.openWritingPipe(plugpairaddress); //Fange an auf der neuen Zufallsadresse zu senden
				plugteachflag=true;  //Setze das Flag auf true damit wir wissen, dass der Pairingmode abgeschlossen ist. 
			}
	        }
		else
		{
			plugpairaddress[0]=EEPROM.read(randnumberplugaddress1);
			plugpairaddress[1]=EEPROM.read(randnumberplugaddress2); 
			radio.openWritingPipe(plugpairaddress);
			//digitalWrite(SyncLED, HIGH);
			plugteachflag=true;
		}
	}
}

Empfänger:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <EEPROM.h>
unsigned char data;
RF24 radio(7, 8); // CE, CSN
const byte address[6] = {'255','255','201','0','15'};  //Feste Adresse zum hören, ob Daten = 50 sind bevor Zufallszahl generiert wird.
byte pairaddress[6] = {'0','0','201','0','15'};   //Array für Zufallsadresse (Array platz 0 und 1 werden geändert)
unsigned char teach_abgeschlossen=0; //Flag um zu wissen, ob Pairmodus abgeschlossen ist. 
unsigned int randNumber=0; //Zahl für 16-Bit Zufallszahl
const int RELAY = 2; //Pin um Relays zu schalten
void setup() {
    Serial.begin(9600);
    radio.begin();
    radio.openReadingPipe(0, address);  //Höre auf Fester Adresse, damit die Zahl 50 empfangen werden kann
    radio.setPALevel(RF24_PA_MAX);
    radio.setChannel(108);
    radio.setDataRate( RF24_250KBPS );
    radio.enableAckPayload();
    radio.startListening();
   
}
void loop() {
  Teach(); //führe als aller erstes den Pairmodus Teach aus. 
  if(teach_abgeschlossen==1)  //Falls Pairmodus abbgeschlossen ist:
  {
    if (radio.available()) {    //Falls Daten anliegen
    radio.read(&data, sizeof(data)); //lese die Daten
    Serial.println(data); //und schreibe sie in den Seriellen Monitor.
    }
  }
}

void Teach(void) //Funktion zum Pairen
{
  if(teach_abgeschlossen==0) //Da das Flag noch 0 ist, wird die Schleife ausgeführt
  {
     if(radio.available())  //Falls Daten anliegen
     {
      radio.read(&data, sizeof(data));  //lese die Daten
      if(data==50)   //Entsprechen die Daten der 50? 
      {
        randomSeed(analogRead(0));   //offener A0 Pin als Seed für Zufallszahl
        randNumber = random(65535);//Zufallszahl 16-Bit generieren
        radio.writeAckPayload(1, &randNumber, sizeof(randNumber)); //Zufallszahl vorladen in Acknowledge
        pairaddress[0]=highByte(randNumber);   //Setze das Highbyte der Zufallszahl in Array platz 0
        pairaddress[1]=lowByte(randNumber);    //Sete das Lowbyte der Zufallszahl in Array platz 1
        radio.stopListening();  //Höre auf, auf alte Adresse zu hören
        radio.openReadingPipe(0, pairaddress); // Öffne den Lesekanal der Zufallsadresse
        radio.startListening();     //Starte zu hören
        Serial.println("Teach Abgeschlossen");  //Schreibe in den Seriellen Monitor "Teach Abgeschlossen"
        teach_abgeschlossen=1;  //Setze Flag auf 1, damit in der Loop die andere Schleife ausgeführt wird. 
      }
    }
  }
}

Das Einzige was passiert ist, dass der Empfänger Seriell schreibt, “Teach Abgeschlossen”,
das heißt er empfängt schon einmal Daten, diese jedoch auf der Fixen Adresse,
ich bekomme es nicht hin, dass Empfänger + Sender auf der gleichen Zufallszahl Hört/Sendet.

Jemand eine Idee, was ich falsch gemacht habe, oder Vorschläge?

Okay,

habe nun wohl schon einmal heraus gefunden, dass ich schon bevor der Slave das erste mal die Daten empfängt die Zufallszahl ins Acknowledgment laden muss. Also mach ich das nun einmal, sobald ich den Slave gestartet habe.

Wenn nun die Zahl 50 empfangen wird, wird ja automatisch als Acknowledge die Zufallszahl gesendet. Der Master fragt mit if(radio.isAckPayloadAvailable()) { }

ob das Acknowledge zurück kommt. Doch ich bekomme kein Acknowledge zurück, der Master kommt nicht in diese if schleife hinein (signalisiere ich mir per LED)

Irgendwo muss ich hier einen Fehler haben, weiß jedoch nicht wo..

Manchmal sieht man den Fehler vor lauter einzer und nullen nicht mehr.

radio.openReadingPipe(0, <— das war bei mir überall der Fehler.
Acknowledge hat auf Pipe 1 senden wollen, die Adressen waren aber auf Pipe 0 gestellt.

Alle Pipes auf 1 gestellt, alles funktioniert.
Nun kann ich z.B. 100 Handsender nehmen, 100 Empfänger,
und diese alle explizit mit einander kommunizieren lassen, sobald ich ihre Adresse per Software aufeinander eingestellt habe.

Handsender5 möchte mit Empfänger 1 reden → Empfänger geht durch tastendruck in Pairmodus.
Handsender5 startet senden der Daten 50 auf fester Adresse
Empfänger 1 schickt per Acknowledge eine Randomzahl und Handsender5+Empfänger1 sind aufeinander abgestimmt.

Somit habe ich nicht überall eine hardcodierte Adresse und mache alles per software :slight_smile:

Solange du nur einen nicht-gepairten Knoten hast, wird das funktionieren.

Ansonsten verstößt du gegen die Regel, dass pro Adresse maximal ein Knoten ein Ack senden darf, völlig unabhängig davon, ob du Ack Payloads benutzt, oder nicht.

Das kannst du eigentlich nur garantieren, wenn auf deiner Konfigurationsadresse kein Knoten Acks benutzt.

Warum willst du überhaupt die Slaves die Zufallszahl erzeugen lassen? Wie verhinderst du das mehrere Slaves die gleiche benutzen wollen?

Naja, es war jetzt nur grob gesagt mit 100 geräten.

Geht halt darum, dass jedes Gerät nur einen Handsender hat, aber ich durch neues Pairen auch einen neuen Handsender benutzen kann, welcher einfach nur gepaired wird. Dies ermöglicht mir jetzt die obige Funktion.

100% sicher ist es natürlich nie, dass es nicht doch mal die selbe Adresse wird, aber bei einer Random Zahl vom Rauschen des Analog 0 Pins gereriere ich mir ja eine 16Bit variable, hier gibt es schon die möglichkeiten dass sehr unterschiedliche Zahlen heraus kommen. Für mich völlig ausreichen und funktionabel.

Wenn es dir reicht.

Nach Murphy werden alle Fälle die schiefgehen können, sicher schiefgehen.