Optimized high speed nRF24L01+ driver class documentation v1.4.8
TMRh20 2020 - Optimized fork of the nRF24L01+ driver
Loading...
Searching...
No Matches
examples_linux/getting_started.py

Written by 2bndy5 in 2020

This is a simple example of using the RF24 class on a Raspberry Pi.

Remember to install the Python wrapper, then navigate to the "RF24/examples_linux" folder.
To run this example, enter

python3 getting_started.py

and follow the prompts.

Note
this example requires python v3.7 or newer because it measures transmission time with time.monotonic_ns().
1"""
2A simple example of sending data from 1 nRF24L01 transceiver to another.
3This example was written to be used on 2 devices acting as 'nodes'.
4"""
5import sys
6import argparse
7import time
8import struct
9from RF24 import RF24, RF24_PA_LOW
10
11
12parser = argparse.ArgumentParser(
13 description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
14)
15parser.add_argument(
16 "-n",
17 "--node",
18 type=int,
19 choices=range(2),
20 help="the identifying radio number (or node ID number)",
21)
22parser.add_argument(
23 "-r",
24 "--role",
25 type=int,
26 choices=range(2),
27 help="'1' specifies the TX role. '0' specifies the RX role.",
28)
29
30
31
38CSN_PIN = 0 # connected to GPIO8
39CE_PIN = 22 # connected to GPIO22
40radio = RF24(CE_PIN, CSN_PIN)
41
46
47# using the python keyword global is bad practice. Instead we'll use a 1 item
48# list to store our float number for the payloads sent/received
49payload = [0.0]
50
51
52def master():
53 """Transmits an incrementing float every second"""
54 radio.stopListening() # put radio in TX mode
55 failures = 0
56 while failures < 6:
57 # use struct.pack() to packet your data into the payload
58 # "<f" means a single little endian (4 byte) float value.
59 buffer = struct.pack("<f", payload[0])
60 start_timer = time.monotonic_ns() # start timer
61 result = radio.write(buffer)
62 end_timer = time.monotonic_ns() # end timer
63 if not result:
64 print("Transmission failed or timed out")
65 failures += 1
66 else:
67 print(
68 "Transmission successful! Time to Transmit:",
69 f"{(end_timer - start_timer) / 1000} us. Sent: {payload[0]}",
70 )
71 payload[0] += 0.01
72 time.sleep(1)
73 print(failures, "failures detected. Leaving TX role.")
74
75
76def slave(timeout=6):
77 """Listen for any payloads and print the transaction
78
79 :param int timeout: The number of seconds to wait (with no transmission)
80 until exiting function.
81 """
82 radio.startListening() # put radio in RX mode
83
84 start_timer = time.monotonic()
85 while (time.monotonic() - start_timer) < timeout:
86 has_payload, pipe_number = radio.available_pipe()
87 if has_payload:
88 # fetch 1 payload from RX FIFO
89 buffer = radio.read(radio.payloadSize)
90 # use struct.unpack() to convert the buffer into usable data
91 # expecting a little endian float, thus the format string "<f"
92 # buffer[:4] truncates padded 0s in case payloadSize was not set
93 payload[0] = struct.unpack("<f", buffer[:4])[0]
94 # print details about the received packet
95 print(
96 f"Received {radio.payloadSize} bytes",
97 f"on pipe {pipe_number}: {payload[0]}",
98 )
99 start_timer = time.monotonic() # reset the timeout timer
100
101 print("Nothing received in", timeout, "seconds. Leaving RX role")
102 # recommended behavior is to keep in TX mode while idle
103 radio.stopListening() # put the radio in TX mode
104
105
106def set_role() -> bool:
107 """Set the role using stdin stream. Timeout arg for slave() can be
108 specified using a space delimiter (e.g. 'R 10' calls `slave(10)`)
109
110 :return:
111 - True when role is complete & app should continue running.
112 - False when app should exit
113 """
114 user_input = (
115 input(
116 "*** Enter 'R' for receiver role.\n"
117 "*** Enter 'T' for transmitter role.\n"
118 "*** Enter 'Q' to quit example.\n"
119 )
120 or "?"
121 )
122 user_input = user_input.split()
123 if user_input[0].upper().startswith("R"):
124 if len(user_input) > 1:
125 slave(int(user_input[1]))
126 else:
127 slave()
128 return True
129 if user_input[0].upper().startswith("T"):
130 master()
131 return True
132 if user_input[0].upper().startswith("Q"):
133 radio.powerDown()
134 return False
135 print(user_input[0], "is an unrecognized input. Please try again.")
136 return set_role()
137
138
139if __name__ == "__main__":
140
141 args = parser.parse_args() # parse any CLI args
142
143 # initialize the nRF24L01 on the spi bus
144 if not radio.begin():
145 raise RuntimeError("radio hardware is not responding")
146
147 # For this example, we will use different addresses
148 # An address need to be a buffer protocol object (bytearray)
149 address = [b"1Node", b"2Node"]
150 # It is very helpful to think of an address as a path instead of as
151 # an identifying device destination
152
153 print(sys.argv[0]) # print example name
154
155 # to use different addresses on a pair of radios, we need a variable to
156 # uniquely identify which address this radio will use to transmit
157 # 0 uses address[0] to transmit, 1 uses address[1] to transmit
158 radio_number = args.node # uses default value from `parser`
159 if args.node is None: # if '--node' arg wasn't specified
160 radio_number = bool(
161 int(input("Which radio is this? Enter '0' or '1'. Defaults to '0' ") or 0)
162 )
163
164 # set the Power Amplifier level to -12 dBm since this test example is
165 # usually run with nRF24L01 transceivers in close proximity of each other
166 radio.setPALevel(RF24_PA_LOW) # RF24_PA_MAX is default
167
168 # set the TX address of the RX node into the TX pipe
169 radio.openWritingPipe(address[radio_number]) # always uses pipe 0
170
171 # set the RX address of the TX node into a RX pipe
172 radio.openReadingPipe(1, address[not radio_number]) # using pipe 1
173
174 # To save time during transmission, we'll set the payload size to be only
175 # what we need. A float value occupies 4 bytes in memory using
176 # struct.pack(); "f" means an unsigned float
177 radio.payloadSize = struct.calcsize("f")
178
179 # for debugging, we have 2 options that print a large block of details
180 # (smaller) function that prints raw register values
181 # radio.printDetails()
182 # (larger) function that prints human readable data
183 # radio.printPrettyDetails()
184
185 try:
186 if args.role is None: # if not specified with CLI arg '-r'
187 while set_role():
188 pass # continue example until 'Q' is entered
189 else: # if role was set using CLI args
190 # run role once and exit
191 if bool(args.role):
192 master()
193 else:
194 slave()
195 except KeyboardInterrupt:
196 print(" Keyboard Interrupt detected. Powering down radio.")
197 radio.powerDown()
Driver class for nRF24L01(+) 2.4GHz Wireless Transceiver.
Definition: RF24.h:116