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

RPi 4 with Arduino Nano: RPi 4 can RX but can't TX - RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc #702

Closed PLLefebvre closed 3 years ago

PLLefebvre commented 3 years ago

Hi, I'm working on a project with Arduino Nano and Raspberry pi 4 that will communicate together using nRF24L01+ modules.

The RPi4 can receive data from the Arduino NANO but, my problem: The RPi4 can't succeed to TX data to the Arduino NANO.
Since I can RX and I can get the radio.printDetails() with the RPi4, I assume the pinout is OK on both devices (SPI and CS).

I have a 100uF plus a 10uF in parallel between VCC and GND on both NRF24 hooked on the RPi4 and the Arduino NANO. I do have an adapter 5V to 3V3 so I can avoid direct connection to the Raspberry pi as well as the Arduino. I have tested 2 arduinos and TX + RX are working in this case so It confirms the RF hardware is OK.

To narrow down the problem to the very minimum, I'm using the hello_world_tx.py example on the RPi and the hello_world_rx.ino example on the arduino nano.
I have been working on this bug trying multiple things on the HW and SW even modifying parts of the library with no success. Any idea where I should be looking to solve the issue? I can RX but can't TX with my raspberry pi 4 and the message when I try to TX is: RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.

Here is the code (adapted from the library examples):

RPi4:

#!/usr/bin/env python
# Simplest possible example of using RF24Network,
#
#  TRANSMITTER NODE
#  Sends messages from to receiver.
#
from __future__ import print_function
import time
from struct import *
from RF24 import *
from RF24Network import *

# CE Pin, CSN Pin, SPI Speed

radio = RF24(26,0)   #RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ)
network = RF24Network(radio)

millis = lambda: int(round(time.time() * 1000)) & 0xffffffff
octlit = lambda n: int(n, 8)

# Address of our node in Octal format (01,021, etc)
this_node = octlit("01")

# Address of the other node
other_node = octlit("00")
# ms -  How `long to wait before sending the next message
interval = 2000

radio.begin()
time.sleep(0.1);
network.begin(90, this_node)  # channel 90
radio.setDataRate(RF24_1MBPS) #250KBPS)
radio.setPALevel(RF24_PA_MAX);
radio.printDetails()
print(radio.getCRCLength())
#not implemented in the wrapper: radio.printPrettyDetails()

packets_sent = 0
last_sent = 0

while 1:
    network.update()
    now = millis()        
    # If it's time to send a message, send it!
    if (now - last_sent >= interval):
        last_sent = now
        print('Sending ..')
        payload = pack('<LL', millis(), packets_sent)
        packets_sent += 1
        ok = network.write(RF24NetworkHeader(other_node), payload)
        if ok:
            print('ok.')
        else:`
            print('failed.')

The Arduino nano:

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

RF24 radio(9,10);                // nRF24L01(+) radio attached using Getting Started board 

RF24Network network(radio);      // Network uses that radio
const uint16_t this_node = 00;//01;    // Address of our node in Octal format ( 04,031, etc)
const uint16_t other_node = 01;//00;   // Address of the other node in Octal format

struct payload_t {                 // Structure of our payload
  unsigned long ms;
  unsigned long counter;
};

void setup(void)
{
  Serial.begin(9600);
  Serial.println("RF24Network/examples/helloworld_rx/");

  SPI.begin();
  radio.begin();

  network.begin(/*channel*/ 90, /*node address*/ this_node);
  //radio.setDataRate(RF24_250KBPS);  
  radio.setDataRate(RF24_1MBPS);
}

void loop(void){
  network.update();                  // Check the network regularly

  while ( network.available() ) {     // Is there anything ready for us?

    RF24NetworkHeader header;        // If so, grab it and print it out
    payload_t payload;
    network.read(header,&payload,sizeof(payload));
    Serial.print("Received packet #");
    Serial.print(payload.counter);
    Serial.print(" at ");
    Serial.println(payload.ms);
  }
}

Here is what I get from in the RPI4 when I try the helloworld_tx.py script: ================ SPI Configuration ================ CSN Pin = 0 CE Pin = Custom GPIO26 SPI Speedz = 10 Mhz ================ NRF Configuration ================ STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0xcccccc3ccc 0xcccccc3c3c RX_ADDR_P2-5 = 0x33 0xce 0x3e 0xe3 TX_ADDR = 0xcccccccc3c RX_PW_P0-6 = 0x20 0x20 0x20 0x20 0x20 0x20 EN_AA = 0x3e EN_RXADDR = 0x3f RF_CH = 0x5a RF_SETUP = 0x07 CONFIG = 0x0f DYNPD/FEATURE = 0x3f 0x04 Data Rate = 1MBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX ARC = 0

Sending .. RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc. failed. Sending .. RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc. failed. Sending .. RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc. failed. Sending .. RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc. RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc. failed.

2bndy5 commented 3 years ago

I can tell that the pyRF24 package isn't updated as evident by

not implemented in the wrapper: radio.printPrettyDetails()

because it is in v1.3.11 and

CSN Pin = 0

which now prints "/dev/spidev0.0" for passing 0 as the CSN pin

But that doesn't address the real problem which I suspect is wiring related (or the SPI bus is hanging but that's less likely). Check your wiring isn't "loose" (connections don't jiggle easily). If your using long jumper cables, try lowering your SPI speed with the optional 3rd parameter in the c'tor (RF24 radio(26, 0, 2500000); in C++ or radio = RF24(26, 0, 2500000) in python). You mentioned that

I do have an adapter 5V to 3V3 so I can avoid direct connection to the Raspberry pi as well as the Arduino.

is this the adapter you speak of? image

I had to stop using this adapter on my RPi4 when developing toward v1.3.11 because I also was getting that errNotfy() call (the "RF24 HARDWARE FAIL..."). I suspect that the 5v regulator on the RPi4 doesn't provide enough juice to use that adapter because it wasn't an issue (or rather less of an issue) after directly connecting the nRF module to the RPi (with 100uF cap of course).

PLLefebvre commented 3 years ago

Hi, Thank you so much for your feedback. I really appreciate. I have indeed the same adapter as yours on both sides (arduino nano and rpi4). I actually tried with and without using my arduinos and I found issues without. The simple action of touching the transceiver was affecting the transmission performances. But I did not try to remove the adapter on my RPI4. So I did after your suggestion. But with no success unfortunately. Here is what I tried after your reply:

  1. removed the 5V to 3v3 adapter, did not changed the problem;
  2. double checked my connections, did not changed the problem;
  3. set the SPI to 2500000 using python line: radio = RF24(26, 0, 2500000). did not changed the problem;
  4. installed a dedicated 5V power supply for the nRF24 on the RPI4 side with the 5V to 3v3 adapter as well (also with the 100uF cap installed directly on the nrf24 module), did not solve the problem...
  5. updated and recompiled the RF24 library.

But still, I get that same problem. I am able to receive data from the Arduino nano to my RPi4 but I can't transmit from the RPI4. Here is what I get when I try my code to receive data from Arduino to RPI4:

Radio Begin Done
Network Begin Done
================ SPI Configuration ================
CSN Pin         = /dev/spidev0.0
CE Pin          = Custom GPIO26
SPI Speedz      = 10 Mhz
================ NRF Configuration ================
STATUS          = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1    = 0xcccccc3ccc 0xccccccce3c
RX_ADDR_P2-5    = 0x33 0xce 0x3e 0xe3
TX_ADDR         = 0xcccccccc3c
RX_PW_P0-6      = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA           = 0x3e
EN_RXADDR       = 0x3f
RF_CH           = 0x5a
RF_SETUP        = 0x27
CONFIG          = 0x0f
DYNPD/FEATURE   = 0x3f 0x04
Data Rate       = 250 KBPS
Model           = nRF24L01+
CRC Length      = 16 bits
PA Power        = PA_MAX
ARC             = 0
Now waiting for the next packet to be recieved...
...
...
...
...
...
...
...
Data Coming
payload length  12
--------------------
Temperature:  19.50  'C
Humitity:  45.60  %
Sensor ID:  0
Header Type:
--------------------
bytearray(b'45.60,19.50\x00')
...
...

And for the problem I have, here is the info I get when I try to transmit data from my RPI4 to the Arduino nano (now radio.printPrettyDetails() is working for more info):

================ SPI Configuration ================
CSN Pin         = /dev/spidev0.0
CE Pin          = Custom GPIO26
SPI Speedz      = 2 Mhz
================ NRF Configuration ================
STATUS          = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1    = 0xcccccc3ccc 0xcccccc3c3c
RX_ADDR_P2-5    = 0x33 0xce 0x3e 0xe3
TX_ADDR         = 0xcccccccc3c
RX_PW_P0-6      = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA           = 0x3e
EN_RXADDR       = 0x3f
RF_CH           = 0x5a
RF_SETUP        = 0x27
CONFIG          = 0x0f
DYNPD/FEATURE   = 0x3f 0x04
Data Rate       = 250 KBPS
Model           = nRF24L01+
CRC Length      = 16 bits
PA Power        = PA_MAX
ARC             = 0
================ SPI Configuration ================
CSN Pin                 = /dev/spidev0.0
CE Pin                  = Custom GPIO26
SPI Frequency           = 2 Mhz
================ NRF Configuration ================
Channel                 = 90 (~ 2490 MHz)
RF Data Rate            = 250 KBPS
RF Power Amplifier      = PA_MAX
RF Low Noise Amplifier  = Enabled
CRC Length              = 16 bits
Address Length          = 5 bytes
Static Payload Length   = 32 bytes
Auto Retry Delay        = 2000 microseconds
Auto Retry Attempts     = 5 maximum
Packets lost on
    current channel     = 0
Retry attempts made for
    last transmission   = 0
Multicast               = Disabled
Custom ACK Payload      = Disabled
Dynamic Payloads        = Enabled
Auto Acknowledgment     = Disabled
Primary Mode            = TX
TX address              = 0xcccccccc3c
pipe 0 ( open ) bound   = 0xcccccc3ccc
pipe 1 ( open ) bound   = 0xcccccc3c3c
pipe 2 ( open ) bound   = 0x33
pipe 3 ( open ) bound   = 0xce
pipe 4 ( open ) bound   = 0x3e
pipe 5 ( open ) bound   = 0xe3
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.
Sending ..
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
RF24 HARDWARE FAIL: Radio not responding, verify pin connections, wiring, etc.
failed.

Not sure what I could try else. Do you have any idea?

2bndy5 commented 3 years ago

Are the nRF24L01 module's the PA/LNA variant? I ask because those modules need electromagnetic shielding. Usually, this would be fixed by using a separate power supply, but you said that didn't work. You might have counterfeit modules (a conclusion we came to on a similar issue when helping someone else that bought the modules from a seller called MakerFire on amazon.com). Sending requires a lot more power than receiving, so you can try playing with capacitors that have more capacitance (in parallel with what you already have). But ultimately it's not a software problem. Setting the PALevel to low or min might help because it requires slightly less power to send, but that is just a hack and not a usable solution for deployment.

PLLefebvre commented 3 years ago

Yes well I have all the variant nRF24L01. Some with the PA/LNA and some without. I have tried nRF24L01 that I bought from different sources on Amazon. I actually have 5 PA/LNA (2 from WayinTop and 3 from Longrunner) and 10 nRF24 modules without PA/LNA from longrunner as well. I have tried the nRF24 with and without the PA/LNA. They all work fine when I it is arduino nano to arduino nano. But the issue is when I try to TX from RPI4 to arduino nano.

FI, I am using a virtual python environment. All the setup and builds are within that environment running:

Python 3.8.1 (default, Nov 1 2020, 21:40:20) [GCC 8.3.0] on linux

Do you think it could be a CS timing issue with the code or some registers communications ? I see in the RF24.cpp that when transmitting, it checks radio status for 95ms before triggering the errNotfy(). Is it enough ? (I tried 200ms) but no success so far...

2bndy5 commented 3 years ago

95 ms is more than enough; what you are fighting is a power issue. Running from within python venv isn't the problem. CSN timing is not an issue because the library works on my RPi4 with an non PA/LNA module.

PLLefebvre commented 3 years ago

A bit of additional info...

Tried this library : https://github.com/2bndy5/CircuitPython_nRF24L01:

using the simple example: examples/nrf24l01_2arduino_handling_data.py:


"""
Example of library driving the nRF24L01 to communicate with a nRF24L01 driven by
the TMRh20 Arduino library. The Arduino program/sketch that this example was
designed for is named GettingStarted_HandlingData.ino and can be found in the "RF24"
examples after the TMRh20 library is installed from the Arduino Library Manager.
"""
import time
import struct
import board
import digitalio as dio
# if running this on a ATSAMD21 M0 based board
# from circuitpython_nrf24l01.rf24_lite import RF24
from circuitpython_nrf24l01.rf24 import RF24

# addresses needs to be in a buffer protocol object (bytearray)
address = [b"1Node", b"2Node"]

# change these (digital output) pins accordingly
ce = dio.DigitalInOut(board.D7) #board.D4)
csn = dio.DigitalInOut(board.D8) #board.D5)

# using board.SPI() automatically selects the MCU's
# available SPI pins, board.SCK, board.MOSI, board.MISO
spi = board.SPI()  # init spi bus object

# initialize the nRF24L01 on the spi bus object
nrf = RF24(spi, csn, ce)
nrf.dynamic_payloads = False  # the default in the TMRh20 arduino library

# set the Power Amplifier level to -12 dBm since this test example is
# usually run with nRF24L01 transceivers in close proximity
nrf.pa_level = -12

# change this variable to oppose the corresponding variable in the
# TMRh20 library's GettingStarted_HandlingData.ino example
radioNumber = True

# Create a data structure for transmitting and receiving data
# pylint: disable=too-few-public-methods
class DataStruct:
    """A data structure to hold transmitted values as the
    'HandlingData' part of the TMRh20 library example"""
    time = 0  # in milliseconds (used as start of timer)
    value = 1.22  # incremented  by 0.01 with every transmission
# pylint: enable=too-few-public-methods

myData = DataStruct()

def master(count=5):  # count = 5 will only transmit 5 packets
    """Transmits an arbitrary unsigned long value every second"""
    # set address of TX node into a RX pipe, and
    # set address of RX node into a TX pipe
    if radioNumber:
        nrf.open_rx_pipe(1, address[0])
        nrf.open_tx_pipe(address[1])
    else:
        nrf.open_rx_pipe(1, address[1])
        nrf.open_tx_pipe(address[0])
    nrf.listen = False  # ensures the nRF24L01 is in TX mode
    while count:
        print("Now Sending")
        myData.time = int(time.monotonic() * 1000)  # start timer
        # use struct.pack to packetize your data into a usable payload
        # '<' means little endian byte order.
        # 'L' means a single 4 byte unsigned long value.
        # 'f' means a single 4 byte float value.
        buffer = struct.pack("<Lf", myData.time, myData.value)
        # send the payload. send_only=1 is default behavior in TMRh20 library
        result = nrf.send(buffer, send_only=1)
        if not result:
            print("send() failed or timed out")
        else:  # sent successful; listen for a response
            nrf.listen = True  # get nRF24L01 ready to receive a response
            timeout = True  # used to determine if response timed out
            while time.monotonic() * 1000 - myData.time < 200:
                # the arbitrary 200 ms timeout value is also used in the
                # TMRh20 library's GettingStarted_HandlingData sketch
                if nrf.update() and nrf.pipe is not None:
                    end_timer = time.monotonic() * 1000  # end timer
                    rx = nrf.recv(32)  # 32 mimics behavior in TMRh20 library
                    rx = struct.unpack("<Lf", rx[:8])
                    myData.value = rx[1]  # save the new float value
                    timeout = False  # skips timeout prompt
                    # print total time to send and receive data
                    print(
                        "Sent {} Got Response: {}".format(
                            struct.unpack("<Lf", buffer),
                            rx
                        )
                    )
                    print("Round-trip delay:", end_timer - myData.time, "ms")
                    break
            if timeout:
                print("failed to get a response; timed out")
            nrf.listen = False  # put the nRF24L01 back in TX mode
        count -= 1
        time.sleep(1)

def slave(count=3):
    """Polls the radio and prints the received value. This method expires
    after 6 seconds of no received transmission"""
    # set address of TX node into a RX pipe, and
    # set address of RX node into a TX pipe
    if radioNumber:
        nrf.open_rx_pipe(1, address[0])
        nrf.open_tx_pipe(address[1])
    else:
        nrf.open_rx_pipe(1, address[1])
        nrf.open_tx_pipe(address[0])
    nrf.listen = True  # put radio into RX mode and power up
    myData.time = time.monotonic() * 1000  # in milliseconds
    while count and (time.monotonic() * 1000 - myData.time) < 6000:
        if nrf.update() and nrf.pipe is not None:
            # clear flags & fetch 1 payload in RX FIFO
            buffer = nrf.recv(32)  # 32 mimics behavior in TMRh20 library
            # increment floating value as part of the "HandlingData" test
            myData.value = struct.unpack("<f", buffer[4:8])[0] + 0.01
            nrf.listen = False  # ensures the nRF24L01 is in TX mode
            myData.time = time.monotonic() * 1000
            # echo buffer[:4] appended with incremented float
            # send_only=True is the default behavior in TMRh20 library
            result = nrf.send(
                buffer[:4] + struct.pack("<f", myData.value),
                send_only=True
            )
            end_timer = time.monotonic() * 1000  # in milliseconds
            # expecting an unsigned long & a float, thus the
            # string format "<Lf"; buffer[:8] ignores the padded 0s
            buffer = struct.unpack("<L", buffer[:4])
            # print the unsigned long and float data sent in the response
            print("Responding: {}, {}".format(buffer[0], myData.value))
            if not result:
                print("response failed or timed out")
            else:
                # print timer results on transmission success
                print(
                    "successful response took {} ms".format(
                        end_timer - myData.time
                    )
                )
            # this will listen indefinitely till counter == 0
            count -= 1
            nrf.listen = True  # put nRF24L01 back into RX mode
    # recommended behavior is to keep in TX mode when in idle
    nrf.listen = False  # put the nRF24L01 in TX mode + Standby-I power state

print(
    """\
    nRF24L01 communicating with an Arduino running the\n\
    TMRh20 library's "GettingStarted_HandlingData.ino" example.\n\
    Run slave() to receive\n\
    Run master() to transmit\n\

    radioNumber is {}. Change this variable to oppose the TMRh20\n\
    example's radioNumber value.""".format(radioNumber)
)

with arduino GettingStarted.ino:


/*
* Getting Started example sketch for nRF24L01+ radios
* This is a very basic example of how to send data from one node to another
* Updated: Dec 2014 by TMRh20
*/

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

/****************** User Config ***************************/
/***      Set this radio as radio number 0 or 1         ***/
bool radioNumber = 0;

/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7 & 8 */
RF24 radio(9,10); //7,8);
/**********************************************************/

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

// Used to control whether this node is sending or receiving
bool role = 0;

void setup() {
  Serial.begin(115200);
  Serial.println(F("RF24/examples/GettingStarted"));
  Serial.println(F("*** PRESS 'T' to begin transmitting to the other node"));

  radio.begin();

  // Set the PA Level low to prevent power supply related issues since this is a
 // getting_started sketch, and the likelihood of close proximity of the devices. RF24_PA_MAX is default.
  radio.setPALevel(RF24_PA_LOW);

  // Open a writing and reading pipe on each radio, with opposite addresses
  if(radioNumber){
    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[0]);
  }else{
    radio.openWritingPipe(addresses[0]);
    radio.openReadingPipe(1,addresses[1]);
  }

  // Start the radio listening for data
  radio.startListening();
}

void loop() {

/****************** Ping Out Role ***************************/  
if (role == 1)  {

    radio.stopListening();                                    // First, stop listening so we can talk.

    Serial.println(F("Now sending"));

    unsigned long start_time = micros();                             // Take the time, and send it.  This will block until complete
     if (!radio.write( &start_time, sizeof(unsigned long) )){
       Serial.println(F("failed"));
     }

    radio.startListening();                                    // Now, continue listening

    unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
    boolean timeout = false;                                   // Set up a variable to indicate if a response was received or not

    while ( ! radio.available() ){                             // While nothing is received
      if (micros() - started_waiting_at > 200000 ){            // If waited longer than 200ms, indicate timeout and exit while loop
          timeout = true;
          break;
      }      
    }

    if ( timeout ){                                             // Describe the results
        Serial.println(F("Failed, response timed out."));
    }else{
        unsigned long got_time;                                 // Grab the response, compare, and send to debugging spew
        radio.read( &got_time, sizeof(unsigned long) );
        unsigned long end_time = micros();

        // Spew it
        Serial.print(F("Sent "));
        Serial.print(start_time);
        Serial.print(F(", Got response "));
        Serial.print(got_time);
        Serial.print(F(", Round-trip delay "));
        Serial.print(end_time-start_time);
        Serial.println(F(" microseconds"));
    }

    // Try again 1s later
    delay(1000);
  }

/****************** Pong Back Role ***************************/

  if ( role == 0 )
  {
    unsigned long got_time;

    if( radio.available()){
                                                                    // Variable for the received timestamp
      while (radio.available()) {                                   // While there is data ready
        radio.read( &got_time, sizeof(unsigned long) );             // Get the payload
      }

      radio.stopListening();                                        // First, stop listening so we can talk   
      radio.write( &got_time, sizeof(unsigned long) );              // Send the final one back.      
      radio.startListening();                                       // Now, resume listening so we catch the next packets.     
      Serial.print(F("Sent response "));
      Serial.println(got_time);  
   }
 }

/****************** Change Roles via Serial Commands ***************************/

  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'T' && role == 0 ){      
      Serial.println(F("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK"));
      role = 1;                  // Become the primary transmitter (ping out)

   }else
    if ( c == 'R' && role == 1 ){
      Serial.println(F("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK"));      
       role = 0;                // Become the primary receiver (pong back)
       radio.startListening();

    }
  }

} // Loop

Rx (from nano to RPi4 is still very fine).
Here is what I get with the serial monitor:

14:56:03.932 -> Sent 173536544, Got response 173536544, Round-trip delay 60964 microseconds 14:56:04.937 -> Now sending 14:56:05.004 -> Sent 174599412, Got response 174599412, Round-trip delay 74000 microseconds 14:56:06.002 -> Now sending 14:56:06.072 -> Sent 175675304, Got response 175675304, Round-trip delay 53764 microseconds

And I was also able to Tx from my RPi4 (well partially).

15:33:02.068 -> *** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK 15:33:10.610 -> Sent response 3401575 15:33:11.648 -> Sent response 3402616 15:33:12.677 -> Sent response 3403656 15:33:13.744 -> Sent response 3404697 15:33:14.778 -> Sent response 3405737

The nano received my data from my RPi4. But the ack is not working. The Tx function is still returning false : result = nrf.send(buffer, send_only=1). Probably why I can't transmit using network.write(...) as well.

I took a look at my signal integrity at the scope and it looks alright with the vcc to gnd directly on the transceiver, did not see any suspect drop during transmission with a falling edge trigger at 3.2V... The SPI bus is also looking pretty good.

Really wonder what the heck is the problem with that RPi4...

HW info: with 2 nano I can get 100 meters range on both sides (Tx and Rx). Tried to wrap the transceivers into a grounded Faraday cage. Got much better range, I can get up to 250 meters.

...But still... not able to Tx properly with the RPi4... As far as I can see it is not related to the signal integrity... It has to be with the RPi4... But can't pinpoint the heck it is... I'm about to change the design and use another nano connected to the serial of the RPi4... I tried it and it works pretty well...

Any idea with that RPi4 that I could try?

Thanks anyhow...

2bndy5 commented 3 years ago

I have a dev branch that has the examples modified for this library's new examples. The changes for that dev branch are listed in the pending PR. The dev branch is mostly an update to the API to be more familiar with this lib's API. If you're interested in testing that branch (worked last time I tried it), you could

pip3 install git+https://github.com/2bndy5/CircuitPython_nRF24L01@dev

docs for that branch are at hosted at rtfd.io

I've been slow to merge and release that dev branch because it breaks backward compatibility...

The nano received my data from my RPi4. But the ack is not working. The Tx function is still returning false

This sounds like there isn't enough current going to the nRF24 module's VCC pin (specifically a common problem when using the PA/LNA modules)

jsvoel commented 3 years ago

Hi, I had the same problem, RPi4 can receive but can't send using a PA+LNA module. I didn't try sending from the Pi directly, but Ack / PayloadAck never arrived at my Microcontroller, while the same python code worked on a RPi Zero.

The main difference was now, I wanted to use the 3.3V of the Pi4 directly.

When I switched that for the module that I confirmed working with the PiZero, using one of those voltage regulator adapters, the problem vanished immediatelly. Now I connected that same module again directly to the Pi4 and it's 3.3V rail, that is also working.

However, the module that doesn't work has pretty long cables, about 50 cm. And they are quite thin, so I doubled up the ones carrying power and added a 22uF condensator, now it's working. I am using the current released library on the RPi and a cut down spin-off (thanks for all the great work) on my STM8 microcontroller, but that shouldn't matter.

It was a power issue. Note that the RPi should be able to supply about 1 Amp of power, which is shared with the processor. So drawing 200-300 milliamps when sending with a PA+LNA should be no problem at all. you just got to watch your cables and other devices on the RPi.

long_cables long_cables_closeup

yes, I should have used a small pcb, but at first it was just a few 1-to-1 connections, right..

2bndy5 commented 3 years ago

@jsvoel someone else helpfully advised me to lower the SPI frequency when using long cables... This proved very useful

2bndy5 commented 3 years ago

@PLLefebvre You said that:

The simple action of touching the transceiver was affecting the transmission performances.

If touching your transceiver improved performance, than it is likely that your transceiver is missing a vital capacitor (which is common for cheaply made clones/counterfeits). Have a look at this article I found about missing on-board capacitors.