nrf24L01 low level programming with arduino nano and rpi4b issue

Hello. I’m trying to send a message from an Arduino Nano to a Raspberry Pi using NRF24L01 modules, but it’s not working. I’ve tested the NRF24L01 using only the NRF24 library(on the Arduino and the Raspberry side), and it worked fine. I suspect the issue lies in the Arduino code since I don't have much experience with embedded programming. I've configured both the transmitter and receiver to use the same address and settings, but no message seems to be received on the Raspberry Pi. Not having any obvious errors.
The wiring is as follows:

Nrf24L01 is connected to Raspberry Pi as:
CE Pin 15 GPIO22
CSN Pin 24 GPIO8 (CE0)
SCK Pin 23 GPIO11
MOSI Pin 19 GPIO10
MISO Pin 21 GPIO9
IRQ Not connected

, and to Arduino
CSN D10
SCK D13
MOSI D11
MISO D12
IRQ D2

I've also connected a 10uF capacitor between GND and VCC.

I’d appreciate it if anyone could help me identify what might be wrong or what I should check next!

Arduino Nano code for nrf24L01 without any library:

#include <SPI.h>

// Pin configuration - change if using different pins
#define CE_PIN   9
#define CSN_PIN 10

// NRF24L01 register definitions
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define TX_ADDR     0x10
#define RX_ADDR_P0  0x0A
#define RX_PW_P0    0x11

// SPI commands
#define W_REGISTER   0x20
#define R_REGISTER   0x00
#define W_TX_PAYLOAD 0xA0
#define FLUSH_TX     0xE1

// Address must exactly match Raspberry Pi receiver (5 bytes)
const uint8_t address[5] = {0x34, 0x34, 0x34, 0x34, 0x34};

void setup() {
  Serial.begin(115200);
  while (!Serial); // Wait for serial monitor
  
  pinMode(CE_PIN, OUTPUT);
  pinMode(CSN_PIN, OUTPUT);
  
  digitalWrite(CE_PIN, LOW);
  digitalWrite(CSN_PIN, HIGH);
  
  SPI.begin();
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // 10MHz SPI

  // Initialize radio
  writeRegister(CONFIG, 0x08);  // Power down
  writeRegister(EN_AA, 0x00);   // Disable auto-ack
  writeRegister(EN_RXADDR, 0x01); // Enable pipe 0
  writeRegister(SETUP_AW, 0x03);  // 5-byte addresses
  writeRegister(SETUP_RETR, 0x00); // No retries
  writeRegister(RF_CH, 76);      // Channel 76 (2.476GHz)
  writeRegister(RF_SETUP, 0x06); // 1Mbps, 0dBm (RF24_PA_LOW)
  
  // Set addresses
  writeRegisterMulti(TX_ADDR, address, 5);
  writeRegisterMulti(RX_ADDR_P0, address, 5);
  writeRegister(RX_PW_P0, 32);   // 32-byte payload
  
  // Power up in TX mode
  writeRegister(CONFIG, 0x0E);   // PWR_UP=1, PRIM_TX=1, CRC=2 bytes
  delay(5);                      // Power-up delay

  Serial.println(F("Arduino NRF24L01 Transmitter ready"));
  Serial.print(F("Address: 34 34 34 34 34 | Channel: 76 | Payload: 32 bytes\n"));
}

void loop() {
  const char message[] = "Hello RPi!";
  
  Serial.print(F("Sending: "));
  Serial.println(message);
  
  if(transmitData((uint8_t*)message, sizeof(message))) {
    Serial.println(F("Transmission successful"));
  } else {
    Serial.println(F("Transmission failed"));
    // Auto-recovery
    writeRegister(CONFIG, 0x08); // Power down
    delay(100);
    writeRegister(CONFIG, 0x0E); // Power up
  }
  
  delay(1000); // 1 second between transmissions
}

bool transmitData(uint8_t* data, uint8_t length) {
  if(length > 32) length = 32;
  
  // Flush TX buffer
  digitalWrite(CSN_PIN, LOW);
  SPI.transfer(FLUSH_TX);
  digitalWrite(CSN_PIN, HIGH);
  
  // Write payload
  digitalWrite(CSN_PIN, LOW);
  SPI.transfer(W_TX_PAYLOAD);
  for(uint8_t i=0; i<length; i++) {
    SPI.transfer(data[i]);
  }
  digitalWrite(CSN_PIN, HIGH);
  
  // Start transmission (10-15μs CE pulse)
  digitalWrite(CE_PIN, HIGH);
  delayMicroseconds(15);
  digitalWrite(CE_PIN, LOW);
  
  // Wait for completion (200ms timeout)
  uint32_t start = millis();
  while(!(readRegister(STATUS) & 0x20)) { // Check TX_DS bit
    if(millis() - start > 200) {
      writeRegister(STATUS, 0x70); // Clear all flags
      return false;
    }
  }
  
  writeRegister(STATUS, 0x20); // Clear TX_DS flag
  return true;
}

// Helper functions
uint8_t readRegister(uint8_t reg) {
  digitalWrite(CSN_PIN, LOW);
  SPI.transfer(R_REGISTER | (reg & 0x1F));
  uint8_t result = SPI.transfer(0xFF);
  digitalWrite(CSN_PIN, HIGH);
  return result;
}

void writeRegister(uint8_t reg, uint8_t value) {
  digitalWrite(CSN_PIN, LOW);
  SPI.transfer(W_REGISTER | (reg & 0x1F));
  SPI.transfer(value);
  digitalWrite(CSN_PIN, HIGH);
}

void writeRegisterMulti(uint8_t reg, uint8_t* data, uint8_t length) {
  digitalWrite(CSN_PIN, LOW);
  SPI.transfer(W_REGISTER | (reg & 0x1F));
  for(uint8_t i=0; i<length; i++) {
    SPI.transfer(data[i]);
  }
  digitalWrite(CSN_PIN, HIGH);
}

And the raspberry pi code:

#include <iostream>
#include <RF24/RF24.h>
#include <ctime>

using namespace std;

// Hardware configuration
RF24 radio(22, 0); // CE=GPIO22, CSN=GPIO8 (CE0)

// 5-byte address (NO null terminator)
const uint8_t address[5] = {0x34, 0x34, 0x34, 0x34, 0x34};

int main()
{
    // Initialize
    if (!radio.begin()) {
        cerr << "Radio hardware not responding!" << endl;
        return 1;
    }

    radio.setPALevel(RF24_PA_LOW);
    radio.setDataRate(RF24_1MBPS);
    radio.setChannel(76);
    radio.setPayloadSize(32);
    radio.setCRCLength(RF24_CRC_16);
    radio.setAutoAck(false); // Must match Arduino's EN_AA=0x00
    radio.setRetries(0, 0);  // Disable retries

    // Open pipe with 5-byte address
    radio.openReadingPipe(0, address);
    radio.startListening();

    // Debug output
    cout << "Listening on:" << endl;
    cout << "  Channel: " << (int)radio.getChannel() << endl;
    cout << "  Address: ";
    for (int i = 0; i < 5; i++)
        printf("%02X ", address[i]);
    cout << endl;

    char payload[32] = {0};
    time_t start = time(nullptr);

    while (time(nullptr) - start < 10) {
        if (radio.available()) {
            radio.read(payload, sizeof(payload));
            cout << "Received: " << payload << endl;
            start = time(nullptr);               // Reset timeout
            memset(payload, 0, sizeof(payload)); // Clear buffer
        }
        delay(10); 
    }

    cout << "No messages received for 30 seconds." << endl;
    return 0;
}

Also, if anyone has a tutorial or anything like that that resolves this problem(or the whole project) I will be very grateful.

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

https://forum.arduino.cc/t/how-to-get-the-best-out-of-this-forum

Please post your full sketch, using code tags when you do

Posting your code using code tags prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows

Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

It is also helpful to post error messages in code tags as it makes it easier to scroll through them and copy them for examination

Please post an annotated schematic showing exactly how you have wired your project. Be sure to include all power sources, power, grounds, and any other hardware involved. Be sure the radios are at least a meter apart.

The wiring is very simple, nothing fancy. I've updated the post to include this information.
Also, the modules were working fine when I used the RF24 library, even if they were only 10 cm apart. For VCC, I'm using the 3.3V pin from the Raspberry Pi. I don't think this is a hardware issue, but rather a problem with the code.

Have you gotten into the printDetails() function of the RF24 library?

I would start there, comparing register and address values to make sure everything matches. It prints them in hex, so you can use Serial.print(value,HEX); in your own code to make it easier.

Yes, everything seemed fine and the same on both sides (channel, address), but a problem that I encounter is when I compile the code the first I get an error from the nrf24 library: hardware is not responding, and the second time compile right after it works fine. I really can t find any code for Arduino that I can look at to discover the problem on my side.

The hardware not responding msg is because of an SPI communication issue. At that point, you haven't gotten into the radio functionality yet.

I would double-check your wiring and/or power supply. You need a power supply separate from the Nano or one of the NRF24 power adapters that converts the 5v down the 3.3v.

You can also try initializing it at a lower SPI speed, but this is more of a workaround than a fix.

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