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
    Sep 29, 2022 at 9:49
  • Now, I get, OSError: nRF24L01+ Hardware not responding Please for your assistance
    – Antifa
    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
    Sep 29, 2022 at 14:42
  • Thank you. Do you know, how should I set the address between Pico and Zero?
    – Antifa
    Sep 30, 2022 at 10:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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