Wireless Pi to Pi Communication with NRF24L01+
The NRF24L01+ is a popular transceiver among hobbyists known for its ease of use, very long distance range for communication and inexpensive nature. The NRF24L01+ boasts a communication range of over a kilometer when using the power amplified version and having a clear line of sight. Even low end units can achieve 30m ranges. In this tutorial I show you how to establish communication between two Raspberry Pis using the NRF24L01+ transceiver.
This tutorial is a little older (published in 2016!). The main principles are still relevant, so I haven't needed to update this lesson.
- Raspberry Pi x2
- 5VDC Micro USB Power Supply x2
- nRF24L01+ Transceivers x2
- Breadboard
- Breadboard compatible wires
DIFFICULTY
DIFFICULT
CIRCUITRY KNOWLEDGE
LITTLE
PYTHON PROGRAMMING
SOME
ABOUT
0
MINUTES- How to connect a NRF24L01+ transceiver to a Raspberry Pi
- How to send a message from a nRF24L01+
- How to receive a message from a nRF24L01+ on a Raspberry Pi
You can copy / paste the code below if you’re having issues with typos or want a shortcut. However I recommend that you follow along in the tutorial to understand what is going on!
recv.py
import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time
import spidev
GPIO.setmode(GPIO.BCM)
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0, 17)
radio.setPayloadSize(32)
radio.setChannel(0x60)
radio.setDataRate(NRF24.BR_2MBPS)
radio.setPALevel(NRF24.PA_MIN)
radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()
radio.openReadingPipe(1, pipes[1])
radio.printDetails()
radio.startListening()
while True:
ackPL = [1]
while not radio.available(0):
time.sleep(1/100)
receivedMessage = []
radio.read(receivedMessage, radio.getDynamicPayloadSize())
print("Received: {}".format(receivedMessage))
print("Translating the receivedMessage into unicode characters...")
string = ""
for n in receivedMessage:
# Decode into standard unicode set
if (n >=32 and n <= 126):
string += chr(n)
print(string)
radio.writeAckPayload(1, ackPL, len(ackPL))
print("Loaded payload reply of {}".format(ackPL))
#>
slave.py
import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time
import spidev
GPIO.setmode(GPIO.BCM)
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0, 17)
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[0])
radio.openReadingPipe(1, pipes[1])
radio.printDetails()
radio.startListening()
def getTemp():
temp = 25
return str(temp)
def sendData(ID, value):
radio.stopListening()
time.sleep(0.25)
message = list(ID) + list(value)
print("About to send the message.")
radio.write(message)
print("Sent the data.")
radio.startListening()
while True:
ackPL = [1]
radio.writeAckPayload(1, ackPL, len(ackPL))
while not radio.available(0):
time.sleep(1/100)
receivedMessage = []
radio.read(receivedMessage, radio.getDynamicPayloadSize())
print("Received: {}".format(receivedMessage))
print("Translating the receivedMessage into unicode characters...")
string = ""
for n in receivedMessage:
# Decode into standard unicode set
if (n >=32 and n <= 126):
string += chr(n)
print(string)
# We want to react to the command from the master.
command = string
if command == "GET_TEMP":
print("We should get the temperature!")
tempID = "temp_"
temp = getTemp()
sendData(tempID, temp)
command = ""
radio.writeAckPayload(1, ackPL, len(ackPL))
print("Loaded payload reply of {}".format(ackPL))
#>
master.py
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
from lib_nrf24 import NRF24
import time
import spidev
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0, 17)
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()
ackPL = [1]
def receiveData():
print("Ready to receive data.")
radio.startListening()
pipe = [0]
while not radio.available(pipe):
time.sleep(1/100)
receivedMessage = []
radio.read(receivedMessage, radio.getDynamicPayloadSize())
print("Translating the receivedMessage to unicode characters...")
string = ""
for n in receivedMessage:
# We want to only decode standard symbols/alphabet/numerals
# Based off unicode standards, our encoding method
if (n >= 32 and n <= 126):
string += chr(n)
print("Our sensor sent us: {}".format(string))
radio.stopListening()
while True:
command = "GET_TEMP"
message = []
message = list(command)
# send a packet to receiver
radio.write(message)
print("Sent: {}".format(message))
# did it return with a payload?
if radio.isAckPayloadAvailable():
pl_buffer=[]
radio.read(pl_buffer, radio.getDynamicPayloadSize())
print(pl_buffer)
print("Translating the acknowledgement to unicode characters...")
string = ""
for n in pl_buffer:
# We want to only decode standard symbols/alphabet/numerals
# Based off unicode standards, our encoding method
if (n >= 32 and n <= 126):
string += chr(n)
print(string)
# So our command was received and acknowledged. We should
# setup ourselves to receive what that temperature was.
receiveData()
else:
print("No received acknowledgement.")
time.sleep(0.5)
#>