NRF24L01+ AckPayload Erste Nachricht

Moin,

Was muss ich in meinen Code noch einbauen, das ich die erste AckPayload Nachricht erhalte? Mit meinem jetzigen Code, geht immer die erste AckPayload verloren :frowning:

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

RF24 radio(7,8);

byte addresses[][6] = {"1Node","2Node"}; 
int counter = 1; 

void setup(){

  Serial.begin(115200);

  radio.begin();

  radio.enableAckPayload();                     // Allow optional ack payloads
  radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
  
   radio.openWritingPipe(addresses[0]);
   radio.openReadingPipe(1,addresses[1]);

  radio.startListening();                       // Start listening  

}

void loop(void) {
  
/****************** Ping Out Role ***************************/

    char a1[] = "hello ";
    char a2[18];
    
    radio.stopListening();  
    
    a1[6] = (counter+'0');
    a1[7] = '\0';
                                                            
    if ( radio.write(&a1, 8 )){                         // Send the counter variable to the other radio 
      Serial.print("Sent: ");
      Serial.print(a1);
      if(!radio.available()){                             // If nothing in the buffer, we got an ack but it is blank
          Serial.println("no radio is available");
        }
        else{      
            while(radio.available() ){                      // If an ack with payload was received
                radio.read( &a2, 18 );                  // Read it, and display the response time
                Serial.print("    Got: ");
                Serial.println(a2);
                }
        }
    if (counter <9 ) counter++;
    else (counter  = 0);
    }
    
    else    {        
      Serial.println(F("Sending failed.")); 
      }          // If no ack response, sending failed
    
    delay(1000);  // Try again later

}
#include <SPI.h>
#include "RF24.h"

RF24 radio(7,8);

byte addresses[][6] = {"1Node","2Node"};              // Radio pipe addresses for the 2 nodes to communicate.

void setup(){

  Serial.begin(115200);

  radio.begin();

  radio.enableAckPayload();                     // Allow optional ack payloads
  radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads

    radio.openWritingPipe(addresses[1]);        // Both radios listen on the same pipes by default, but opposite addresses
    radio.openReadingPipe(1,addresses[0]);      // Open a reading pipe on address 0, pipe 1

  radio.startListening();                       // Start listening  
  
  radio.writeAckPayload(1,1,1);          // Pre-load an ack-paylod into the FIFO buffer for pipe 1

}

void loop(void) {

/****************** Pong Back Role ***************************/
    byte pipeNo;                          // Declare variables for the pipe and the byte received
    char a1[8];
 
    while( radio.available(&pipeNo)){              // Read all available payloads

      radio.read( &a1, 8 );                   

      Serial.print("Got: ");
      Serial.print(a1);
      Serial.print("   Sent: ");
      Serial.println(a1);
      
      radio.writeAckPayload(pipeNo,&a1, 8 );  // This can be commented out to send empty payloads.

   }
}

was ich so bekomme:

Sent: hello 1`    Got: 
Sent: hello 2`    Got: hello 1
Sent: hello 3`    Got: hello 2

Wie kriege ich beim Sender, das erste Payload?

Das eine Byte an der Adresse 1 könnte einfach eine Null sein, oder etwas das nicht printable ist.

Benutz doch das gleiche Statement fĂŒr das Preload wie fĂŒr das Reload.

      radio.writeAckPayload(pipeNo,&a1, 8 ); payloads.

a1 sollte dann aber global sein und einen Inhalt wie "hello 0" haben.

Schon klar, aber das behebt ja nicht mein Problem, das mein Sender das erste Payload nicht empfÀngt, sondern immer um 1 Payload hinterher hÀngt...

Dir ist schon klar, dass das genau so sein muss?
Vorher mit einem Paket laden, beim nÀchsten Empfang wird diese Nachricht gesendet,
nicht die, die danach wieder vorgeladen wird.

Das ist mir klar, aber es Àndert schlicht nichts, das ich am Sender die erste Payload NICHT empfange, auch wenn ich beim Receiver:

radio.enableAckPayload();                     // Allow optional ack payloads
  radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads

    radio.openWritingPipe(addresses[1]);        // Both radios listen on the same pipes by default, but opposite addresses
radio.openReadingPipe(1,addresses[0]);      // Open a reading pipe on address 0, pipe 1

radio.startListening(); 
radio.writeAckPayload(1,"hello 0", 8 ); payloads.

Wenn du es sagst, es ist zumindest ungewöhnlich,
ich habe schon das erste in setup geladene Paket als Ack-Payload erhalten.

Du könntest das preload vor das startListening verschieben.

Ansonsten, wenn das bei dir so ist, wo ist das Problem?
Schick am Sender das erste Paket zweimal, das erste hat halt dann kein Ack-payload.

Hm... vielleicht bin ich auch einfach zu doof, oder denke zu kompliziert...?

Leider kein erfolg, der Sender blieb immer 1 Paket dahinter....

Das Problem ist, ich schicke den Befehl "BATTERY" an eine Adresse, diese gibt mir per "ACK" dann die Batterie-Spannung zurĂŒck, schicke danach den Befehl "LUX" dann erhalte ich per ACK die LUX als Analogwert zurĂŒck.

Aktuell ist es so, ich sende Battery kriege nichts, sende dann LUX und kriege dafĂŒr die Batteriespannung zurĂŒck, beim nĂ€chsten "Battery" Befehl, dann die LUX Zahl.... So wiederholt sich das fĂŒr alle Anfragen (Bleibt Asynchron 1 Paket dahinter)

Klar könnte ich erstmal ein Fake Paket los schicken, bis das "lÀuft" aber ist ja eigentlich nicht sinn und zweck der Sache.

Beim Sender muss ich aber nicht ein writeAckPayload losschicken?

Das funktioniert nicht so wie du glaubst.
Du bekommst keine Antwort per Ack, die Info im Ack muss Àlter als die Nachricht sein.

Schick einfach Batteriewert und Lux als ein Ack-Payload.

Da hast du wohl leider Recht, ich dachte das es dennoch funktioniert?
Dachte eigentlich das dass Funktionieren sollte, wozu gibts denn die Funktion dann um eine Payload zurĂŒck zugeben, wenn diese nicht Synchron ist?

Das sind ja leider nicht die einzigen Infos die ich schicke, die Payload LÀnge ist ja ohne Mesh auf 32 Begrenzt. Soviel Informationen kriege ich leider nicht in eine einzelne Payload, deshalb hÀnge ich genau an diesem Problem fest :frowning:

Nö, du hÀngst nur in deiner Denke fest.

Sende jeden Request direkt aufeinanderfolgend zweimal,
und betrachte nur den Ack-Payload des zweiten (das ist deine "Antwort" auf den ersten).
Dazu musst du nur entsprechend schnell preloaden.

Alternativ könntest du erst nach der Analyse des empfangenen Pakets etwas preloaden,
das dann mit dem zweiten Request abgegriffen wird.
(Hier sehe ich eine weitere Möglichkeit einfach viele Daten zu ĂŒbertragen,
indem man in der Frage spezifiziert, welchen Teil der Daten man möchte.)
Ack-Payload ist keine Pflicht, nur eine Möglichkeit.

Dein Beispiel ist nicht tauglich zu sehen, was du wirklich wo machst,
also kannst du nur generelle Tipps bekommen.

Haben deine Knoten wirklich mehr als 32 Byte Daten zu berichten?
Erscheint mir sehr viel, ich bin bisher selten an diese Grenze gestoßen.

Aber wenn du mehr Daten zu berichten hast, kannst du ja zusÀtzliche Requests benutzen,
zwei benutzt du ja eh schon, um top-aktuell zu sein (bzw. um eine "Antwort" zu bekommen).

Die physikalische Payload LĂ€nge ist immer auf 32 Bytes begrenzt,
Mesh ist 'lediglich' ein Protokoll das multi-Packet Nachrichten unterstĂŒtzt,
was natĂŒrlich die nutzbare PaketgrĂ¶ĂŸe weiter verkleinert.

request1 -> Keine Antwort
request2 < ack auf 1
request3 -> Kommt jetzt keine Antwort oder ack auf 2?
request4 < ack auf 3?

Ich find mich da nicht wirklich rein, halte das Verfahren aber fĂŒr völlig kontraproduktiv.
Ich hab ja mit denen nu ne Menge gemacht :wink: aber irgendwie will mir nicht in den Sinn, warum ich zwei Payloads schicken muss um ein payload.ACK zu bekommen.

Dann stimmt IMHO etwas an dem Konzept nicht.
Kannst Du mir das bitte auflösen?

Es sind einfach zwei unabhÀngige Streams von Paketen.
Nur das Ack gehört zum aktuellen Paket,
die Daten mussten aber vor Empfang des Pakets generiert und ĂŒbertragen werden.

Du kannst keine Antwort erwarten, die vorliegen muss, ehe die Frage gestellt wird.
Die Kommunikation soll so schnell als möglich erfolgen,
da bleibt keine Zeit vor einem Ack den Prozessor zu bemĂŒhen.
Insofern ist deine Anwendung nicht wirklich darauf abgestimmt,
kann aber ĂŒber einen zweiten Request erfĂŒllt werden.

Willst du lieber jedes Mal den Mode beider Stationen Àndern,
um die Antwort zu ĂŒbertragen?
Das dauert lÀnger als ein zweiter Request.

Es funktioniert halt nicht so wie du (und viele andere) sich das vorstellen,
bevor sie sich wirklich damit auseinandersetzen.
Ist ein prima RĂŒckkanal, aber halt ein Paket versetzt, was in der Natur der Sache liegt.

Aber es ist wie mit der maximalen PaketlÀnge,
mehr wÀre schöner, aber man kann und muss damit leben.

request 1 -> Keine Antwort
request 2 -> Antwort auf Request 1
request 3 -> Antwort auf Request 2
request 4 -> Antwort auf Request 3
request 5 -> Antwort auf Request 4

u.s.w

Ich halte das ACK Verfahren auch fĂŒr kontraproduktiv wenn das wirklich so funktionieren soll.
Doch leider kann ich im Netz nichts finden, das es genau SO sein SOLL, wie ich es habe.

Okay, wie wĂŒrde denn deine Empfohlene Methode sein wenn ich folgendes machen möchte:

Abfrage erfolgt alle 15 Sekunden...

(Master wechselt in Sendemodus)
Master sendet Request an Node 1

(Master wechselt von Sende und Empfangsmodus)
Master wartet auf Node 1 seine Antwort.

(Master wechselt in Sendemodus)
Master Sendet Request an Node 1

(Master wechselt in Empfangsmodus)
Master wartet auf Node 1 seine Antwort.

Es kann ja nicht Sache des Erfinders gewesen sein, das die NRF24 Module als "only Sender" und "only Receiver" gedacht sind? oder irre ich mich?

Nein. :wink:

Und genau hier wĂŒrde ich eingreifen:
Abfrage erfolgt alle 15 Sekunden...
Antwortzeit auf xxx(!?)ms begrenzt.

(Master wechselt in Sendemodus)
Master sendet Request an Node 1

(Master wechselt von Sende in Empfangsmodus)
Master wartet auf Node 1 seine Antwort oder ob die Anwortzeit abgelaufen ist.

Die Antwort besteht aus tatsÀchlichen zwei Teilen.
Im ersten Teil wird bestĂ€tigt, das Anfrage empfangen und auf diese reagiert wird; aufgefĂŒllt mit einer ID

Die zweite enthÀlt die ID und die Antwort, was abgefragt wurde.

Wird Antwort Teil1 empfangen und Teil2 nicht, geht das im nÀchsten Umlauf wieder von vorn los.

Das könnte Deine Lösung sein. Dann bist Du mit dem ACK bei und sendest die ID, die schon vorher angelegt wurde.
Und im nÀchsten Durchgang die ID mit payload.

Bekommst Du kein ACK.ID, gehst Du gleich weiter und fragst den nÀchsten Node ab ohne auf den Abbruch durch TiemOut zu warten...

1 Like

Da sehe ich keine Anwendung fĂŒr Ack-Payload.
Mach doch einfach was du da beschreibst, ohne den "Warten" Teil.

Ich wĂŒrde alle 15 Sekunden eine Abfrage machen und nur dafĂŒr in den Sendemodus gehen.
Nicht auf irgendetwas warten, sondern einfach Nachrichten der anderen verarbeiten,
auch, wenn ich diese vorher mit einer Nachricht auslöse.

Wenn viele Daten ĂŒbertragen werden sollen ist ein hĂ€ufiger Modewechsel ungĂŒnstig.

1 Like

woki toki oder walkie-talkie so is es
:wink:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.