INTRODUCTION

ESP8266 & NR24L01

Having two or more MCU boards be able to communicate with each other wirelessly over a distance opens lots of possibilities like remotely monitoring sensor data, controlling robots, home automation and the list goes on. And when it comes down to having inexpensive yet reliable 2-way RF solutions, no one does a better job than nRF24L01+ transceiver module from Nordic Semiconductor.nRF24L01+ (plus) transceiver module can often be obtained online for less than two dollars, making it one of the most inexpensive data communication options that you can get. And best of all, these modules are super tiny, allowing you to incorporate a wireless interface into almost any project. I will also post some tutorial links where I have interfaced NRF24L01 with other microcontrollers. If you have any queries about it, ask in the comments and I will resolve it.

Hardware Introduction 

Raspberry Pi Pico Overview 

Raspberry Pi Pico is the debut microcontroller-class board from Raspberry Pi. Built around our RP2040 silicon platform, Pico brings our signature values of high performance, low cost, and ease of use to the microcontroller space. 

With a large on-chip memory, symmetric dual-core processor complex, deterministic bus fabric, and rich peripheral set augmented with our unique Programmable I/O (PIO) subsystem, RP2040 provides professional users

with unrivalled power and flexibility. With detailed documentation, a polished MicroPython port, and a UF2 bootloader in ROM, it has the lowest possible barrier to entry for beginner and hobbyist users. 

RP2040 is manufactured on a modern 40nm process node, delivering high performance, low dynamic power consumption, and low leakage, with a variety of low-power modes to support extended-duration operation on battery power. 

Raspberry Pi Pico pairs RP2040 with 2MB of Flash memory, and a power supply chip supporting input voltages from 1.8-5.5V. It provides 26 GPIO pins, three of which can function as analogue inputs, on 0.1”-pitch through-hole pads with castellated edges. Raspberry Pi Pico is available as an individual unit, or in 600-unit reels for automated assembly. 

Following are the key features: 

● RP2040 microcontroller with 2MByte Flash 

● Micro-USB B port for power and data (and for reprogramming the Flash) ● 40 pin 21×51 ‘DIP’ style 1mm thick PCB with 0.1″ through-hole pins also with edge castellations 

➢ Exposes 26 multi-function 3.3V General Purpose I/O (GPIO) 

➢ 23 GPIO are digital-only and 3 are ADC capable 

➢ Can be surface-mounted as a module. 

● 3-pin ARM Serial Wire Debug (SWD) port . 

● Simple yet highly flexible power supply architecture. 

➢ Various options for easily powering the unit from micro-USB, external supplies or batteries. 

● High quality, low cost, high availability. 

● Comprehensive SDK, software examples and documentation. 

Key features RP2040 are: 

• Dual-core cortex M0+ at up to 133MHz 

➢ On-chip PLL allows variable core frequency 

• 264kByte multi-bank high performance SRAM 

• External Quad-SPI Flash with eXecute In Place and 16kByte on-chip cache • High performance full-crossbar bus fabric Raspberry Pi Pico Datasheet

 • On-board USB1.1 (device or host) 

• 30 multi-function General Purpose IO (4 can be used for ADC) ➢ 1.8-3.3V IO Voltage (NOTE Pico IO voltage is fixed at 3.3V) 

• 12-bit 500ksps Analogue to Digital Converter (ADC) 

• Various digital peripherals 

➢ 2 × UART, 2 × I2C, 2 × SPI, 16 × PWM channels 

➢ 1 × Timer with 4 alarms, 1 × Real Time Counter

• 2 × Programmable IO (PIO) blocks, 8 state machines total ➢ Flexible, user-programmable high-speed IO ➢ Can emulate interfaces such as SD Card and VGA

Pin Diagram: 

Figure 1. The pinout of the Raspberry Pi Pico Rev3 board.

Pico Specifications: 

Interfacing: 26 GPIO pins, including 3 analogue inputs
CPU: Dual-core Arm Cortex-M0+ @ 133MHz
Flash Storage: 2MB
Memory: 264 KB on-chip SRAM; 2MB on-board QSPI Flash
GIPO: 26 × multi-function GPIO pins 2 × SPI, 2 × I2C, 2 × UART, 3 × 12-bit ADC, 8 × Programmable I/O (PIO) state machines for custom peripheral support Castellated module allows soldering directly to carrier boards
Input power: 1.8–5.5V DC

Operating temperature: -20°C to +85°C 

USB port: Micro USB 

Dimensions: 51x21mm 

Production lifetime: Raspberry Pi Pico will remain in production until at least January 2028

Raspberry Pi Pico pinouts 

GPIO Pins on Raspberry Pi Pico 

GPIO29: IP Used in ADC mode (ADC3) to measure VSYS/3
GPIO25: OP Connected to user LED
GPIO24: IP VBUS sense – high if VBUS is present, else low
GPIO23: OP Controls the on-board SMPS Power Save pin

ADC or Analog to Digital Converter Pins

ADC Pin GPIO Pins
ADC0 GP26
ADC1 GP27
ADC2 GP28

I2C Pins on Raspberry Pi Pico 

I2C is a two-wire, bi-directional serial bus that provides an easy and quick method for transmission over a short distance between I2C enabled devices. The Raspberry Pi Pico comes with two I2C controllers, both I2C controllers are accessible through GPIO pins of Raspberry Pi Pico. 

I2C Controller GPIO Pins 

I2C0 SDA GP0/GP4/GP8/GP12/GP16/GP20 

I2C0 SCL GP1/GP5/GP9/GP13/GP17/GP21 

I2C1 SDA GP2/GP6/GP10/GP14/GP18/GP26 

I2C1 SCL GP3/GP7/GP11/GP15/GP19/GP27 

SPI Pins on Raspberry Pi Pico 

Serial Peripheral Interface (SPI) is an interface bus that is used to transfer data between the microcontroller and SPI-enabled devices. Raspberry Pi Pico supports two SPI interfaces that are accessible through GPIO pins of the board. 

SPI Controller                                           GPIO Pins
SPI0_RX                                                GP0/GP4/GP16
SPI0_TX                                                GP3/GP7/GP19
SPI0_CLK                                              GP2/GP6/GP18
SPI0_CSn                                              GP1/GP5/GP17
SPI1_RX                                                GP8/GP12

SPI1_TX            GP11/GP15 

SPI1_CLK          GP10/GP14 

SPI1_CSn          GP9/GP13

UART Pins on Pico 

The Raspberry Pi Pico also contains two identical UART peripherals. UART (universal asynchronous receiver-transmitter) pins are used for asynchronous serial communication between the micro-controller and UART devices or other microcontrollers. 

UART Pins            GPIO Pins
UART0-TX                 GP0/GP12/GP16
UART0-RX              GP1/GP13/GP17
UART1-TX                 GP4/GP8
UART1-RX                GP5/GP9

Other Pins on Pico board:– 

GND: is the Ground pin used to complete the circuit. 

              VBUS: is the micro-USB input voltage connected to micro-USB port pin 1. 

VSYS: is the main system input voltage, which can vary in the allowed range 1.8V to 5.5V, and is used by the on-board

NRF24L01 (Sensor Description) 

NRF24L01 is a single chip radio transceiver for the world wide 2.4 – 2.5 GHz ISM band. The transceiver consists of a fully integrated frequency synthesizer, a power amplifier, a crystal oscillator, a demodulator, modulator and Enhanced ShockBurst™ protocol engine. Output power, frequency channels, and protocol setup are easily programmable through a SPI interface. Current consumption is very low, only 9.0mA at an output power of -6dBm and 12.3mA in RX mode. Built-in Power Down and Standby modes makes power saving easily realizable. 

NRF24L01 specification:

Features of the nRF24L01 include: 

• Radio X Worldwide 2.4GHz ISM band operation 

  • 126 RF channels 
  • Common RX and TX pins 
  • GFSK modulation 
  • 1 and 2Mbps air data rate 
  • 1MHz non-overlapping channel spacing at 1Mbps 
  • 2MHz non-overlapping channel spacing at 2Mbps

Transmitter 

  • Programmable output power: 0, -6, -12 or -18dBm 
  • 11.3mA at 0dBm output power

Receiver 

  • Integrated channel filters 
  • 12.3mA at 2Mbps 
  •  -82dBm sensitivity at 2Mbps
  • -85dBm sensitivity at 1Mbps 
  • Programmable LNA gain 

• Power Management 

  • Integrated voltage regulator 
  • 1.9 to 3.6V supply range 
  • Idle modes with fast start-up times for advanced power management 
  • 22uA Standby-I mode, 900nA power down mode 
  • Max 1.5ms start-up from power down mode 
  • Max 130us start-up from standby-I mode 

• RF Synthesizer 

  • Fully integrated synthesizer 
  • No external loop filter, VCO varactor diode or resonator 
  •  Accepts low cost ±60ppm 16MHz crystal

• Enhanced ShockBurst™ 

  • 1 to 32 bytes dynamic payload length 
  • Automatic packet handling 
  • Auto packet transaction handling 
  • 6 data pipe MultiCeiver™ for 1:6 star networks

Enhanced ShockBurst™ uses ShockBurst™ for automatic packet handling and timing. During transmit, ShockBurst™ assembles the packet and clocks the bits in the data packet into the transmitter for transmission. During receive, ShockBurst™ constantly searches for a valid address in the demodulated signal.

When ShockBurst™ finds a valid address, it processes the rest of the packet and validates it by CRC. If the packet is valid the payload is moved into the RX FIFO. The high speed bit handling and timing is controlled by ShockBurst™.

Enhanced ShockBurst™ features automatic packet transaction handling that enables the implementation of a reliable bi-directional data link. An Enhanced ShockBurst™ packet transaction is a packet exchange between two transceivers, where one transceiver is the Primary Receiver (PRX) and the other is the Primary Transmitter (PTX). An Enhanced ShockBurst™ packet transaction is always initiated by a packet transmission from the PTX, the transaction is complete when the PTX has received an acknowledgment packet(ACK packet) from the PRX.

GND is the Ground Pin. It is usually marked by encasing the pin in a square so it can be used as a reference for identifying the other pins.

VCC supplies power for the module. This can be anywhere from 1.9 to 3.9 volts. You can connect it to 3.3V output from your Arduino. Remember connecting it to a 5V pin will likely destroy your nRF24L01+ module!

CE (Chip Enable) is an active-HIGH pin. When selected the nRF24L01 will either transmit or receive, depending upon which mode it is currently in.

CSN (Chip Select Not) is an active-LOW pin and is normally kept HIGH. When this pin goes low, the nRF24L01 begins listening on its SPI port for data and processes it accordingly.

SCK (Serial Clock) accepts clock pulses provided by the SPI bus Master.

MOSI (Master Out Slave In) is SPI input to the nRF24L01.

MISO (Master In Slave Out) is SPI output from the nRF24L01.

IRQ is an interrupt pin that can alert the master when new data is available to process.

Power consumption

PTX operation

You activate PTX mode by setting the CE pin high. If there is a packet present in the TX FIFO the nRF24L01 enters TX mode and transmits the packet. If Auto Retransmit is enabled, the state machine checks if the NO_ACK flag is set. If it is not set, the nRF24L01 enters RX mode to receive an ACK packet. If the received ACK packet is empty, only the TX_DS IRQ is asserted. If the ACK packet contains a payload, both TX_DS IRQ and RX_DR IRQ are asserted simultaneously before nRF24L01 returns to standby-I mode.

If the ACK packet is not received before timeout occurs, the nRF24L01 returns to standby-I mode. It stays in standby-I mode until the ARD has elapsed. If the number of retransmits has not reached the ARC, the nRF24L01 enters TX mode and transmits the last packet once more.

While executing the Auto Retransmit feature, the number of retransmits can reach the maximum number defined in ARC. If this happens, the nRF24L01 asserts the MAX_RT IRQ and returns to standby-I mode.

If the CE is high and the TX FIFO is empty, the nRF24L01 enters Standby-II mode.

PRX Operation:

You activate PRX mode by setting the CE pin high. The nRF24L01 enters RX mode and starts searching for packets. If a packet is received and Auto Acknowledgement is enabled the nRF24L01 decides if this is a new packet or a copy of a previously received packet. If the packet is new the payload is made available in the RX FIFO and the RX_DR IRQ is asserted. If the last received packet from the transmitter is acknowledged with an ACK packet with payload, the TX_DS IRQ indicates that the PTX received the ACK packet.with payload. If the No_ACK flag is not set in the received packet, the PRX enters TX mode. If there is a pending payload in the TX FIFO it is attached to the ACK packet. After the ACK packet is transmitted, the nRF24L01 returns to RX mode.

A copy of a previously received packet might be received if the ACK packet is lost. In this case, the PRX discards the received packet and transmits an ACK packet before it returns to RX mode.

Function:

Multiceiver:

Multiceiver is a feature used in RX mode that contains a set of 6 parallel data pipes with unique addresses. A data pipe is a logical channel in the physical RF channel. Each data pipe has its own physical address decoding in the nRF24L01.

nRF24L01 configured as PRX (primary receiver) can receive data addressed to six different data pipes in one frequency channel.Each data pipe has its own unique address and can be configured for individual behavior.Up to six nRF24L01s configured as PTX can communicate with one nRF24L01 configured as PRX. All data pipe addresses are searched for simultaneously. Only one data pipe can receive a packet at a time. All data pipes can perform Enhanced ShockBurst™ functionality

Auto Acknowledgement

Auto acknowledgment is a function that automatically transmits an ACK packet to the PTX after it has received and validated a packet. The auto acknowledgement function reduces the load of the system MCU and can remove the need for dedicated SPI hardware. This also reduces cost and average current consumption. The Auto Acknowledgement feature is enabled by setting the EN_AA register.

Auto Retransmission (ART)

The auto retransmission is a function that retransmits a packet if an ACK packet is not received. It is used at the PTX side in an auto acknowledgement system. You can set up the number of times a packet is allowed to be retransmitted if a packet is not acknowledged with the ARC bits in the SETUP_RETR register.

PTX enters RX mode and waits a time period for an ACK packet each time a packet is transmitted.

NRF24L01+

NRF24L01 comes in an advanced version. It is  2.4GHz NRF24L01+PA+LNA SMA Wireless Transceiver Antenna.This board features a reverse polarized SMA connector for maximum RF range. And there is PA and LNA circuit on board, with the external antenna it can reach a longer distance than the one without these parts.This module comes with the 2.4G antenna (2DB), with a 250Kbps transmission rate on open-air it can reach the 800-1K meters communication distance.

Its features are :

  • Voltage: 3-3.6V (recommended 3.3V) V.
  • Maximum output power: +20dBm.
  • Power-down mode current: 4.2uA.
  • Operating Range: 1Km
  • Antenna Gain (peak): 2Dbi.
  • 2MB rate (Open area): 520m.
  • 1MB rate (Open area): 750m.
  • 250Kb rate (Open area): 1100m.
  • It uses 2.4GHz global open ISM band, with license free.
  • Facilitate the development for customers, without development RF part.
  • Low cost: integrated with high-speed signal processing parts associated with RF protocol, such as: automatically resend lost packets and generate acknowledge signal;

Package Includes :

  • 1 x 2.4GHz NRF24L01 Transceiver module.
  • 1 x SMA Antenna

Specification:

Schematic Diagram

Pin Connection Table 

Source code

TRANSMITTER Source Code:

from machine import *
GPIO.setmode(GPIO.BCM)
from lib_nrf24 import NRF24
import time
import spidev
from machine import *
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(22, 19)
time.sleep(1)
radio.setRetries(15,15)
radio.setPayloadSize(32)
radio.setChannel(0x60)
radio.setDataRate(NRF24.BR_2MBPS)
radio.setPALevel(NRF24.PA_MIN)
radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openWritingPipe(pipes[1])
radio.openReadingPipe(1, pipes[0])
radio.printDetails()
c=1
while True:
    buf = ['H', 'E', 'L', 'O',c]
    c = (c + 1) & 255
    radio.write(buf)
    print ("Sent:"),
    print (buf)
    if radio.isAckPayloadAvailable():
        pl_buffer=[]
        radio.read(pl_buffer, radio.getDynamicPayloadSize())
        print ("Received back:"),
        print (pl_buffer)
    else:
        print ("Received: Ack only, no payload")
    time.sleep(10)

Code explanation

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
from lib_nrf24 import NRF24
import time
import spidev
from machine import *

Import libraries Rpi.GPIO, Spider, time, NRF24 and machine.

pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
//radio = NRF24(GPIO, spidev.SpiDev())
Radio = NRF24L01(spi, cs, ce)
Radio.send_tx()
Radio.rx()

Create an array named pipes with different address values

radio.begin(22, 19)
time.sleep(1)
radio.setRetries(15,15)
radio.setPayloadSize(32)
radio.setChannel(0x60)
radio.setDataRate(NRF24.BR_2MBPS)
radio.setPALevel(NRF24.PA_MIN)

Initialize the pins from input and outputs.

Then the wireless communication begins.

time.sleep(1) suspends the execution for 1 seconds.

Set the number and delay of retries on failed submit.

Optionally reduce the payload size and  seems to improve reliability

Retry for connection every 15 seconds.

Set payload size as 32 bit, channel address as 60, data rate of 2 mbps and power levels as minimum.

radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openWritingPipe(pipes[1])
radio.openReadingPipe(1, pipes[0])
radio.printDetails()

Set auto acknowledge as true, enable dynamic payloads and Enable custom payloads on the acknowledged packets.

Open the pipes to start reading the data and print the basic details of nRF24l01.

c=1
while True:
    buf = ['H', 'E', 'L', 'O',c]
    c = (c + 1) & 255
    radio.write(buf)
    print ("Sent:"),
    print (buf)

Initialize the value of c as 1

Applying a while loop to check true, print Hello.

Increment the value of variable c by 1 and perform bit wise and operation. If the condition is true, then print the message ‘sent’ along with buf value.

 if radio.isAckPayloadAvailable():
        pl_buffer=[]
        radio.read(pl_buffer, radio.getDynamicPayloadSize())
        print ("Received back:"),
        print (pl_buffer)
 else:
        print ("Received: Ack only, no payload")
    time.sleep(10)

create a null array named pl_buffer.

If the acknowledged payload available  value is true and dynamic payload size matches then read the value and print the message “Received back” along with the received message else print the message “Received: ack only, no payload”.

Suspend the execution for 10 seconds.

RECEIVER Source Code:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
from lib_nrf24 import NRF24
import time
import spidev
from machine import *
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio2 = NRF24(GPIO, spidev.SpiDev())
radio2.begin(22,19)
radio2.setRetries(15,15)
radio2.setPayloadSize(32)
radio2.setChannel(0x60)
radio2.setDataRate(NRF24.BR_2MBPS)
radio2.setPALevel(NRF24.PA_MIN)
radio2.setAutoAck(True)
radio2.enableDynamicPayloads()
radio2.enableAckPayload()
radio2.openWritingPipe(pipes[0])
radio2.openReadingPipe(1, pipes[1])
radio2.startListening()
radio2.stopListening()
radio2.printDetails()
radio2.startListening()
c=1
while True:
    akpl_buf = [c,1, 2, 3,4,5,6,7,8,9,0,1, 2, 3,4,5,6,7,8]
    pipe = [0]
    while not radio2.available(pipe):
        time.sleep(10000/1000000.0)
    recv_buffer = []
    radio2.read(recv_buffer, radio2.getDynamicPayloadSize())
    print ("Received:") ,
    print (recv_buffer)
    c = c + 1
    if (c&1) == 0:
        radio2.writeAckPayload(1, akpl_buf, len(akpl_buf))
        print ("Loaded payload reply:"),
        print (akpl_buf)
    else:
        print ("(No return payload)")

Create an array named pipes with different address values

Initialize the pins from input and outputs.

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
from lib_nrf24 import NRF24
import time
import spidev
from machine import *

Then the wireless communication begins.

time.sleep(1) suspends the execution for 1 seconds.

Optionally reduce the payload size and  seems to improve reliability

Retry for connection every 15 seconds.

Set payload size as 32 bit, channel address as 60, data rate of 2 mbps and power levels as minimum.

radio2.setAutoAck(True)
radio2.enableDynamicPayloads()
radio2.enableAckPayload()
radio2.openWritingPipe(pipes[0])
radio2.openReadingPipe(1, pipes[1])
radio2.startListening()
radio2.stopListening()
radio2.printDetails()
radio2.startListening()

Set auto acknowledge as true, enable dynamic payloads and enable acknowledge payloads.

Open the pipes to start writing the data and print the basic details of nRF24l01

Start listening on the pipes opened for reading.

c=1
while True:
    akpl_buf = [c,1, 2, 3,4,5,6,7,8,9,0,1, 2, 3,4,5,6,7,8]
    pipe = [0]
    while not radio2.available(pipe):
        time.sleep(10000/1000000.0)
    recv_buffer = []
    radio2.read(recv_buffer, radio2.getDynamicPayloadSize())
    print ("Received:") ,
    print (recv_buffer)
    c = c + 1

Initialize the value of c as 1.

Declare an array akpl_buf, pipe and initialize them with certain values.

When data is not available at the pipe , make the module sleep for certain seconds. 

Declare a null array named recv_buffer. 

If the dynamic payload available  value is true and dynamic payload size matches then read the value and print the message Received.And also print the recv_buffer.

Increment the value of the variable c by 1.

 if (c&1) == 0:
        radio2.writeAckPayload(1, akpl_buf, len(akpl_buf))
        print ("Loaded payload reply:"),
        print (akpl_buf)
    else:
        print ("(No return payload)")

If bitwise and operation between c and 1 is equal to zero then write the acknowledged payload value and print the message Loaded Payload Reply. At last print the value of akpl_buf.

Else if c&1 != 0 then print the message ‘No return Payload’.   

Github Link:

https://github.com/iottrends/iottrends/tree/main/NRF24L01

0 0 votes
Article Rating
Previous articleHow to Interface ESP8266 with NRF24L01
Next articleHow to Interface PWM Using MicroPython: A Comprehensive Guide
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments