nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.22k stars 1.02k forks source link

[Question] ACK and NONACK payload send/receive using NRF24 #721

Closed Ganesh-Shanbhag closed 3 years ago

Ganesh-Shanbhag commented 3 years ago

My requirements are using an address for broadcasting message to all the devices present which should not send an ACK after reception all the device will listen to this address on pipe 2. And every device will listen to its own address on pipe 0 which must send an ACK after successful reception.

So I disabled ACK on pipe 2 by using setAutoAck(2, false) but when I broadcasted data then none of the devices received the message although they are listening on the broadcast address. But when sent from one device to other with recipient's address it was sent successfully.

So how to perform a NONACK write on broadcast address such that all can receive the message?

TMRh20 commented 3 years ago

You may have to set setAutoAck(0,false) before sending because the writing pipe (pipe0) needs AA disabled when broadcasting. Call setAutoAck(0,true) before sending normal payloads. You could also try using dynamic acks as well.

On Jan 25, 2021, at 7:40 AM, Ganesh-Shanbhag notifications@github.com wrote:

 My requirements are using an address for broadcasting message to all the devices present which should not send an ACK after reception all the device will listen to this address on pipe 2. And every device will listen to its own address on pipe 0 which must send an ACK after successful reception.

So I disabled ACK on pipe 2 by using setAutoAck(2, false) but when I broadcasted data then none of the devices received the message although they are listening on the broadcast address. But when sent from one device to other with recipient's address it was sent successfully.

So how to perform a NONACK write on broadcast address such that all can receive the message?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

Ganesh-Shanbhag commented 3 years ago

Hi I followed you but still I am not able to broadcast. If I did any mistakes in the code let me know I am sharing my code here. I took 3 nodes but for simplicity I initially took only two nodes to try. I am using Arduino Nano in all the devices.

/********** Node 2 code **********/
#include <RF24.h>

RF24 node(7, 8); // CE, CSN

byte netAddr[] = {0x31, 0x30, 0x30};  // Broadcast address
byte nodeAddr[] = {0x32, 0x30, 0x30}; // Node 2 address

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

  node.begin();
  node.setPALevel(RF24_PA_MIN);
  node.setDataRate(RF24_250KBPS);
  node.setAddressWidth(3);
  node.setChannel(3);

  // Address to read broadcast messages (NOACK messages)
  node.openReadingPipe(2, netAddr);
  node.setAutoAck(2, false);

  // Address to read ACK messages
  node.openReadingPipe(0, nodeAddr);

  ////////////////////////////////////////////////////////////////////////////////////////////////
  Serial.print("Network Address: "); Serial.write(netAddr, sizeof(netAddr)); Serial.println();
  Serial.print("Channel        : "); Serial.println(node.getChannel());
  Serial.print("Node Address   : "); Serial.write(nodeAddr, sizeof(nodeAddr)); Serial.println();
  ////////////////////////////////////////////////////////////////////////////////////////////////
}

void loop() {

  if (Serial.available()) {
    char buf[32] = "";
    String str = Serial.readString();

    // Write ACK message to node 3
    if (str == "n3") {
      strcpy(buf, "Hi I am node 2");

      // Write to other node address
      byte addr[3] = {0x33, 0x30, 0x30};
      node.setAutoAck(0, true);
      node.openWritingPipe(addr);

      Serial.println("Writing to node 3");
    }
    // Write NOACK message
    else if (str == "br") {
      strcpy(buf, "Node 2 broadcasted a message");

      // Write to other node address
      node.setAutoAck(0, false);
      node.openWritingPipe(netAddr);

      Serial.println("Broadcasting");
    }

    node.stopListening();
    if (node.write(&buf, sizeof(buf)))
      Serial.println("Success");
    else
      Serial.println("Failed");
  }

  node.startListening();

  if (node.available()) {
    char buf[32] = "";
    node.read(&buf, sizeof(buf));
    Serial.println(buf);
  }
}
/********** Node 3 code **********/
#include <RF24.h>

RF24 node(7, 8); // CE, CSN

byte netAddr[] = {0x31, 0x30, 0x30}; // Broadcast Address
byte nodeAddr[] = {0x33, 0x30, 0x30}; // Node 3 Address

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

  node.begin();
  node.setPALevel(RF24_PA_MIN);
  node.setDataRate(RF24_250KBPS);
  node.setAddressWidth(3);
  node.setChannel(3);

  // Address to read broadcast messages (NOACK messages)
  node.openReadingPipe(2, netAddr);
  node.setAutoAck(2, false);

  // Address to read ACK messages
  node.openReadingPipe(0, nodeAddr);

  ////////////////////////////////////////////////////////////////////////////////////////////////
  Serial.print("Network Address: "); Serial.write(netAddr, sizeof(netAddr)); Serial.println();
  Serial.print("Channel        : "); Serial.println(node.getChannel());
  Serial.print("Node Address   : "); Serial.write(nodeAddr, sizeof(nodeAddr)); Serial.println();
  ////////////////////////////////////////////////////////////////////////////////////////////////
}

void loop() {

  if (Serial.available()) {
    char buf[32] = "";
    String str = Serial.readString();

    // Write ACK message to node 2
    if (str == "n2") {
      strcpy(buf, "Hi I am node 3");

      byte addr[3] = {0x32, 0x30, 0x30};
      // Write to other node address
      node.setAutoAck(0, true);
      node.openWritingPipe(addr);

      Serial.println("Writing to node 2");
    }
    // Write NOACK message
    else if (str == "br") {
      strcpy(buf, "Node 3 broadcasted a message");

      // Write to other node address
      node.setAutoAck(0, false);
      node.openWritingPipe(netAddr);

      Serial.println("Broadcasting");
    }

    node.stopListening();
    if (node.write(&buf, sizeof(buf)))
      Serial.println("Success");
    else
      Serial.println("Failed");
  }

  node.startListening();

  if (node.available()) {
    char buf[32] = "";
    node.read(&buf, sizeof(buf));
    Serial.println(buf);
  }
}
2bndy5 commented 3 years ago

If you can send data using auto-ack, then you're probably not using a clone/counterfeit radio. I would have tried the enableDynamicAck() in setup() and simply use the multicast set to true in calls to write() when no ACK is desired.

If transmissions with auto-ack are not getting received, then you may have a different problem.

Also, docs recommend using pipe 1 to receive and leaving pipe 0 to only transmit. Remember that pipes 2-5 use the first 4 LSBytes from pipe 1's address and only allows setting the MSByte of an address to any pipe greater than 1.

Ganesh-Shanbhag commented 3 years ago

Also, docs recommend using pipe 1 to receive and leaving pipe 0 to only transmit. Remember that pipes 2-5 use the first 4 LSBytes from pipe 1's address and only allows setting the MSByte of an address to any pipe greater than 1.

@2bndy5 As per my knowledge pipe 1-5 uses the first 4 MSBytes (Byte 4 to 1) from pipe 1 with LSByte (Byte 0) always unique and must be greater than 1. Correct me if I am wrong.

2bndy5 commented 3 years ago

I get my endianess backwards all the time. I would consult the datasheet for correctness. I think the docs have this mentioned with example code snippet.

The fact is that your code never sets an address to pipe 1. If your program is running after a power-on-reset (unplug and replug the USB cable), then the address used on pipe 2 is probably 0xc2c231. Use printDetails() to verify the addresses on the pipes.

Ganesh-Shanbhag commented 3 years ago

@TMRh20 and @2bndy5 Thanks for your suggestions and input now it is working as per my expectation.

I am sharing my code here. For any further doubts/questions I will reach you guys

/************* Node 2 code ****************/
#include <RF24.h>

RF24 node(7, 8); // CE, CSN

byte netAddr[] = {0x31, 0x30, 0x30};  // Broadcast Address
byte nodeAddr[] = {0x32, 0x30, 0x30}; // Node 2 Address

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

  node.begin();
  node.setPALevel(RF24_PA_MIN);
  node.setDataRate(RF24_250KBPS);
  node.setAddressWidth(3);
  node.setChannel(3);

  // Listen to broadcast Address
  node.openReadingPipe(2, netAddr);
  // Disable ACK on broadcast address
  node.setAutoAck(2, false);
  // Listen to its own address
  node.openReadingPipe(1, nodeAddr);

  ////////////////////////////////////////////////////////////////////////////////////////////////
  Serial.print("Network Address: "); Serial.write(netAddr, sizeof(netAddr)); Serial.println();
  Serial.print("Channel        : "); Serial.println(node.getChannel());
  Serial.print("Node Address   : "); Serial.write(nodeAddr, sizeof(nodeAddr)); Serial.println();
  ////////////////////////////////////////////////////////////////////////////////////////////////
}

void loop() {

  if (Serial.available()) {
    char buf[32] = "";
    String str = Serial.readString();

    if (str == "n3") {
      byte addr[3] = {0x33, 0x30, 0x30};
      // Enable ACK on pipe 0
      node.setAutoAck(0, true);
      // Write to other node address
      node.openWritingPipe(addr);

      Serial.println("Writing to node 3");
    }
    else if (str == "br") {
      // Disable ACK on pipe 0 for broadcast
      node.setAutoAck(0, false);
      // Write to broadcast address
      node.openWritingPipe(netAddr);

      Serial.println("Broadcasting");
    }

    if (str == "n3")
      strcpy(buf, "Hi I am node 2");
    else if (str == "br")
      strcpy(buf, "Node 2 broadcasted a message");

    node.stopListening();
    if (node.write(&buf, sizeof(buf)))
      Serial.println("Success");
    else
      Serial.println("Failed");
  }

  node.startListening();
  if (node.available()) {
    char buf[32] = "";
    node.read(&buf, sizeof(buf));
    Serial.println(buf);
  }
}
/************* Node 3 code ****************/
#include <RF24.h>

RF24 node(7, 8); // CE, CSN

byte netAddr[] = {0x31, 0x30, 0x30};  // Broadcast address
byte nodeAddr[] = {0x33, 0x30, 0x30}; // Node 3 address

void setup() {
  delay(500);
  Serial.begin(9600);

  node.begin();
  node.setPALevel(RF24_PA_MIN);
  node.setDataRate(RF24_250KBPS);
  node.setAddressWidth(3);
  node.setChannel(3);

  // Listen to broadcast Address
  node.openReadingPipe(2, netAddr);
  // Disable ACK on broadcast address
  node.setAutoAck(2, false);
  // Listen to its own address
  node.openReadingPipe(1, nodeAddr);

  ////////////////////////////////////////////////////////////////////////////////////////////////
  Serial.print("Network Address: "); Serial.write(netAddr, sizeof(netAddr)); Serial.println();
  Serial.print("Channel        : "); Serial.println(node.getChannel());
  Serial.print("Node Address   : "); Serial.write(nodeAddr, sizeof(nodeAddr)); Serial.println();
  ////////////////////////////////////////////////////////////////////////////////////////////////
}

void loop() {

  if (Serial.available()) {
    char buf[32] = "";
    String str = Serial.readString();

    if (str == "n2") {
      byte addr[3] = {0x32, 0x30, 0x30};
      // Enable ACK on pipe 0
      node.setAutoAck(0, true);
      // Write to other node address
      node.openWritingPipe(addr);

      Serial.println("Writing to node 2");
    }
    else if (str == "br") {
      // Disable ACK on pipe 0 for broadcast
      node.setAutoAck(0, false);
      // Write to broadcast address
      node.openWritingPipe(netAddr);

      Serial.println("Broadcasting");
    }

    if (str == "n2")
      strcpy(buf, "Hi I am node 3");
    else if (str == "br")
      strcpy(buf, "Node 3 broadcasted a message");

    node.stopListening();
    if (node.write(&buf, sizeof(buf)))
      Serial.println("Success");
    else
      Serial.println("Failed");
  }

  node.startListening();
  if (node.available()) {
    char buf[32] = "";
    node.read(&buf, sizeof(buf));
    Serial.println(buf);
  }
}