NRF24L01 with a Pi Pico

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
emii
Posts: 3
Joined: Sun Feb 28, 2021 2:41 pm

NRF24L01 with a Pi Pico

Post by emii » Sun Feb 28, 2021 6:25 pm

I recently bought some nRF24s with the intention of talking to some Pi Picos in micropython. I did some digging and found the drivers
https://github.com/micropython/micropyt ... s/nrf24l01
and
https://github.com/peterhinch/micropython-radio/
but if I'm honest I don't really know how to use them very well. I have a basic program running the first drivers but I'm getting a "send failed" - the pin assigments are correct so I'm unsure what's causing this.
Does anyone have any code examples on how to use these libraries? The examples provided seem to all be for the PyBoard, esp32 or micro:bit, so I'm a little confused.
Sorry for the kinda basic question, I'm still quite new to this sort of stuff and I've never used SPI before. Thanks in advance!

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: NRF24L01 with a Pi Pico

Post by pythoncoder » Mon Mar 01, 2021 5:23 pm

I suggest you tell us exactly how these are wired up and what test program you're running. You need to have a unit running as receiver before starting the transmitter: unlike many radios the NRF24l01, when transmitting, automatically checks for successful reception.
Peter Hinch
Index to my micropython libraries.

thetestdoctor
Posts: 5
Joined: Fri Feb 26, 2021 11:26 pm
Location: Scotland

Re: NRF24L01 with a Pi Pico

Post by thetestdoctor » Mon Mar 01, 2021 9:30 pm

OK I managed to get this working between an ESP32 & a Pico with code in the links you provided (I didn't try a Pico to Pico) but it should work.

In nrf24l01_test.py change the references from usys to sys. For the Esp32 & Pico the module is sys (this is a bit confusing as the author changed from sys to usys, change it back).

Next wire the Pico to the nrf module as shown in the Python SDK section 3.7. SPI.
Note confusingly where it says Pin it actually means GPIO. I used.

CE to GPIO14
CSN to GPIO15
MISO to GPIO4
MOSI to GPIO7
SCK to GPIO6
Connect GND & 3V3OUT to the nrf device.

Modify the sys.platform check at the start of the test program
Note the use of "spi":0,

Code: Select all

elif sys.platform == "rp2":
    cfg = {"spi": 0, "miso": 4, "mosi": 7, "sck": 6, "csn": 15, "ce": 14}
else:
    raise ValueError("Unsupported platform {}".format(sys.platform))
You must keep all the parameters the same for the master & slave (channel, speed, pipes etc) or the devices wont communicate. Make one device a slave & the other a master by
adding slave() & master on the last line of nrf24l01_test.py

I have used these devices with Arduino's & Rpi the results aren't great, they are difficult to wire, fairly unreliable, can only send up-to 32 bits (the more bits you send in a packet the worse they are) and have a very limited range, even outdoors expect < 10meters. There is also a reported problem of poor power supply regulation, I soldered a 4.7uF across the power pins . So good luck.

thetestdoctor
Posts: 5
Joined: Fri Feb 26, 2021 11:26 pm
Location: Scotland

Re: NRF24L01 with a Pi Pico

Post by thetestdoctor » Tue Mar 02, 2021 11:31 am

Just a quick update. I didn't fully check the setup last night. Between two Esp32 it works fine. However for Esp32 & Pico, with Pico as the Master & Esp32 as Slave I get 5/16 passes,with the Master/Slave swapped it doesn't work at all.

I may take a further look, but have previously spent many frustrating hours & IMHO you're better off using a microcontroller with a 'proper' wifi module, which are easier to use, have more flexibility (mqtt support) and more reliable. You could connect an Esp-01 to a Pico but you're better off simply using an Esp32 or waiting for the Adafruit/Arduino Rp2040 wifi variants when they appear. If as you say you haven't used SPI before these devices are not ones to start with.

I did get it working reliably with the Pico as Master by using an external power supply for the nrf24l01 rather than the Pico 3V3, Pico as a slave still not working. Probably leave it there as I have all but given up using these devices for any projects.
Last edited by thetestdoctor on Tue Mar 02, 2021 1:58 pm, edited 1 time in total.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: NRF24L01 with a Pi Pico

Post by pythoncoder » Tue Mar 02, 2021 1:18 pm

thetestdoctor wrote:
Mon Mar 01, 2021 9:30 pm
...
I have used these devices with Arduino's & Rpi the results aren't great, they are difficult to wire, fairly unreliable, can only send up-to 32 bits (the more bits you send in a packet the worse they are) and have a very limited range, even outdoors expect < 10meters. There is also a reported problem of poor power supply regulation, I soldered a 4.7uF across the power pins . So good luck.
The range varies greatly with the quality of manufacture. I have disarded Chinese units that could barely manage 2 meters in the same room. Good ones (e.g. from Adafruit) have a similar range to WiFi: a great deal better than 10 metres out of doors. I have a project with four Pyboards communicating with these radios. The system has been running 24/7 for several years.

In projects like this one, they are energy efficient: the Pyboards wake from deep sleep, use the radio to exchange messages, and go back to sleep. I'm pretty sure that connecting to, and using, a WiFi network would take substantially more energy. However, whether I'd use them in a new project is debatable.
Peter Hinch
Index to my micropython libraries.

emii
Posts: 3
Joined: Sun Feb 28, 2021 2:41 pm

Re: NRF24L01 with a Pi Pico

Post by emii » Tue Mar 02, 2021 1:41 pm

Thank you so much for the help! I'll look into the alternatives you mentioned and try those instead.

thetestdoctor
Posts: 5
Joined: Fri Feb 26, 2021 11:26 pm
Location: Scotland

Re: NRF24L01 with a Pi Pico

Post by thetestdoctor » Tue Mar 02, 2021 2:05 pm

I brought a batch of 5, blew one up the other 4 must be as you say discarded Chinese ones, BTW I was being generous when I said 10m it was probably 2-3m in the garden. Point taken about low power usage & new projects. My experience has been hours of frustration with them.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: NRF24L01 with a Pi Pico

Post by pythoncoder » Wed Mar 03, 2021 10:26 am

If you decide to use these, do pay a bit more for quality hardware. It will save a lot of wasted time. I incorrectly mentioned Adafruit: they don't make these. The units I use are from Sparkfun: https://www.sparkfun.com/products/691 and https://www.sparkfun.com/products/705.

The other factor to bear in mind is that WiFi, though superficially easy, isn't if you care about reliability. No radio communication is. The signal can be lost by moving out of range, or it can be obliterated by interference. See my notes on the subject. With @kevinkk525 I developed a resilient MQTT solution which copes with WiFi and broker outages. It is considerably more involved than the official solutions, which are rather fragile.
Peter Hinch
Index to my micropython libraries.

dnts
Posts: 2
Joined: Sun Apr 04, 2021 7:25 am

Re: NRF24L01 with a Pi Pico

Post by dnts » Sun Apr 04, 2021 9:27 am

Hi all,
I need some help to get a pico-pico communicate with the NRF24L01.
The connections are:
CE to GPIO14
CSN to GPIO15
MISO to GPIO4
MOSI to GPIO7
SCK to GPIO6
as mentioned above.

The code i use for master:

Code: Select all

"""Test for nrf24l01 module.  Portable between MicroPython targets."""

import sys
import ustruct as struct
import utime
from machine import Pin, SPI
from nrf24l01 import NRF24L01
from micropython import const

if sys.platform == "pyboard":
    cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"}
elif sys.platform == "esp8266":  # Hardware SPI
    cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5}
elif sys.platform == "esp32":  # Software SPI
    cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27}
elif sys.platform == "rp2":   
    cfg = {"spi": 0, "miso": 4, "mosi": 7, "sck": 6, "csn": 15, "ce": 14}  
else:
    raise ValueError("Unsupported platform {}".format(usys.platform))

# Addresses are in little-endian format. They correspond to big-endian
# 0xf0f0f0f0e1, 0xf0f0f0f0d2
pipes = (b"\xe1\xf0\xf0\xf0\xf0", b"\xd2\xf0\xf0\xf0\xf0")

pin = machine.Pin(25, machine.Pin.OUT)

def master():
    csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
    ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
    if cfg["spi"] == -1:
        spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
        nrf = NRF24L01(spi, csn, ce, payload_size=8)
    else:
        nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, channel=100, payload_size=32)

    nrf.stop_listening()
    
    nrf.open_tx_pipe(pipes[0])

    print("NRF24L01 master mode, sending ...")

    while True:
        millis = utime.ticks_ms()
        print("sending ", millis)
        pin.value(1)
        try:
            nrf.send(struct.pack("i", millis))
        except OSError:
            print("OS error")
            pass

        pin.value(0)
                    
        # delay then loop
        utime.sleep_ms(500)

print("NRF24L01 test module loaded")
print("NRF24L01 pinout for test:")
print("    CE on", cfg["ce"])
print("    CSN on", cfg["csn"])
print("    SCK on", cfg["sck"])
print("    MISO on", cfg["miso"])
print("    MOSI on", cfg["mosi"])
print("run nrf24l01test.slave() on slave, then nrf24l01test.master() on master")

print("This is master")
while True:
    master()
The code for slave:

Code: Select all

"""Test for nrf24l01 module.  Portable between MicroPython targets."""

import sys
import ustruct as struct
import utime
from machine import Pin, SPI
from nrf24l01 import NRF24L01
from micropython import const

if sys.platform == "pyboard":
    cfg = {"spi": 2, "miso": "Y7", "mosi": "Y8", "sck": "Y6", "csn": "Y5", "ce": "Y4"}
elif sys.platform == "esp8266":  # Hardware SPI
    cfg = {"spi": 1, "miso": 12, "mosi": 13, "sck": 14, "csn": 4, "ce": 5}
elif sys.platform == "esp32":  # Software SPI
    cfg = {"spi": -1, "miso": 32, "mosi": 33, "sck": 25, "csn": 26, "ce": 27}
elif sys.platform == "rp2":   
    cfg = {"spi": 0, "miso": 4, "mosi": 7, "sck": 6, "csn": 15, "ce": 14}      
else:
    raise ValueError("Unsupported platform {}".format(usys.platform))

pin = machine.Pin(25, machine.Pin.OUT)

# Addresses are in little-endian format. They correspond to big-endian
# 0xf0f0f0f0e1, 0xf0f0f0f0d2
pipes = (b"\xe1\xf0\xf0\xf0\xf0", b"\xd2\xf0\xf0\xf0\xf0")

def slave():
    csn = Pin(cfg["csn"], mode=Pin.OUT, value=1)
    ce = Pin(cfg["ce"], mode=Pin.OUT, value=0)
    if cfg["spi"] == -1:
        spi = SPI(-1, sck=Pin(cfg["sck"]), mosi=Pin(cfg["mosi"]), miso=Pin(cfg["miso"]))
        nrf = NRF24L01(spi, csn, ce, payload_size=8)
    else:
        nrf = NRF24L01(SPI(cfg["spi"]), csn, ce, channel=100, payload_size=32)

    nrf.open_rx_pipe(1, pipes[0])
    
    nrf.start_listening()

    print("NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)")
    
    pin.value(1)
    while True:
        utime.sleep_ms(const(250))
        print("Still waiting")
        
        if nrf.any():
            while nrf.any():
                buf = nrf.recv()
                millis = struct.unpack("i", buf)
                print("received", millis)
                pin.value(0)

print("NRF24L01 test module loaded")
print("NRF24L01 pinout for test:")
print("    CE on", cfg["ce"])
print("    CSN on", cfg["csn"])
print("    SCK on", cfg["sck"])
print("    MISO on", cfg["miso"])
print("    MOSI on", cfg["mosi"])
print("run nrf24l01test.slave() on slave, then nrf24l01test.master() on master")
print("This is slave")

while True:
    slave()
simplified versions of the nrf24l01test.py file.

I always get an OS error.
I also tried the nrf24l01test.py without any changes to channel or payload_size. I get a failed, response timed out message

Is there something obvious that i am missing? Any help?
Thanks.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: NRF24L01 with a Pi Pico

Post by Roberthh » Sun Apr 04, 2021 9:50 am

OSError on which device and code line?

Post Reply