nrf24l01.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. """NRF24L01 driver for MicroPython
  2. """
  3. from micropython import const
  4. import utime
  5. # nRF24L01+ registers
  6. CONFIG = const(0x00)
  7. EN_RXADDR = const(0x02)
  8. SETUP_AW = const(0x03)
  9. SETUP_RETR = const(0x04)
  10. RF_CH = const(0x05)
  11. RF_SETUP = const(0x06)
  12. STATUS = const(0x07)
  13. RX_ADDR_P0 = const(0x0a)
  14. TX_ADDR = const(0x10)
  15. RX_PW_P0 = const(0x11)
  16. FIFO_STATUS = const(0x17)
  17. DYNPD = const(0x1c)
  18. # CONFIG register
  19. EN_CRC = const(0x08) # enable CRC
  20. CRCO = const(0x04) # CRC encoding scheme; 0=1 byte, 1=2 bytes
  21. PWR_UP = const(0x02) # 1=power up, 0=power down
  22. PRIM_RX = const(0x01) # RX/TX control; 0=PTX, 1=PRX
  23. # RF_SETUP register
  24. POWER_0 = const(0x00) # -18 dBm
  25. POWER_1 = const(0x02) # -12 dBm
  26. POWER_2 = const(0x04) # -6 dBm
  27. POWER_3 = const(0x06) # 0 dBm
  28. SPEED_1M = const(0x00)
  29. SPEED_2M = const(0x08)
  30. SPEED_250K = const(0x20)
  31. # STATUS register
  32. RX_DR = const(0x40) # RX data ready; write 1 to clear
  33. TX_DS = const(0x20) # TX data sent; write 1 to clear
  34. MAX_RT = const(0x10) # max retransmits reached; write 1 to clear
  35. # FIFO_STATUS register
  36. RX_EMPTY = const(0x01) # 1 if RX FIFO is empty
  37. # constants for instructions
  38. R_RX_PL_WID = const(0x60) # read RX payload width
  39. R_RX_PAYLOAD = const(0x61) # read RX payload
  40. W_TX_PAYLOAD = const(0xa0) # write TX payload
  41. FLUSH_TX = const(0xe1) # flush TX FIFO
  42. FLUSH_RX = const(0xe2) # flush RX FIFO
  43. NOP = const(0xff) # use to read STATUS register
  44. class NRF24L01:
  45. def __init__(self, spi, cs, ce, channel=46, payload_size=16):
  46. assert payload_size <= 32
  47. self.buf = bytearray(1)
  48. # store the pins
  49. self.spi = spi
  50. self.cs = cs
  51. self.ce = ce
  52. # init the SPI bus and pins
  53. self.init_spi(4000000)
  54. # reset everything
  55. ce.init(ce.OUT, value=0)
  56. cs.init(cs.OUT, value=1)
  57. self.payload_size = payload_size
  58. self.pipe0_read_addr = None
  59. utime.sleep_ms(5)
  60. # set address width to 5 bytes and check for device present
  61. self.reg_write(SETUP_AW, 0b11)
  62. if self.reg_read(SETUP_AW) != 0b11:
  63. raise OSError("nRF24L01+ Hardware not responding")
  64. # disable dynamic payloads
  65. self.reg_write(DYNPD, 0)
  66. # auto retransmit delay: 1750us
  67. # auto retransmit count: 8
  68. self.reg_write(SETUP_RETR, (6 << 4) | 8)
  69. # set rf power and speed
  70. self.set_power_speed(POWER_3, SPEED_250K) # Best for point to point links
  71. # init CRC
  72. self.set_crc(2)
  73. # clear status flags
  74. self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
  75. # set channel
  76. self.set_channel(channel)
  77. # flush buffers
  78. self.flush_rx()
  79. self.flush_tx()
  80. def init_spi(self, baudrate):
  81. try:
  82. master = self.spi.MASTER
  83. except AttributeError:
  84. self.spi.init(baudrate=baudrate, polarity=0, phase=0)
  85. else:
  86. self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
  87. def reg_read(self, reg):
  88. self.cs(0)
  89. self.spi.readinto(self.buf, reg)
  90. self.spi.readinto(self.buf)
  91. self.cs(1)
  92. return self.buf[0]
  93. def reg_write_bytes(self, reg, buf):
  94. self.cs(0)
  95. self.spi.readinto(self.buf, 0x20 | reg)
  96. self.spi.write(buf)
  97. self.cs(1)
  98. return self.buf[0]
  99. def reg_write(self, reg, value):
  100. self.cs(0)
  101. self.spi.readinto(self.buf, 0x20 | reg)
  102. ret = self.buf[0]
  103. self.spi.readinto(self.buf, value)
  104. self.cs(1)
  105. return ret
  106. def flush_rx(self):
  107. self.cs(0)
  108. self.spi.readinto(self.buf, FLUSH_RX)
  109. self.cs(1)
  110. def flush_tx(self):
  111. self.cs(0)
  112. self.spi.readinto(self.buf, FLUSH_TX)
  113. self.cs(1)
  114. # power is one of POWER_x defines; speed is one of SPEED_x defines
  115. def set_power_speed(self, power, speed):
  116. setup = self.reg_read(RF_SETUP) & 0b11010001
  117. self.reg_write(RF_SETUP, setup | power | speed)
  118. # length in bytes: 0, 1 or 2
  119. def set_crc(self, length):
  120. config = self.reg_read(CONFIG) & ~(CRCO | EN_CRC)
  121. if length == 0:
  122. pass
  123. elif length == 1:
  124. config |= EN_CRC
  125. else:
  126. config |= EN_CRC | CRCO
  127. self.reg_write(CONFIG, config)
  128. def set_channel(self, channel):
  129. self.reg_write(RF_CH, min(channel, 125))
  130. # address should be a bytes object 5 bytes long
  131. def open_tx_pipe(self, address):
  132. assert len(address) == 5
  133. self.reg_write_bytes(RX_ADDR_P0, address)
  134. self.reg_write_bytes(TX_ADDR, address)
  135. self.reg_write(RX_PW_P0, self.payload_size)
  136. # address should be a bytes object 5 bytes long
  137. # pipe 0 and 1 have 5 byte address
  138. # pipes 2-5 use same 4 most-significant bytes as pipe 1, plus 1 extra byte
  139. def open_rx_pipe(self, pipe_id, address):
  140. assert len(address) == 5
  141. assert 0 <= pipe_id <= 5
  142. if pipe_id == 0:
  143. self.pipe0_read_addr = address
  144. if pipe_id < 2:
  145. self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
  146. else:
  147. self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
  148. self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
  149. self.reg_write(EN_RXADDR, self.reg_read(EN_RXADDR) | (1 << pipe_id))
  150. def start_listening(self):
  151. self.reg_write(CONFIG, self.reg_read(CONFIG) | PWR_UP | PRIM_RX)
  152. self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
  153. if self.pipe0_read_addr is not None:
  154. self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
  155. self.flush_rx()
  156. self.flush_tx()
  157. self.ce(1)
  158. utime.sleep_us(130)
  159. def stop_listening(self):
  160. self.ce(0)
  161. self.flush_tx()
  162. self.flush_rx()
  163. # returns True if any data available to recv
  164. def any(self):
  165. return not bool(self.reg_read(FIFO_STATUS) & RX_EMPTY)
  166. def recv(self):
  167. # get the data
  168. self.cs(0)
  169. self.spi.readinto(self.buf, R_RX_PAYLOAD)
  170. buf = self.spi.read(self.payload_size)
  171. self.cs(1)
  172. # clear RX ready flag
  173. self.reg_write(STATUS, RX_DR)
  174. return buf
  175. # blocking wait for tx complete
  176. def send(self, buf, timeout=500):
  177. self.send_start(buf)
  178. start = utime.ticks_ms()
  179. result = None
  180. while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
  181. result = self.send_done() # 1 == success, 2 == fail
  182. if result == 2:
  183. raise OSError("send failed")
  184. # non-blocking tx
  185. def send_start(self, buf):
  186. # power up
  187. self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
  188. utime.sleep_us(150)
  189. # send the data
  190. self.cs(0)
  191. self.spi.readinto(self.buf, W_TX_PAYLOAD)
  192. self.spi.write(buf)
  193. if len(buf) < self.payload_size:
  194. self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data
  195. self.cs(1)
  196. # enable the chip so it can send the data
  197. self.ce(1)
  198. utime.sleep_us(15) # needs to be >10us
  199. self.ce(0)
  200. # returns None if send still in progress, 1 for success, 2 for fail
  201. def send_done(self):
  202. if not (self.reg_read(STATUS) & (TX_DS | MAX_RT)):
  203. return None # tx not finished
  204. # either finished or failed: get and clear status flags, power down
  205. status = self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
  206. self.reg_write(CONFIG, self.reg_read(CONFIG) & ~PWR_UP)
  207. return 1 if status & TX_DS else 2