[Python] NRF24L01 communication between Raspberry Pi 4 and Raspberry Pi Pico (MicroPython) not...

Discussão em 'Python' iniciado por Stack, Agosto 13, 2025.

  1. Stack

    Stack Membro Participativo

    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.

    Does anyone have any idea what might cause this? Are there any specifics to using the NRF24L01 with MicroPython on the Pico that I should be aware of? Any tips on how to further debug this would be highly appreciated!

    Thanks in advance!

    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)

    Continue reading...

Compartilhe esta Página