summaryrefslogtreecommitdiffstatshomepage
path: root/drivers/nrf24l01/nrf24l01.py
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nrf24l01/nrf24l01.py')
-rw-r--r--drivers/nrf24l01/nrf24l01.py96
1 files changed, 56 insertions, 40 deletions
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
index 255aade83f..2db3546814 100644
--- a/drivers/nrf24l01/nrf24l01.py
+++ b/drivers/nrf24l01/nrf24l01.py
@@ -1,4 +1,11 @@
-"""NRF24L01 driver for Micro Python"""
+"""NRF24L01 driver for Micro Python
+
+Support for nonblocking send added. Minor fixes:
+Timeout now uses pyb.elapsed_millis().
+Channel numbers constrained to 125 as per datasheet.
+Status register read with reg_read() - reg_read_ret_status() removed.
+Default speed 250K for improved range/error rate.
+"""
import pyb
@@ -69,8 +76,10 @@ class NRF24L01:
self.pipe0_read_addr = None
pyb.delay(5)
- # set address width to 5 bytes
+ # set address width to 5 bytes and check for device present
self.reg_write(SETUP_AW, 0b11)
+ if self.reg_read(SETUP_AW) != 0b11:
+ raise OSError("nRF24l01+ Hardware not responding")
# disable dynamic payloads
self.reg_write(DYNPD, 0)
@@ -80,7 +89,7 @@ class NRF24L01:
self.reg_write(SETUP_RETR, (6 << 4) | 8)
# set rf power and speed
- self.set_power_speed(POWER_3, SPEED_1M)
+ self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
# init CRC
self.set_crc(2)
@@ -102,13 +111,6 @@ class NRF24L01:
self.cs.high()
return buf[0]
- def reg_read_ret_status(self, reg):
- self.cs.low()
- status = self.spi.send_recv(reg)[0]
- buf = self.spi.recv(1)
- self.cs.high()
- return status
-
def reg_write(self, reg, buf):
self.cs.low()
status = self.spi.send_recv(0x20 | reg)[0]
@@ -143,7 +145,7 @@ class NRF24L01:
self.reg_write(CONFIG, config)
def set_channel(self, channel):
- self.reg_write(RF_CH, min(channel, 127))
+ self.reg_write(RF_CH, min(channel, 125)) # Changed from 127
# address should be a bytes object 5 bytes long
def open_tx_pipe(self, address):
@@ -194,41 +196,55 @@ class NRF24L01:
self.spi.send(R_RX_PAYLOAD)
buf = self.spi.recv(self.payload_size)
self.cs.high()
-
# clear RX ready flag
self.reg_write(STATUS, RX_DR)
return buf
- def send(self, buf, timeout=500):
- # power up
- self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
- pyb.udelay(150)
-
- # send the data
- self.cs.low()
- self.spi.send(W_TX_PAYLOAD)
- self.spi.send(buf)
- if len(buf) < self.payload_size:
- self.spi.send(b'\x00' * (self.payload_size - len(buf))) # pad out data
- self.cs.high()
-
- # enable the chip so it can send the data
- self.ce.high()
- pyb.udelay(15) # needs to be >10us
- self.ce.low()
-
# blocking wait for tx complete
+ def send(self, buf, timeout=500):
+ send_nonblock = self.send_nonblocking(buf)
start = pyb.millis()
- while pyb.millis() - start < timeout:
- status = self.reg_read_ret_status(OBSERVE_TX)
- if status & (TX_DS | MAX_RT):
- break
-
- # get and clear all status flags
- status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
- if not (status & TX_DS):
+ result = None
+ while result is None and (pyb.elapsed_millis(start) < timeout):
+ result = send_nonblock() # 1 == success 2 == fail
+ if result == 2:
raise OSError("send failed")
- # power down
- self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
+ def send_nonblocking(self, buf):
+ '''
+ Support for nonblocking transmission. Returns a function instance.
+ The first call to a function instance sends the data and returns None.
+ Subsequent calls test TX status returning not ready None, ready 1, error 2.
+ '''
+ init = True
+ def make_snb():
+ nonlocal init
+ if init:
+ # power up
+ self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
+ pyb.udelay(150)
+
+ # send the data
+ self.cs.low()
+ self.spi.send(W_TX_PAYLOAD)
+ self.spi.send(buf)
+ if len(buf) < self.payload_size:
+ self.spi.send(b'\x00' * (self.payload_size - len(buf))) # pad out data
+ self.cs.high()
+
+ # enable the chip so it can send the data
+ self.ce.high()
+ pyb.udelay(15) # needs to be >10us
+ self.ce.low()
+ init = False
+ return None # Not ready
+
+ if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)):
+ return None # Not ready
+ # Either ready or failed: get and clear status flags, power down
+ status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
+ self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
+ return 1 if status & TX_DS else 2
+ return make_snb
+