[SOLVED] Can't get RF24 to work with SAMD51

Hi !

I'm using an Adafruit Grand Central board equipped with an ATSAMD51P20 running at 120Mhz.

I'm trying without success to get my nRF24L01+ module to work.

The connection is effective, Rx/Tx LEDs are blinking on both sides (client/server), but no data are sent/received on the GrandCentral.

The SPI_CLOCK_DIV wasn't defined and preventing the code to compile, so I've modified the RF24-config.h to include:

//Adafruit M4 (SAMD51)
#if defined(ADAFRUIT_FEATHER_M4_EXPRESS) || defined(ADAFRUIT_METRO_M4_EXPRESS) || defined(ADAFRUIT_GRAND_CENTRAL_M4)
#define SPI_CLOCK_DIV2 6
#define SPI_CLOCK_DIV4 12
#define SPI_CLOCK_DIV8 24
#define SPI_CLOCK_DIV16 48
#define SPI_CLOCK_DIV32 96
#define SPI_CLOCK_DIV64 192
#define SPI_CLOCK_DIV128 255
#endif

Any idea what's going wrong and how to get it to work ?

Thanks
Regards

Alkerion:
Any idea what's going wrong and how to get it to work ?

There are countless reasons why a wireless module might "not work" and the information you have provided gives no clue even as to whether the code snippet you posted is relevant.

My experience is only with the 16MHz Arduinos. If you have a couple of Unos I suggest you get the first example in this Simple nRF24L01+ Tutorial working between them and when that works you could try getting your faster board to communicate with one of the working Unos.

A common problem with nRF24s is inadequate 3.3v power. Try powering them with a pair of AA alkaline cells (3v) with the battery GND connected to the Arduino GND.

...R

Hi Robin,

My modules and my code is working perfect on Arduino Mega, the same modules ans same code isn't working on GrandCentral.

I've already tried to go back to the roots with basic code on the GC, without success.

There is something going wrong between the library and the GC, but what ?

Alkerion:
My modules and my code is working perfect on Arduino Mega, the same modules ans same code isn't working on GrandCentral.

That is rather confusing.

Do you mean that you have a pair of programs that can communicate reliably using a pair of Arduino Megas?

And if so, do you mean that when you use one of those GrandCentral boards in place of one of the Megas that communication stops working?

Please post the pair of programs that actually works (hopefully they are very short).

...R

The program is the exact same (99.9999%) on both boards.

The button board is an Arduino Micro.

The program is rather big, I'll just post relevant RF parts.

//Pins for the RF24 module
#define CE_PIN A8
#define CSN_PIN A9
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

I'm using Struct to exchange data.

//Struct for data to send
typedef struct {
	int rnd;
	int type;
	int msg;
}
A_t;

RF setup:

	//Setting up the RF24
	radio.begin();
	radio.printDetails();
	radio.setDataRate(RF24_250KBPS); //best 
	radio.setPALevel(RF24_PA_MAX); //max power
	radio.setChannel(125);//To avoid Wifi noise
	radio.openReadingPipe(1, thisMasterAddress);
	radio.enableAckPayload();
	radio.setRetries(3, 15); // delay, count
	radio.startListening();

The Loop:

void loop() {

	do {
		BlaBlaBla....
	}

	while (!radio.available());

	radio.read(&Data_Received, sizeof(Data_Received));

	btnNr = Data_Received.msg;

	if (btnNr != buzzMashedDisplay[0][0] ) {
			sendToBtn(btnNr, TURN_LED_ON);
	}
}

sendTBtn():

void sendToBtn(int id, int c) {

	Data_Sent.msg = c;
	Data_Sent.rnd++;

	bool rslt;

	//We have to stop listening before writing
	radio.stopListening();
	radio.flush_tx();

	radio.openWritingPipe(buttonAddress[id - 1]);
	
	rslt = radio.write(&Data_Sent, sizeof(Data_Sent));

	if (rslt) {
		btnConnected[id] = true;
		if (!radio.isAckPayloadAvailable()) {
			Serial.println("  Acknowledge but no data ");
		}
	}
	else {
		btnConnected[id] = false;
		Serial.println("  Tx failed");
	}
	//We start the listening again
	radio.startListening();
}

Something is working as when I push the button the GC see data are incoming, but it always receive 0.

Same for sending data back to button, the button receive the data, but alwas 0.

They both send an acknowledge.

If I change the GC by a Mega everything is working fine.

I've tried to run Mega and GC in parallel, when I push the button the Mega react correctly, the GC receive 0....

The only thing I see, apart it's totally different MC, is the speed difference between both boards 16Mhz vs 120Mhz.
Could that be an issue for SPI ?

I've tried with many SPI_CLOCK_DIV16 values, without success, result is always the same.

Alkerion:
The program is rather big, I'll just post relevant RF parts.

First get communication working reliably with a very short program - as in my Tutorial.

Second, posting snippets is next to useless - the problem is almost always in the other part - which is why you haven't found it. Which is also a strong reason for starting with a very short program.

Third, does this

The button board is an Arduino Micro.

mean that you are successfully communicating between a Micro and a Mega using nRF24 modules? If so, why not just say so.

Fourth, maybe the problem is in the 0.0001% difference

The program is the exact same (99.9999%) on both boards.

And I have understood that you are trying 3 different boards.

What is the difference, and why is there a difference?

Fifth - same as First - get wireless communication working with a simple program. Only then add on other features.

...R

Hi !

First:

Wise advice, so I've tried from scratch with your Simple code.

I got it to work on both Mega and GrandCentral.

But as soon as I try to send a Struct it stops working on the GrandCentral....

Note that even if data aren't received there is an acknowledgement

Rx:

// SimpleRx - the slave or the receiver

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

#define CE_PIN   A8
#define CSN_PIN A9


//Struct for data received
typedef struct {
	int rnd;
	int type;
	int msg;
}
B_t;

B_t Data_Received;

//const byte thisSlaveAddress[5] = { 'R','x','A','A','A' }; //Mega
const byte thisSlaveAddress[5] = { 'R','x','A','A','B' }; //Grand Central

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
bool newData = false;

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

void setup() {

	Serial.begin(115200);

	Serial.println("SimpleRx Starting");
	radio.begin();
	radio.setDataRate(RF24_250KBPS);
	radio.openReadingPipe(1, thisSlaveAddress);
	radio.startListening();
}

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

void loop() {
	//getStructData();
	//showStructData();
	getData();
	showData();
}

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

void getData() {
	if (radio.available()) {
		radio.read(&dataReceived, sizeof(dataReceived));
		newData = true;
	}
}

void showData() {
	if (newData == true) {
		Serial.print("Data received ");
		Serial.println(dataReceived);
		newData = false;
	}
}

void getStructData() {
	if (radio.available()) {
		radio.read(&Data_Received, sizeof(Data_Received));
		newData = true;
	}
}

void showStructData() {
	if (newData == true) {
		Serial.print("Data received ");
		Serial.println(Data_Received.msg);
		newData = false;
	}
}

Tx:

// SimpleTx - the master or the transmitter

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


#define CE_PIN   A4
#define CSN_PIN A5

//Struct for data to send
typedef struct {
	int rnd;
	int type;
	int msg;
}
A_t;

A_t Data_Sent;

const byte slaveAddress[5] = { 'R','x','A','A','A' };
const byte slaveAddress2[5] = { 'R','x','A','A','B' };

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

char dataToSend[10] = "Message 0";
char txNum = '0';


unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second


void setup() {

	Serial.begin(9600);

	Serial.println("SimpleTx Starting");

	radio.begin();
	radio.setDataRate(RF24_250KBPS);
	radio.setRetries(3, 5); // delay, count
	
}

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

void loop() {
	currentMillis = millis();
	if (currentMillis - prevMillis >= txIntervalMillis) {
		radio.openWritingPipe(slaveAddress);
		send();
		//sendStruct();
		delay(1000);
		radio.openWritingPipe(slaveAddress2);
		send();
		//sendStruct();
		prevMillis = millis();
		updateMessage();
	}
}

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

void send() {

	bool rslt;
	rslt = radio.write(&dataToSend, sizeof(dataToSend));
	// Always use sizeof() as it gives the size as the number of bytes.
	// For example if dataToSend was an int sizeof() would correctly return 2

	Serial.print("Data Sent ");
	Serial.print(dataToSend);
	if (rslt) {
		Serial.println("  Acknowledge received");
	}
	else {
		Serial.println("  Tx failed");
	}
}

void sendStruct() {

	Data_Sent.rnd++;

	bool rslt;

	rslt = radio.write(&Data_Sent, sizeof(Data_Sent));

	// Always use sizeof() as it gives the size as the number of bytes.
	// For example if dataToSend was an int sizeof() would correctly return 2

	Serial.print("Data Sent ");
	Serial.print(Data_Sent.msg);
	if (rslt) {
		Serial.println("  Acknowledge received");
		updateMessage();
	}
	else {
		Serial.println("  Tx failed");
	}
}

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

void updateMessage() {
	// so you can see that new data is being sent
	txNum += 1;
	if (txNum > '9') {
		txNum = '0';
	}
	dataToSend[8] = txNum;
	Data_Sent.msg++;
}

Second:
I won't post thousands lines of code here.

Third:
I though it was clear, sorry ::slight_smile:

Fourth:
The only differences are in Pins attribution

Fifth:
Not won with Struct yet.

Any idea where the problem could be ?

In RF24 Lib or SPI lib ?

GrandCentral Bootloader ?

That's the same issue with a Metro M4 board (same controller, less IO) in place of GrandCentral.

Hold on now.

If the simple pair of programs works then there is nothing wrong with the RF24 lib or with SPI.

It just occurs to me that the problem with the struct is probably because the datatypes on the GrandCentral are different from the Mega. For example on the Mega an int is 2 bytes but it might be 4 bytes on the GrandCentral.

The nRF24 just sends a stream of bytes so your programs need to use datatypes that are the same size.

...R

OK....

I feel a little stupid....

I was having a break in front of TV with some good ice cream, that should have cooled my brain just enough to suddenly realized that the cpus on Mega and GrandCentral aren't really of the same kind.

Mega use an Atmega2560, 8bits AVR
Pro micro use a ATMega 32U4, 8bits AVR
GrandCentral use a ATSAMD51, 32bits ARM.

Sending a Struct containing int is no so a good idea as int isn't the same size depending the micro-controller.

It was working between Mega and Pro micro as they are both 8 bits, but not the Grand central.

Using uint8_t solved the issue

:slight_smile:

Hey Robin !

You was faster than me on understanding the issue :wink:

Thanks a lots for your help.

Regards

Mainly for the benefit of someone else who might be reading this Thread I would like to draw attention to the value of proving that communication could work with a very simple program.

Once it was clear that the wireless was working diagnostic thoughts could turn to the reason why a specific type of message might present a problem.

...R