1

I am trying to implement a wireless communication between RpiZero and RpiPico through NRF24l01 modules.

Pico is the receiver, and Zero is the transmitter. I have successfully started the Pico listening using the test file of MicroPython's library for nrf24. I started also the Zero to send measurement using also the test python file of the library for the sender.

I think that I am not configuring well the addresses. Could you please help me?

RpiZero Code:

import argparse
from datetime import datetime
from random import normalvariate
import struct
import sys
import time
import traceback

import pigpio
from nrf24 import *

#
# A simple NRF24L sender that connects to a PIGPIO instance on a hostname and port, default "localhost" and 8888, and
# starts sending data on the address specified.  Use the companion program "simple-receiver.py" to receive the data
# from it on a different Raspberry Pi.
#
if __name__ == "__main__":
    print("Python NRF24 Simple Sender Example.")

    # Parse command line argument.
    parser = argparse.ArgumentParser(prog="simple-sender.py", description="Simple NRF24 Sender Example.")
    parser.add_argument('-n', '--hostname', type=str, default='localhost',
                        help="Hostname for the Raspberry running the pigpio daemon.")
    parser.add_argument('-p', '--port', type=int, default=8888, help="Port number of the pigpio daemon.")
    parser.add_argument('address', type=str, nargs='?', default='1SNSR',
                        help="Address to send to (3 to 5 ASCII characters).")

    args = parser.parse_args()
    hostname = args.hostname
    port = args.port
    # address = args.address
    address = b"\xf0\xf0\xf0\xf0\xf0"

    if not (2 < len(address) < 6):
        print(f'Invalid address {address}. Addresses must be 3 to 5 ASCII characters.')
        sys.exit(1)

    # Connect to pigpiod
    print(f'Connecting to GPIO daemon on {hostname}:{port} ...')
    pi = pigpio.pi(hostname, port)
    if not pi.connected:
        print("Not connected to Raspberry Pi ... goodbye.")
        sys.exit()

    # Create NRF24 object.
    # PLEASE NOTE: PA level is set to MIN, because test sender/receivers are often close to each other, and then MIN works better.
    nrf = NRF24(pi, ce=25, payload_size=8, channel=125, data_rate=RF24_DATA_RATE.RATE_250KBPS, pa_level=RF24_PA.LOW)
    nrf.set_address_bytes(len(address))
    nrf.open_writing_pipe(address)

    # Display the content of NRF24L01 device registers.
    nrf.show_registers()

    try:
        print(f'Send to {address}')
        count = 0
        while True:

            # Emulate that we read temperature and humidity from a sensor, for example
            # a DHT22 sensor.  Add a little random variation so we can see that values
            # sent/received fluctuate a bit.
            temperature = normalvariate(23.0, 0.5)
            humidity = normalvariate(62.0, 0.5)
            print(f'Sensor values: temperature={temperature}, humidity={humidity}')

            # Pack temperature and humidity into a byte buffer (payload) using a protocol
            # signature of 0x01 so that the receiver knows that the bytes we are sending
            # are a temperature and a humidity (see "simple-receiver.py").
            payload = struct.pack("<Bff", 0x01, temperature, humidity)

            # Send the payload to the address specified above.
            nrf.reset_packages_lost()
            nrf.send(payload)
            try:
                nrf.wait_until_sent()
            except TimeoutError:
                print('Timeout waiting for transmission to complete.')
                # Wait 10 seconds before sending the next reading.
                time.sleep(10)
                continue

            if nrf.get_packages_lost() == 0:
                print(f"Success: lost={nrf.get_packages_lost()}, retries={nrf.get_retries()}")
            else:
                print(f"Error: lost={nrf.get_packages_lost()}, retries={nrf.get_retries()}")

            # Wait 10 seconds before sending the next reading.
            time.sleep(10)
    except:
        traceback.print_exc()
        nrf.power_down()
        pi.stop()

RpiPico code:

"""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

# Slave pause between receiving data and checking for further packets.
_RX_POLL_DELAY = const(15)
# Slave pauses an additional _SLAVE_SEND_DELAY ms after receiving data and before
# transmitting to allow the (remote) master time to get into receive mode. The
# master may be a slow device. Value tested with Pyboard, ESP32 and ESP8266.
_SLAVE_SEND_DELAY = const(10)

if sys.platform == "rp2":  # PI PICO
    cfg = {"spi": 1, "miso": 8, "mosi": 11, "sck": 10, "csn": 14, "ce": 17}

else:
    raise ValueError("Unsupported platform {}".format(sys.platform))

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

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, payload_size=8, channel=125)

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

    print("NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)")

    while True:
        if nrf.any():
            while nrf.any():
                buf = nrf.recv()
                millis, led_state = struct.unpack("ii", buf)
                print("received:", millis, led_state)
                for led in leds:
                    if led_state & 1:
                        led.on()
                    else:
                        led.off()
                    led_state >>= 1
                utime.sleep_ms(_RX_POLL_DELAY)

            # Give master time to get into receive mode.
            utime.sleep_ms(_SLAVE_SEND_DELAY)
            nrf.stop_listening()
            try:
                nrf.send(struct.pack("i", millis))
            except OSError:
                pass
            print("sent response")
            nrf.start_listening()


try:
    import pyb

    leds = [pyb.LED(i + 1) for i in range(4)]
except:
    leds = []

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")
slave()

Output of RpiZero:

Python NRF24 Simple Sender Example.
Connecting to GPIO daemon on localhost:8888 ...
Registers:
----------
CONFIG: (0x00) => RX_DR IRQ, TX_DS IRQ, MAX_RT IRQ, CRC off, CRC 1 byte, Power down, TX
EN_AA: (0x00) => P0:no ACK P1:no ACK P2:no ACK P3:no ACK P4:no ACK P5:no ACK
EN_RXADDR: (0x00) => P0:off P1:off P2:off P3:off P4:off P5:off
SETUP_AW: (0x00) => address width bytes invalid
SETUP_RETR: (0x00) => retry delay 250 us, retries 0
RF_CH: (0x00) => channel=0
RF_SETUP: (0x00) => no continuous carrier, no force PLL lock, 1 Mbps, -18 dBm
STATUS: (0x00) => no RX data, no TX, TX retries ok, pipe 0 data, TX FIFO not full
OBSERVE_TX: (0x00) => lost packets 0, retries 0
RPD: (0x00) => received power detector 0
RX ADDR_PX: P0=0x0000000000 P1=0x0000000000 P2=0x00 P3=0x00 P4=0x00 P5=0x00
TX_ADDR: 0x0000000000
RX_PW_PX: P0=00 P1=00 P2=00 P3=00 P4=00 P5=00
FIFO_STATUS: (0x00) => TX reuse not set, TX FIFO has data, RX FIFO has data
DYNPD: (0x00) => P0:off P1:off P2:off P3:off P4:off P5:off
FEATURE: (0x00) => Dynamic payload off, ACK payload off, W_TX_PAYLOAD_NOACK off
----------
Send to b'\xf0\xf0\xf0\xf0\xf0'
Sensor values: temperature=22.924126949489008, humidity=60.99676182811973
Timeout waiting for transmission to complete.

Output of RpiPico:

NRF24L01 test module loaded
NRF24L01 pinout for test:  
    CE on 17
    CSN on 14
    SCK on 10
    MISO on 8
    MOSI on 11
run nrf24l01test.slave() on slave, then nrf24l01test.master() on master
NRF24L01 slave mode, waiting for packets... (ctrl-C to stop)

1 Answer 1

0

Check your Pico SPI connections and GPIO.

I thought MISO and MOSI were swapped. Looking again they seem correct.

4
  • Thank you for your answer. So, you propose to swap MOSI and MISO as well as SCK and CSN?
    – Antifa
    Commented Sep 29, 2022 at 9:49
  • Now, I get, OSError: nRF24L01+ Hardware not responding Please for your assistance
    – Antifa
    Commented Sep 29, 2022 at 12:19
  • My answer is wrong. I was wrong about MOSI and MISO. They were correct as you had.them. SCK is ok. CSN may be okay.
    – joan
    Commented Sep 29, 2022 at 14:42
  • Thank you. Do you know, how should I set the address between Pico and Zero?
    – Antifa
    Commented Sep 30, 2022 at 10:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.