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)