-
Notifications
You must be signed in to change notification settings - Fork 56
/
example-nrf24-pair.py
154 lines (126 loc) · 5.27 KB
/
example-nrf24-pair.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/python
#
# Example program to send packets between 2 NRF24L01+ radios
#
# Demonstrates: 2 x NRF24 radios both operating from SPI on one virt-GPIO, doing 2-way radio data transfer
# Dynamic payload size both ways (to 32 bytes).
# "Auto-Ack" mode, with "ack-payload" carrying the return data.
# Forward payload and return ack-payload data content is rather arbitrary, but is identifiable.
# (Single PTX-PRX link is demonstrated, although PRX has 6-channel capacity.)
# Setup: 2 x NRF24L01+ (each with 5V to 3.3V "adapter plate") (total eBay cost under $5, "8 pin" types)
# Radio1 in PTX (master) mode, radio2 in PRX (slave/server) mode.
# Pins: Radio1 Arduino pin9 as NRF24-CSN (spi CE), Tie RF24-CE to HIGH (+3 or +5)
# Radio2 Arduino pin10 as NRF24-CSN, Tie RF24-CE to HIGH (+3 or +5)
# (VirtGPIO/arduino uses notation "CE" differently from NRF24 usage!)
# Both radios: Arduino pin11 = MOSI, pin12 = MISO, pin13 = SCLK
# Note: NRF24 power MUST be 3.3V, NOT 5v. (Its data pins may operate at 3.3V or 5V.)
# Optionally, a LED on pin6, as switched-across "activity Led".
import virtGPIO as GPIO
from lib_nrf24 import NRF24
import time
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
# Comment re multiple SPIDEV devices:
# Official spidev documentation is sketchy. Implementation in virtGPIO allows multiple SpiDev() objects.
# This may not work on RPi? Probably RPi uses alternating open() / xfer2() /close() within one SpiDev() object???
# On virtGPIO each of multiple SpiDev() stores its own mode and cePin. Multiple RF24 used here becomes easy.
# This issue affects only using MULTIPLE Spi devices.
##################################################################
# SET UP RADIO1 - PTX
radio1 = NRF24(GPIO, GPIO.SpiDev())
radio1.begin(9) # SPI-CE=RF24-CSN=pin9, no RF24-CE pin
time.sleep(1)
radio1.setRetries(15,15)
radio1.setPayloadSize(32)
radio1.setChannel(0x62)
radio1.setDataRate(NRF24.BR_2MBPS)
radio1.setPALevel(NRF24.PA_MIN)
radio1.setAutoAck(True)
radio1.enableDynamicPayloads()
radio1.enableAckPayload()
radio1.openWritingPipe(pipes[1])
radio1.openReadingPipe(1, pipes[0])
if not radio1.isPVariant():
# If radio configures correctly, we confirmed a "plus" (ie "variant") nrf24l01+
# Else print diagnostic stuff & exit.
radio1.printDetails()
# (or we could always just print details anyway, even on good setup, for debugging)
print ("NRF24L01+ not found.")
exit()
##################################################################
# AND THEN RADIO2 - PRX - VIRTUALLY IDENTICAL !
radio2 = NRF24(GPIO, GPIO.SpiDev())
radio2.begin(10) # SPI-CE=RF24-CSN=pin10, no RF24-CE pin
time.sleep(1)
radio2.setRetries(15,15)
radio2.setPayloadSize(32)
radio2.setChannel(0x62)
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()
if not radio2.isPVariant():
radio2.stopListening()
radio2.printDetails()
print ("NRF24L01+ not found.")
exit()
##################################################################
c1 = 1
def serviceRadio1():
# Let's deal with PTX - radio1:
print ("TX:")
global c1
global radio1
buf = ['H', 'E', 'L', 'O',(c1 & 255)] # something to recognise at other end
c1 += 1
# send a packet to receiver
radio1.write(buf)
# RF24 handles all timeouts, retries and ACKs and ACK-payload
# So the call to radio.write() only returns after ack and its payload have finished
print ("\033[31;1mPTX Sent:\033[0m"),
print (buf)
# did a payload come back with the ACK?
if radio1.isAckPayloadAvailable():
pl_buffer=[]
radio1.read(pl_buffer, radio1.getDynamicPayloadSize())
print ("\033[31;1mPTX Received back:\033[0m"),
print (pl_buffer)
else:
print ("PTX Received: Ack only, no payload")
##################################################################
c2 = 1
def serviceRadio2():
# Now deal separately with PRX - radio 2
print ("RX?")
global c2
global radio2
akpl_buf = [(c2& 255),1, 2, 3,4,5,6,7,8,9,0,1, 2, 3,4,5,6,7,8] # We should see this returned to PTX
pipe = [0]
if not radio2.available(pipe):
return
recv_buffer = []
radio2.read(recv_buffer, radio2.getDynamicPayloadSize())
print ("\033[32;1mPRX Received:\033[0m") ,
print (recv_buffer)
c2 += 1
if (c2&1) == 0: # alternate times - so we can see difference beteeen ack-payload and no ack-payload
radio2.writeAckPayload(1, akpl_buf, len(akpl_buf))
print ("PRX Loaded payload reply:"),
print (akpl_buf)
else:
print ("PRX: (No return payload)")
##################################################################
# We could experiment with differing payload lengths above, up to max 32 bytes each way.
c=0
while True:
c += 1
print ("Loop %d" % c),
if not (c % 3): # only once per x loops
serviceRadio1() # send something
time.sleep(0.01)
else:
serviceRadio2() # has it arrived? (if so, maybe send return data)
time.sleep(2) # 1 sec per loop