0

I’m trying to set up wireless communication using two NRF24L01 modules. I’m using a Raspberry Pi 4 Model B as the receiver using the pyRF24 Library and a Raspberry Pi Pico with MicroPython as the sender.

I tried setup with the Raspberry Pi 4 and a Raspberry Pi Zero (both with NRF24L01) first and it worked perfectly - I was able to send and receive data using the mentioned pyRF24 Library and the example programs ran without any issues.

Now, I replaced the Raspberry Pi Zero with the Raspberry Pi Pico. For the Pico, I tried several MicroPython libraries (e.g., from the official micropython GitHub repository) and double-checked the pin connections multiple times:

MISO: GP4
MOSI: GP7
SCK: GP6
CSN: GP15
CE: GP14

Now, the communication no longer works. There are no error messages, but no data is received, regardless of whether the Pico is set as sender or receiver. I will add the testing code for the Pi 4 (based on the first example in the pyRF24 library and the Pico (tried to adapt the same example for the micropython-library) at the end of this text.

What might cause this? Am I using the micropython library wrong? Are there any specifics to using the NRF24L01 with MicroPython on the Pico that I should be aware of? How to further debug this?

Code for Raspberry Pi 4 Model B, based on PyRF24 Documentation:

"""
Simple example of using the RF24 class.
See documentation at https://nRF24.github.io/pyRF24
"""
import time
import struct
from pyrf24 import RF24, RF24_PA_MAX, RF24_DRIVER
print(__file__) # print example name
########### USER CONFIGURATION ###########
# CE Pin uses GPIO number with RPi and SPIDEV drivers, other drivers use
# their own pin numbering
# CS Pin corresponds the SPI bus number at /dev/spidev<a>.<b>
# ie: radio = RF24(<ce_pin>, <a>*10+<b>)
# where CS pin for /dev/spidev1.0 is 10, /dev/spidev1.1 is 11 etc...
CSN_PIN = 0 # aka CE0 on SPI bus 0: /dev/spidev0.0
if RF24_DRIVER == "MRAA":
 CE_PIN = 15 # for GPIO22
elif RF24_DRIVER == "wiringPi":
 CE_PIN = 3 # for GPIO22
else:
 CE_PIN = 22
radio = RF24(CE_PIN, CSN_PIN)
# using the python keyword global is bad practice. Instead we'll use a 1 item
# list to store our float number for the payloads sent
payload = [0.0]
# For this example, we will use different addresses
# An address need to be a buffer protocol object (bytearray)
address = [b"1Node", b"2Node"]
# It is very helpful to think of an address as a path instead of as
# an identifying device destination
# to use different addresses on a pair of radios, we need a variable to
# uniquely identify which address this radio will use to transmit
# 0 uses address[0] to transmit, 1 uses address[1] to transmit
radio_number = bool(
 int(input("Which radio is this? Enter '0' or '1'. Defaults to '0' ") or 0)
)
# initialize the nRF24L01 on the spi bus
if not radio.begin():
 raise OSError("nRF24L01 hardware isn't responding")
# set the Power Amplifier level to -12 dBm since this test example is
# usually run with nRF24L01 transceivers in close proximity of each other
radio.set_pa_level(RF24_PA_MAX) # RF24_PA_MAX is default
# set TX address of RX node (uses pipe 0)
radio.stop_listening(address[radio_number]) # enter inactive TX mode
# set RX address of TX node into an RX pipe
radio.open_rx_pipe(1, address[not radio_number]) # using pipe 1
# To save time during transmission, we'll set the payload size to be only what
# we need. A float value occupies 4 bytes in memory using struct.calcsize()
# "<f" means a little endian unsigned float
radio.payload_size = struct.calcsize("<f")
# for debugging
# radio.print_details()
# or for human readable data
# radio.print_pretty_details()
def master(count: int = 5): # count = 5 will only transmit 5 packets
 """Transmits an incrementing float every second"""
 radio.listen = False # ensures the nRF24L01 is in TX mode
 while count:
 # use struct.pack() to pack your data into a usable payload
 # into a usable payload
 buffer = struct.pack("<f", payload[0])
 # "<f" means a single little endian (4 byte) float value.
 start_timer = time.monotonic_ns() # start timer
 result = radio.write(buffer)
 end_timer = time.monotonic_ns() # end timer
 if not result:
 print("Transmission failed or timed out")
 else:
 print(
 "Transmission successful! Time to Transmit:",
 f"{(end_timer - start_timer) / 1000} us. Sent: {payload[0]}",
 )
 payload[0] += 0.01
 time.sleep(1)
 count -= 1
 # recommended behavior is to keep radio in TX mode while idle
 radio.listen = False # enter inactive TX mode
def slave(timeout: int = 6):
 """Polls the radio and prints the received value. This method expires
 after 6 seconds of no received transmission."""
 radio.listen = True # put radio into RX mode
 start = time.monotonic()
 while (time.monotonic() - start) < timeout:
 has_payload, pipe_number = radio.available_pipe()
 if has_payload:
 length = radio.payload_size # grab the payload length
 # fetch 1 payload from RX FIFO
 received = radio.read(length)
 # expecting a little endian float, thus the format string "<f"
 # received[:4] truncates padded 0s in case dynamic payloads are disabled
 payload[0] = struct.unpack("<f", received[:4])[0]
 # print details about the received packet
 print(f"Received {length} bytes on pipe {pipe_number}: {payload[0]}")
 start = time.monotonic() # reset the timeout timer
 # recommended behavior is to keep radio in TX mode while idle
 radio.listen = False # enter inactive TX mode
if radio_number == 1:
 slave()
else:
 master()

Code for Raspberry Pi Pico, using the micropython nrf24l01.py library:

from machine import Pin, SPI
import time, struct
from nrf24l01 import NRF24L01
# SPI & Pins
spi = SPI(0, baudrate=4000000, polarity=0, phase=0, sck=Pin(6), mosi=Pin(7), miso=Pin(4))
csn = Pin(15, mode=Pin.OUT)
ce = Pin(14, mode=Pin.OUT)
nrf = NRF24L01(spi, csn, ce, payload_size=4)
pipes = (b"1Node", b"2Node")
# Select role: 0 = sender, 1 = reciever
ROLE = 0
if ROLE == 0: # Master / Sender
 print("Pipe to send: ", pipes[0])
 print("Pipe to recieve: ", pipes[1])
 nrf.open_tx_pipe(pipes[0])
 nrf.open_rx_pipe(1, pipes[1])
 nrf.stop_listening()
 value = 0.0
 while True:
 buf = struct.pack("<f", value)
 nrf.send(buf)
 print("Sent:", value)
 value += 0.01
 time.sleep(1)
else: # Slave / Reciever
 print("Pipe to send: ", pipes[1])
 print("Pipe to recieve: ", pipes[0])
 nrf.open_tx_pipe(pipes[1])
 nrf.open_rx_pipe(1, pipes[0])
 nrf.start_listening()
 while True:
 if nrf.any():
 buf = nrf.recv()
 value = struct.unpack("<f", buf)[0]
 print("Received:", value)
jsotola
7261 gold badge9 silver badges13 bronze badges
asked Aug 14 at 12:12

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.