[SOLVED] changing addresses with nRF24LO1+

Hi all,

I am trying to change the address that the Arduino is using to receive from a different node. I am using the nRF24L01+ module. I am posting the important snippets of the code:

byte slaveAddress[5] = {'2','1','1','1','1'};

Here I am just stating the address.

It all works, I can send and receive with this address. It prints 49 (as far as I understand correctly the ASCII representation of ‘1’) and then 50 and so on… So then I use this part of my code to just add ‘1’ to the second char and then I print the whole thing. However, when I get to more than 88 the whole software breaks. What is the reason for that?

void changeAddress() {
Serial.println("changeAddress");
  slaveAddressCount += 1;
  Serial.println(slaveAddressCount);
  slaveAddress[c] = slaveAddressCount;
  for (int i = 0; i < 5; i++) {
    Serial.println(slaveAddress[i]);
    }

I am very happy about any advice.

Thank you very much.

Snippets aren't useful. Post your full code or an MCVE that demonstrates the problem -- which ever is shorter.

Have a look at this Simple nRF24L01+ Tutorial.

You may find the addressing system easier to use.

...R

Thank you for your answers. I am very aware of Robin2 tutorial and it is great. However, I am supposed to do it like this.
These code snippets are the only important parts concerning the address change. I can post the full code, but it is probably a waste of time.

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

#define CE_PIN   9
#define CSN_PIN 10

byte thisSlaveAddress[5] = {'1','1','1','1','1'};
byte slaveAddress[5] = {'2','1','1','1','1'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[2]; // this must match dataToSend in the TX
char dataReceivedAtInit[1];
char allData[20];
char slaveAddressCount ='1';
char dataToSend;  // Array an charactern, um die Daten zu übersenden

int allDataAddAt = -1;
int i = 0;
int c = 1;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 2;

bool didSend = false;
bool newData = false;
bool readyForData = false;
bool switchAddress = false;
bool passDataOn = false;

//===========

void setup() {

    Serial.begin(9600);
    Serial.println("SimpleRx Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    for (int i = -1; i < 5; i++) {
    Serial.println(thisSlaveAddress[i]);
    }
}

//=============

void loop() {
    //Serial.println("starting loop");
    if (readyForData == false) {
      Serial.println("ready for Data");
      startQuestioning();
    }
    if (readyForData == true) {
      if (didSend == false) {
      dataToSend ='t';
      askData();
      }
      
      if (didSend == true) {
        //Serial.println("didSend is true");
        getData();
        }
        if (newData == true) {
          Serial.println("new data is true");
          processData();
        }
      currentMillis = millis();
    }
}

//==============

void getData() {
 //Serial.println("starting getData");
    radio.openReadingPipe(1, thisSlaveAddress);
    radio.startListening();
    if (radio.available()) {
      Serial.println("getanything");
        radio.read(&dataReceived, sizeof(dataReceived));
        Serial.println("dataInit is false");      
      newData = true;
      Serial.println("new data set true");
    }
}

//==============

void processData() {
        //Serial.println("starting processData");
        Serial.print("Data received: ");
          if (dataReceived[0] == 's') {
            switchAddress = true;
            //Serial.print(dataReceived[0]);
            Serial.println(dataReceived[1]);
            Serial.println("switchAddress is true");
           }
           else {
            readyForData = false;
            Serial.println("switchAddress NOT true");
          }
        newData = false;
        if (switchAddress == true) {
         int allDataAt = slaveAddressCount-49;
         allData[allDataAt] = dataReceived[0];
         Serial.println(allData[0]);
         Serial.println(allData[allDataAt]);
         changeAddress();
        }
}

//==============

void askData() {
  //Serial.println("starting askData with Address: ");
  for (int i = 0; i < 5; i++) {
      Serial.println(slaveAddress[i]);
      }
    radio.stopListening();
    radio.setRetries(3,3);
    radio.openWritingPipe(slaveAddress);
    send();
}

//==============

void send() {
  //Serial.println("starting send");
  bool rslt;
    if (currentMillis - prevMillis >= txIntervalMillis) {
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
    if (rslt) {
        Serial.println("Acknowledge received");
        Serial.print("asked for Data: ");
        Serial.println(dataToSend);
        didSend = true;
        Serial.println("didSend set true and rslt is true");
    }
    else {
        Serial.println("Tx failed");
    }
        prevMillis = millis();
    }
    
}

//==============

void startQuestioning() {
  Serial.println("If all voters are done please continue by pressing g");
  //if (Serial.available() && Serial.read() == 'g') {
    readyForData = true;
    Serial.println("readyForData set true");
  //}
}

//==============

void changeAddress() {
Serial.println("changeAddress");
  slaveAddressCount += 1;
  Serial.println(slaveAddressCount);
  slaveAddress[c] = slaveAddressCount;
  for (int i = 0; i < 5; i++) {
    Serial.println(slaveAddress[i]);
    }
  passDataOn = true;
  readyForData = false;
  didSend = false;
  newData = false;
  switchAddress = false;
  Serial.print("printing all bools to see where we go:");
  Serial.print(didSend);
  Serial.print(newData);
  Serial.print(readyForData);
  Serial.println(switchAddress);
  
}

Thanks for any help
P.S.: I am also aware of the ACK method, thus TX and RX roles don’t have to be changed. I need to explore both.

In your Original Post you said "when I get to more than 88 the whole software breaks"

What exactly does that mean? Can you post some examples of the program output?

And PLEASE do not use single character variable names such as 'c' because I can't use the search facility in my editor to find all instances of the variable - every 'c' in the program gets highlighted.

...R

By the software breaks I mean that the Arduino resets and starts the sketch from scratch.

Here is an image, showing what happens:

I will try to not use single characters in future.

Thanks for the advice

It's very hard to read your image. Please don't post pictures of text, just copy and paste the text.

Insofar as I can read it I don't understand it. Presumably something is wrong somewhere - but what and where?

...R

I am sorry for making this harder to understand than it is...

What am I doing?
I am increasing the second digit of the address array by one to change the address. As (as far as I understand) the character is printed in ASCII the digit 1 equals (when printed) 49. 2 would then be 50 and so on. As soon as it gets to 88 (so 39 as a digit) the code breaks and the Arduino resets.

This is what is being outputted:

asked for Data: t // the receiving node is first in transmit mode to tell the other node to send its data. To verify I use the letter t
getanything // the receiver switched to receiving mode and is getting data
dataInit is false
new data set true
new data is true // just some bools to check where I am
Data received: B //this is the button (from A to D) that was pressed
switchAddress is true //it is supposed to switch address
changeAddress // void change address was called and starts
50
88
49
49
49 //the new Address {'2','39','1','1','1'}

right here it takes probably a good second for the program loop to start over (longer than before).

asked for Data: t // same thing starts again
getanything
dataInit // here it breaks and does not even finish printing the statement

Why are you screwing around with ASCII? Print all the bytes in HEX. Then, you'll know exactly what you've got.

The issue is, when I print for example the second key (which is the number that increases from one) it prints automatically like this.

I don't know how I would get it to print the digit its showing in the array.

  ...
  pSomeHex(thisSlaveAddress, 5);
  Serial.println();
  ...

void pSomeHex(byte* ptr, byte len) {
  while (len--) {
    pHex(*ptr++);
  }
}

void pHex(byte val) {
  pNibble(val >> 4);
  pNibble(val);
}

void pNibble(byte nib) {
  nib &= 0xF;
  Serial.write(nib + (nib < 10 ? '0' : 'A' - 10));
}

Larry_2:
50
88
49
49
49 //the new Address {‘2’,‘39’,‘1’,‘1’,‘1’}

right here it takes probably a good second for the program loop to start over (longer than before).

I had not realized those numbers are the values from the address array.

(By the way I see nothing wrong with printing them that way - I can’t see HEX adding any value).

You need to add more debugging Serial.print() statements to find out at exactly what part in the program it goes awry. It seems to print the address values OK so the problem must be somewhere else rather than in the changeAddress() function.

It would help if you explain what the Arduino is communicating with - it seems strange to me to have such a range of addresses.

…R

The first severe bug is in “setup”: “for (int i = -1; i < 5; i++)”, element at index “-1” does not exist. The next even worse bug is related to the array “char allData[20]”, which can hold 20 elements / characters. In your code you fill this data with “allData[slaveAddressCount - 49] = value”. Since you are constantly incrementing “slaveAddressCount” you will write “out of bounds” when your slave address counter reaches 70 (or the letter ‘F’) and upwards. That’s not gonna work for you :slight_smile:

EDIT: Oh, and these discoveries would have been impossible to make with your snippets in #1. So, yet again a topic where the bug wheren’t in the initially posted snippets! :wink:

Danois90:
The first severe bug is in ...

Nice detective work.

...R

Thank you all for your great help.

Robin2:
Nice detective work.

Indeed, thanks for that.

Robin2:
It would help if you explain what the Arduino is communicating with - it seems strange to me to have such a range of addresses.

I have to build a "feedback" system, where students/audience get a handheld device, the teacher/someone giving a speech/... wants the people to give their opinion and vote for something. So, the audience may become quite big, thus I need to change the addresses quite often. All in all I'm just trying to have one main Arduino receiving all the votes from the many transmitters (the handheld devices with four buttons).

Danois90:
EDIT: Oh, and these discoveries would have been impossible to make with your snippets in #1. So, yet again a topic where the bug wheren't in the initially posted snippets! :wink:

I actually thought, that the issue was something with the addresses, so I did not want to make it more complicated... But that actually made it worse....

Thank you very much. As soon as I get home I will test the code with these improvements.

Instead of giving each "voter" a different address, which will most likely give you problems, you should use an ID for the voter. There is no problem in having multiple "receivers" for the same message as long as you do not use any automated acknowledgements, so your "brain" can send a question to all voters at once, the voters can then answer to the same address but with different ID's. This construction should be MUCH simpler to do. Only caveat is that you have to make code which ensures that all voters receives the broadcasted message.

Thank you all!
By eliminating all the issues pointed out the code now works properly and does not fail.

Danois90:
Instead of giving each "voter" a different address, which will most likely give you problems, you should use an ID for the voter.

Thank you very much for pointing this out, however, I need to explore all of the different methods, so I basically need to try it this way too.

Thanks again!

Danois90:
Instead of giving each "voter" a different address, which will most likely give you problems, you should use an ID for the voter. There is no problem in having multiple "receivers" for the same message as long as you do not use any automated acknowledgements, so your "brain" can send a question to all voters at once, the voters can then answer to the same address but with different ID's. This construction should be MUCH simpler to do. Only caveat is that you have to make code which ensures that all voters receives the broadcasted message.

I agree with this.

The master can include in the message the ID of the slave that it requires an answer from. All the slaves will receive all the messages but only the slave that recognizes its own ID will respond. The master should apply a short timeout and then assume that the slave won't reply and go on to the next one.

You could have one slave (which you keep in your control) which would acknowledge all the messages just so you know that the master is sending successfully.

...R