PLEASE SEE REVISED FILES IN POST BELOW 28 NOV 2014.
B
Here are my experiences of getting NRF24L01+ modules ($1 up on eBay) running on rPi. It is based on Joao Paulo Barraca's pynrf24 python library at https://github.com/jpbarraca/pynrf24. It took some debugging, but now I have a working system that seems stable and adaptable to projects.
How to tweak up JPB's python module to love the Raspberry Pi:
Code: Select all
Tweak Joao Paulo Barraca's BBB/rPi version of nrf24.py:
Get from github at https://github.com/jpbarraca/pynrf24.
Check your version: last line should be line 772: " return ((250" etc
We will edit from the bottom upwards, to keep line numbering stable for editing.
JPB's code is admittedly tuned for Beagle Bone Black, with probable validity for rPi.
These are my tweaks that make this library sing on two rPi's here.
1. The calculated timeout of getMaxTimeout (line 770) is (empirically) premature by about 30%.
Add multiplier " * 2" at end if line 772, to double the timeout.
Crude but adequate. This timeout ought never be hit if the nrf24 chip is functioning,
but all software should guard against sticking in a loop!
But premature timeouts as here seem to get the chip very confused.
2. Delete lines 496 - 501 (the else: irq section).
(I have removed all IRQ function for this version, as rPi would need a rethink anyway.)
3. Line 485. remove third and fourth parameters (IRQ)
4. Add a missing line after line 466.
465 if what['rx_ready']:
466 self.ack_payload_length = self.getDynamicPayloadSize()
467 self.ack_payload_available = True # needed for ack-payload
5. Add two lines after line 462:
460 what = self.whatHappened()
461
462 result = what['tx_ok']
463 if what['tx_fail']:
464 self.flush_tx(); # dont fill up the tx fifo
465 # Handle the ack packet
Retry count-out ("tx-fail") in ACK mode does not clear the tx buffer. We need to dump it.
6. Remove line 373 (irq_pin) and line 370 (irq_pin).
In line 365 remove last parameter (irq_pin) in begin().
7. Function print_observe_tx() at line 299+ yields wrong value for PLOS_CNT.
Looking at the code, I'm not sure why, but the result is wrong.
Simple pragmatic solution - put in a replacement that works:
Delete lines 300-305, and replace with one line:
299 def print_observe_tx(self, value):
300 print "Observe Tx: %02x Lost Pkts: %d Retries: %d" % (value, value >> NRF24.PLOS_CNT, value & 15)
8. Delete lines 195-205 (irqWait)
9. Delete line 176 (irq_pin)
Alter line 175 (BBB type pin number) to
175 self.ce_pin = 17
10. Delete lines 17-24 (BBB configuration)
Replace with these lines:
18 import RPi.GPIO as GPIO
19 GPIO.setmode(GPIO.BCM)
20 GPIO.setwarnings(False)
There are only 3 files, the nrf24.py library and the two send/recv scripts.
The mode used is ack retry with dynamic payload size and ack payload enabled (1-32 bytes transmit payload, and 0-32 bytes ack-payload. My 2 rPis have been chattering happily all overnight, minimum RF power, 2MB/s, across my 6-foot bench, not missing a beat. I can stop the receiver and restart, and everything recovers and resumes happily. I have a working system that can only improve from here.
Now, here is my recv_akpl.py:
Code: Select all
from nrf24 import NRF24
import time
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24()
radio.begin(0, 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[0])
radio.openReadingPipe(1, pipes[1])
radio.startListening()
radio.stopListening()
radio.printDetails()
radio.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]
# wait for incoming packet from transmitter
while not radio.available(pipe):
time.sleep(10000/1000000.0)
recv_buffer = []
radio.read(recv_buffer, radio.getDynamicPayloadSize())
print recv_buffer
c = c + 1
if (c&1) == 0: # queue a return payload every alternate time
radio.writeAckPayload(1, akpl_buf, len(akpl_buf))
Code: Select all
from nrf24 import NRF24
import time
pipes = [[0xe7, 0xe7, 0xe7, 0xe7, 0xe7], [0xc2, 0xc2, 0xc2, 0xc2, 0xc2]]
radio = NRF24()
radio.begin(0, 0, 17) #Set ce0/csn and rf24-CE
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
# send a packet to receiver
radio.write(buf)
# did it return with a payload?
if radio.isAckPayloadAvailable():
pl_buffer=[]
radio.read(pl_buffer, radio.getDynamicPayloadSize())
print pl_buffer
time.sleep(2)
Also, I haven't tried rPi-arduino by radio yet. (Actually, I did try it early on when the rPi code wasn't yet behaving properly. Guess what? - rPi-arduino wouldn't work properly.)
Maybe IRQ operation should go back one day. The transmit write() function typically takes 2.2 mSec assuming ACK works as intended and no retries are needed, but WAY longer (depending on the delay/count settings you make for retries) if the receiver end is not responding.


