0

I didn't write here before, though i get in often to find solutions for my problems with raspberry, so thanks in advance.

I got the following problem with nRF24L01+ radio breakout board. Here is my configuration

Model: Raspberry B+ rev 1.2
Kernel: 4.9.70+
OS: Raspbian GNU/Linux 8 (Jessie)

Problem:

Module nRF24L01+ is connected to SPI channel 0:

MOSI -> MOSI
MISO -> MISO
SCK -> SCK
CE0 -> CSN

I left CE floating on nRF but it doesn't matter until i only try read/write on registers), i use wiringPi (through pip3 it installed well) on Python 3. Simplest commands (avoid syntax error please, i am writing those without reading them on the script, though i don't get syntax errors):

import wiringpi
wiringpi.wiringPiSetupGpio()
wiringpi.wiringPiSPISetupMode(0, speed, 2)

//i wrote speed cause i tried any frequency between 0,5 to 8 MHz

//the 2 is the mode, i will explain soon why i chose 2 though i tried also the others

wiringpi.wiringPiSPIDataRW(0, b'\x00\xff')

//good, it returns two bytes, the right status 0x0e and the right config register value, which is 0x08

wiringpi.wiringPiSPIDataRW(0, b'\x20\x0B')

//try to write config register to go power on and rx mode... weird behavior, it again return correct status but the second byte is 0xe7, there's no reason to have that, it should return 0x00 but i go on

wiringpi.wiringPiSPIDataRW(0, b'\x00\xff')

//try to read back config register to see if it has been changed

//it returns 0x0e status ok but again 0x08 so no, config hasn't been written

I am debugging it with tests for two days, i will try to say them all but i don't remember everything i guess:

I tired SPI with raspi master and a picMicro as slave, all fine.

I tried SPI with picMicro master and nRF slave with the same procedure of read config register/write 0x0b in it/read back to see changes, all fine, it changes. Here, i found that SPI mode of raspi has to be 2 to interact with the nRF since also the pic has to be set to the same to interact right with nRF, though as i said i tried also other modes. Plus, i noticed on the pic, i had to change the sampling time to middle of clock period instead of the end of it (or the opposite, i don't remember) to make it work.

I tried using spidev with identical results.

I tried using python2 with identical results.

I tried a fresh installation of OS with same results.

I guess those are the noticeable tests to be said. From those i guessed something:

It cannot be a matter of connection (or it won't reply with the right status and config values)

I guess it is a matter of the sampling time point, if true it should be just a matter of sampling on received bits but if i try to write config with the raspi then connect the pic to nRF without turning it off and read config, it hasn't been written by raspi (still returning 0x08) and i don't know how to check it since i didn't find a way to change it on raspi.

I don't have more options, so if someone of you got suggestions, i will be happy to try. Unfortunately at work i don't have enough free time to turn raspi on and check signals with the oscilloscope, it will be much better i am sure, i hope i can in next days.

I know i could use a pic for translation in between raspi and nRF since the micro has 2 SPI and also i2c (tried with success with raspi) but it will be a "patch" not a solution and also a bottleneck for communication speed. Thanks for reading my long post and also for future suggestions, hi again, Alessandro

  • I would connect CE and try again. – joan Jan 5 '18 at 13:27
  • Please, read datasheet before reply. It is useless on SPI communications. Though it doesn't change anything – Alessandro Perla Jan 6 '18 at 10:01
  • Does that explain why I have working code and you do not? – joan Jan 6 '18 at 11:26
  • Add some informations please about your working configuration, i can tie it to v+ but it still doesn't work – Alessandro Perla Jan 6 '18 at 14:56
2

I have just hooked up a couple of the radios to an original Pi B and a Pi 3.

The units are connected via the main SPI CE0 and CE is connected to GPIO4.

The following code works.

#!/usr/bin/env python

import time
import pigpio

class NRF24:
   """
   Note that RX and TX addresses must match

   Note that communication channels must match:

   Note that payload size must match:

   The following table describes how to configure the operational
   modes.

   +----------+--------+---------+--------+-----------------------------+
   |Mode      | PWR_UP | PRIM_RX | CE pin | FIFO state                  |
   +----------+--------+---------+--------+-----------------------------+
   |RX mode   |  1     |  1      |  1     | ---                         |
   +----------+--------+---------+--------+-----------------------------+
   |TX mode   |  1     |  0      |  1     | Data in TX FIFOs. Will empty|
   |          |        |         |        | all levels in TX FIFOs      |
   +----------+--------+---------+--------+-----------------------------+
   |TX mode   |  1     |  0      |  >10us | Data in TX FIFOs. Will empty|
   |          |        |         |  pulse | one level in TX FIFOs       |
   +----------+--------+---------+--------+-----------------------------+
   |Standby-II|  1     |  0      |  1     | TX FIFO empty               |
   +----------+--------+---------+--------+-----------------------------+
   |Standby-I |  1     |  ---    |  0     | No ongoing transmission     |
   +----------+--------+---------+--------+-----------------------------+
   |Power Down|  0     |  ---    |  ---   | ---                         |
   +----------+--------+---------+--------+-----------------------------+
   """

   SPI_MAIN_CE0 = 0
   SPI_MAIN_CE1 = 1
   SPI_AUX_CE0  = 2
   SPI_AUX_CE1  = 3
   SPI_AUX_CE2  = 4

   TX = 0
   RX = 1

   ACK_PAYLOAD = -1
   DYNAMIC_PAYLOAD = 0
   MIN_PAYLOAD = 1
   MAX_PAYLOAD = 32

   def _NRFXfer(self, data):

      b, d = self.pi.spi_xfer(self.spih, data)

      return d

   def _NRFCommand(self, arg):

      if type(arg) is not list:
         arg = [arg]

      return self._NRFXfer(arg)

   def _NRFReadReg(self, reg, count):

      return self._NRFXfer([reg] + [0]*count)[1:]

   def _NRFWriteReg(self, reg, arg):
      """
      Write arg (which may be one or more bytes) to reg.

      This function is only permitted in a powerdown or
      standby mode.
      """
      if type(arg) is not list:
         arg = [arg]

      self._NRFXfer([self.W_REGISTER | reg] + arg)

   def _configurePayload(self):
      if self.payload >= self.MIN_PAYLOAD: # fixed payload
         self._NRFWriteReg(self.RX_PW_P0, self.payload)
         self._NRFWriteReg(self.RX_PW_P1, self.payload)
         self._NRFWriteReg(self.DYNPD, 0)
         self._NRFWriteReg(self.FEATURE, 0)
      else: # dynamic payload
         self._NRFWriteReg(self.DYNPD, self.DPL_P0 | self.DPL_P1)
         if self.payload  == self.ACK_PAYLOAD:
            self._NRFWriteReg(self.FEATURE, self.EN_DPL | self.EN_ACK_PAY)
         else:
            self._NRFWriteReg(self.FEATURE, self.EN_DPL)

   def __init__(self,
      pi,                       # pigpio Pi connection
      CE,                       # GPIO for chip enable
      spi_channel=SPI_MAIN_CE0, # SPI channel
      spi_speed=50e3,           # SPI bps
      mode=RX,                  # primary mode (RX or TX)
      channel=1,                # radio channel
      payload=8,                # message size in bytes
      pad=32,                   # value used to pad short messages
      address_bytes=5,          # RX/TX address length in bytes
      crc_bytes=1               # number of CRC bytes
         ):
      """
      Instantiate with the Pi to which the card reader is connected.

      Optionally the SPI channel may be specified.  The default is
      main SPI channel 0.

      The following constants may be used to define the channel:

         SPI_MAIN_CE0 - main SPI channel 0
         SPI_MAIN_CE1 - main SPI channel 1
         SPI_AUX_CE0  - aux  SPI channel 0
         SPI_AUX_CE1  - aux  SPI channel 1
         SPI_AUX_CE2  - aux  SPI channel 2
      """

      self.pi = pi

      assert 0 <= CE <= 31

      self.CE = CE

      pi.set_mode(CE, pigpio.OUTPUT)

      self.unsetCE()

      assert NRF24.SPI_MAIN_CE0 <= spi_channel <= NRF24.SPI_AUX_CE2

      assert 32000 <= spi_speed <= 10e6

      if spi_channel < NRF24.SPI_AUX_CE0:
         self.spih = pi.spi_open(spi_channel, int(spi_speed))
      else:
         self.spih = pi.spi_open(
            spi_channel - NRF24.SPI_AUX_CE0, int(spi_speed), NRF24._AUX_SPI)

      self.setChannel(channel)

      self.setPayload(payload)

      self.setPadValue(pad)

      self.setAddressBytes(address_bytes)

      self.setCRCBytes(crc_bytes)

      self.PTX = 0

      self.powerDown()

      self._NRFWriteReg(self.SETUP_RETR, 0b11111)

      self.flushRX()
      self.flushTX()

      self.powerUpRX()

   def setChannel(self, channel):
      assert 0 <= channel <= 125
      self.channel = channel # frequency (2400 + channel) MHz
      self._NRFWriteReg(self.RF_CH, self.channel)

   def setPayload(self, payload):
      assert self.ACK_PAYLOAD <= payload <= self.MAX_PAYLOAD
      self.payload = payload # 0 is dynamic payload
      self._configurePayload()

   def setPadValue(self, pad):
      try:
         self.pad = ord(pad)
      except:
         self.pad = pad
      assert 0 <= self.pad <= 255

   def setAddressBytes(self, address_bytes):
      assert 3 <= address_bytes <= 5
      self.width = address_bytes
      self._NRFWriteReg(self.SETUP_AW, self.width - 2)

   def setCRCBytes(self, crc_bytes):
      assert 1 <= crc_bytes <= 2
      if crc_bytes == 1:
         self.CRC = 0
      else:
         self.CRC = self.CRCO

   def showRegisters(self):
      print(self.format_CONFIG())
      print(self.format_EN_AA())
      print(self.format_EN_RXADDR())
      print(self.format_SETUP_AW())
      print(self.format_SETUP_RETR())
      print(self.format_RF_CH())
      print(self.format_RF_SETUP())
      print(self.format_STATUS())
      print(self.format_OBSERVE_TX())
      print(self.format_RPD())
      print(self.format_RX_ADDR_PX())
      print(self.format_TX_ADDR())
      print(self.format_RX_PW_PX())
      print(self.format_FIFO_STATUS())
      print(self.format_DYNPD())
      print(self.format_FEATURE())

   def _setFixedWidth(self, msg, width, pad):
      msg = list(msg)
      if len(msg) >= width:
         return msg[:width]
      msg.extend([pad]*(width-len(msg)))
      return msg

   def send(self, data):

      status = self.getStatus()

      if status & (self.TX_FULL | self.MAX_RT):
         self.flushTX()

      if self.payload >= self.MIN_PAYLOAD: # fixed payload
         data = self._setFixedWidth(data, self.payload, self.pad)

      self._NRFCommand([self.W_TX_PAYLOAD] + data)

      self.powerUpTX()

   def ack_payload(self, data):
      self._NRFCommand([self.W_ACK_PAYLOAD] + data)

   def setLocalAddress(self, laddr): 

      addr = self._setFixedWidth(laddr, self.width, self.pad)

      self.unsetCE()

      self._NRFWriteReg(self.RX_ADDR_P1, addr)

      self.setCE()

   def setRemoteAddress(self, raddr): 

      addr = self._setFixedWidth(raddr, self.width, self.pad)

      self.unsetCE();

      self._NRFWriteReg(self.TX_ADDR, addr)
      self._NRFWriteReg(self.RX_ADDR_P0, addr) # Needed for auto acks

      self.setCE()

   def dataReady(self):

      status = self.getStatus()

      if status & self.RX_DR:
         return True

      status = self._NRFReadReg(self.FIFO_STATUS, 1)[0]

      if status & self.FRX_EMPTY:
         return False
      else:
         return True

   def isSending(self):

      if self.PTX > 0:
         status = self.getStatus()

         if  status & (self.TX_DS | self.MAX_RT):
            self.powerUpRX()
            return False

         return True

      return False

   def getPayload(self):

      if self.payload < self.MIN_PAYLOAD: # dynamic payload
         bytes = self._NRFCommand([self.R_RX_PL_WID, 0])[1]
      else: # fixed payload
         bytes = self.payload

      d = self._NRFReadReg(self.R_RX_PAYLOAD, bytes)

      self.unsetCE() # added

      self._NRFWriteReg(self.STATUS, self.RX_DR)

      self.setCE() # added

      return d

   def getStatus(self):

      return self._NRFCommand(self.NOP)[0]

   def powerUpTX(self):

      self.unsetCE()

      self.PTX = 1

      config = self.EN_CRC | self.CRC | self.PWR_UP

      self._NRFWriteReg(self.CONFIG, config)

      self._NRFWriteReg(self.STATUS, self.RX_DR | self.TX_DS | self.MAX_RT)

      self.setCE()

   def powerUpRX(self):

      self.unsetCE()

      self.PTX = 0

      config = self.EN_CRC | self.CRC | self.PWR_UP | self.PRIM_RX

      self._NRFWriteReg(self.CONFIG, config)

      self._NRFWriteReg(self.STATUS, self.RX_DR | self.TX_DS | self.MAX_RT)

      self.setCE()

   def powerDown(self):

      self.unsetCE()

      self._NRFWriteReg(self.CONFIG, self.EN_CRC | self.CRC)

   def setCE(self):

      self.pi.write(self.CE, 1)

   def unsetCE(self):

      self.pi.write(self.CE, 0)

   def flushRX(self):

      self._NRFCommand(self.FLUSH_RX)

   def flushTX(self):

      self._NRFCommand(self.FLUSH_TX)

   _AUX_SPI=(1<<8)

   R_REGISTER          = 0x00 # reg in bits 0-4, read 1-5 bytes
   W_REGISTER          = 0x20 # reg in bits 0-4, write 1-5 bytes
   R_RX_PL_WID         = 0x60
   R_RX_PAYLOAD        = 0x61 # read 1-32 bytes
   W_TX_PAYLOAD        = 0xA0 # write 1-32 bytes
   W_ACK_PAYLOAD       = 0xA8 # pipe in bits 0-2, write 1-32 bytes
   W_TX_PAYLOAD_NO_ACK = 0xB0 # no ACK, write 1-32 bytes
   FLUSH_TX            = 0xE1
   FLUSH_RX            = 0xE2
   REUSE_TX_PL         = 0xE3
   NOP                 = 0xFF # no operation

   CONFIG      = 0x00
   EN_AA       = 0x01
   EN_RXADDR   = 0x02
   SETUP_AW    = 0x03
   SETUP_RETR  = 0x04
   RF_CH       = 0x05
   RF_SETUP    = 0x06
   STATUS      = 0x07
   OBSERVE_TX  = 0x08
   RPD         = 0x09
   RX_ADDR_P0  = 0x0A
   RX_ADDR_P1  = 0x0B
   RX_ADDR_P2  = 0x0C
   RX_ADDR_P3  = 0x0D
   RX_ADDR_P4  = 0x0E
   RX_ADDR_P5  = 0x0F
   TX_ADDR     = 0x10
   RX_PW_P0    = 0x11
   RX_PW_P1    = 0x12
   RX_PW_P2    = 0x13
   RX_PW_P3    = 0x14
   RX_PW_P4    = 0x15
   RX_PW_P5    = 0x16
   FIFO_STATUS = 0x17
   DYNPD       = 0x1C
   FEATURE     = 0x1D

   # CONFIG

   MASK_RX_DR =  1 << 6
   MASK_TX_DS =  1 << 5
   MASK_MAX_RT = 1 << 4
   EN_CRC =      1 << 3 # default
   CRCO =        1 << 2
   PWR_UP =      1 << 1
   PRIM_RX =     1 << 0

   def format_CONFIG(self):

      v = self._NRFReadReg(self.CONFIG, 1)[0]

      s = "CONFIG: "

      if v & self.MASK_RX_DR:
         s += "no RX_DR IRQ, "
      else:
         s += "RX_DR IRQ, "

      if v & self.MASK_TX_DS:
         s += "no TX_DS IRQ, "
      else:
         s += "TX_DS IRQ, "

      if v & self.MASK_MAX_RT:
         s += "no MAX_RT IRQ, "
      else:
         s += "MAX_RT IRQ, "

      if v & self.EN_CRC:
         s += "CRC on, "
      else:
         s += "CRC off, "

      if v & self.CRCO:
         s += "CRC 2 byte, "
      else:
         s += "CRC 1 byte, "

      if v & self.PWR_UP:
         s += "Power up, "
      else:
         s += "Power down, "

      if v & self.PRIM_RX:
         s += "RX"
      else:
         s += "TX"

      return s

   # EN_AA

   ENAA_P5 = 1 << 5 # default
   ENAA_P4 = 1 << 4 # default
   ENAA_P3 = 1 << 3 # default
   ENAA_P2 = 1 << 2 # default
   ENAA_P1 = 1 << 1 # default
   ENAA_P0 = 1 << 0 # default

   def format_EN_AA(self):

      v = self._NRFReadReg(self.EN_AA, 1)[0]

      s = "EN_AA: "

      for i in range(6):
         if v & (1<<i):
            s += "P{}:ACK ".format(i)
         else:
            s += "P{}:no ACK ".format(i)

      return s

   # EN_RXADDR

   ERX_P5 = 1 << 5
   ERX_P4 = 1 << 4
   ERX_P3 = 1 << 3
   ERX_P2 = 1 << 2
   ERX_P1 = 1 << 1 # default
   ERX_P0 = 1 << 0 # default

   def format_EN_RXADDR(self):

      v = self._NRFReadReg(self.EN_RXADDR, 1)[0]

      s = "EN_RXADDR: "

      for i in range(6):
         if v & (1<<i):
            s += "P{}:on ".format(i)
         else:
            s += "P{}:off ".format(i)

      return s

   # SETUP_AW

   AW_3 = 1
   AW_4 = 2
   AW_5 = 3 # default

   def format_SETUP_AW(self):

      v = self._NRFReadReg(self.SETUP_AW, 1)[0]

      s = "SETUP_AW: address width bytes "

      if v == self.AW_3:
         s += "3"
      elif v == self.AW_4:
         s += "4"
      elif v == self.AW_5:
         s += "5"
      else:
         s += "invalid"

      return s

   # SETUP_RETR

   # ARD 7-4
   # ARC 3-0

   def format_SETUP_RETR(self):

      v = self._NRFReadReg(self.SETUP_RETR, 1)[0]

      ard = (((v>>4)&15)*250)+250
      arc = v & 15
      s = "SETUP_RETR: retry delay {} us, retries {}".format(ard, arc)

      return s

   # RF_CH

   # RF_CH 6-0

   def format_RF_CH(self):

      v = self._NRFReadReg(self.RF_CH, 1)[0]

      s = "RF_CH: channel {}".format(v&127)

      return s

   # RF_SETUP

   CONT_WAVE  =  1 << 7
   RF_DR_LOW  =  1 << 5
   PLL_LOCK   =  1 << 4
   RF_DR_HIGH =  1 << 3
   # RF_PWR  2-1

   def format_RF_SETUP(self):

      v = self._NRFReadReg(self.RF_SETUP, 1)[0]

      s = "RF_SETUP: "

      if v & self.CONT_WAVE:
         s += "continuos carrier on, "
      else:
         s += "no continuous carrier, "

      if v & self.PLL_LOCK:
         s += "force PLL lock on, "
      else:
         s += "no force PLL lock, "

      dr = 0

      if v & self.RF_DR_LOW:
         dr += 2

      if v & self.RF_DR_HIGH:
         dr += 1

      if dr == 0:
         s += "1 Mbps, "
      elif dr == 1:
         s += "2 Mbps, "
      elif dr == 2:
         s += "250 kbps, "
      else:
         s += "illegal speed, "

      pwr = (v>>1) & 3

      if pwr == 0:
         s += "-18 dBm"
      elif pwr == 1:
         s += "-12 dBm"
      elif pwr == 2:
         s += "-6 dBm"
      else:
         s += "0 dBm"

      return s

   # STATUS

   RX_DR      =  1 << 6
   TX_DS      =  1 << 5
   MAX_RT     =  1 << 4
   # RX_P_NO 3-1
   TX_FULL    =  1 << 0

   def format_STATUS(self):

      v = self._NRFReadReg(self.STATUS, 1)[0]

      s = "STATUS: "

      if v & self.RX_DR:
         s += "RX data, "
      else:
         s += "no RX data, "

      if v & self.TX_DS:
         s += "TX ok, "
      else:
         s += "no TX, "

      if v & self.MAX_RT:
         s += "TX retries bad, "
      else:
         s += "TX retries ok, "

      p = (v>>1)&7

      if p < 6:
         s += "pipe {} data, ".format(p)
      elif p == 6:
         s += "PIPE 6 ERROR, "
      else:
         s += "no pipe data, "

      if v & self.TX_FULL:
         s += "TX FIFO full"
      else:
         s += "TX FIFO not full"

      return s

   # OBSERVE_TX

   # PLOS_CNT 7-4
   # ARC_CNT 3-0

   def format_OBSERVE_TX(self):

      v = self._NRFReadReg(self.OBSERVE_TX, 1)[0]

      plos = (v>>4)&15
      arc = v & 15
      s = "OBSERVE_TX: lost packets {}, retries {}".format(plos, arc)

      return s

   # RPD

   # RPD 1 << 0

   def format_RPD(self):

      v = self._NRFReadReg(self.RPD, 1)[0]

      s = "RPD: received power detector {}".format(v&1)

      return s

   # RX_ADDR_P0 - RX_ADDR_P5

   def _byte2hex(self, s):

      return ":".join("{:02x}".format(c) for c in s)

   def format_RX_ADDR_PX(self):

      p0 = self._NRFReadReg(self.RX_ADDR_P0, 5)
      p1 = self._NRFReadReg(self.RX_ADDR_P1, 5)
      p2 = self._NRFReadReg(self.RX_ADDR_P2, 1)[0]
      p3 = self._NRFReadReg(self.RX_ADDR_P3, 1)[0]
      p4 = self._NRFReadReg(self.RX_ADDR_P4, 1)[0]
      p5 = self._NRFReadReg(self.RX_ADDR_P5, 1)[0]

      s  = "RX ADDR_PX: "
      s += "P0=" + self._byte2hex(p0) + " "
      s += "P1=" + self._byte2hex(p1) + " "
      s += "P2={:02x} ".format(p2)
      s += "P3={:02x} ".format(p3)
      s += "P4={:02x} ".format(p4)
      s += "P5={:02x}".format(p5)

      return s

   # TX_ADDR

   def format_TX_ADDR(self):

      p0 = self._NRFReadReg(self.TX_ADDR, 5)

      s  = "TX_ADDR: " + self._byte2hex(p0)

      return s

   # RX_PW_P0 - RX_PW_P5

   def format_RX_PW_PX(self):

      p0 = self._NRFReadReg(self.RX_PW_P0, 1)[0]
      p1 = self._NRFReadReg(self.RX_PW_P1, 1)[0]
      p2 = self._NRFReadReg(self.RX_PW_P2, 1)[0]
      p3 = self._NRFReadReg(self.RX_PW_P3, 1)[0]
      p4 = self._NRFReadReg(self.RX_PW_P4, 1)[0]
      p5 = self._NRFReadReg(self.RX_PW_P5, 1)[0]

      s = "RX_PW_PX: "
      s += "P0={} ".format(p0)
      s += "P1={} ".format(p1)
      s += "P2={} ".format(p2)
      s += "P3={} ".format(p3)
      s += "P4={} ".format(p4)
      s += "P5={} ".format(p5)

      return s

   # FIFO_STATUS

   FTX_REUSE = 1 << 6
   FTX_FULL =  1 << 5
   FTX_EMPTY = 1 << 4
   FRX_FULL =  1 << 1
   FRX_EMPTY = 1 << 0

   def format_FIFO_STATUS(self):

      v = self._NRFReadReg(self.FIFO_STATUS, 1)[0]

      s = "FIFO_STATUS: "

      if v & self.FTX_REUSE:
         s += "TX reuse set, "
      else:
         s += "TX reuse not set, "

      if v & self.FTX_FULL:
         s += "TX FIFO full, "
      elif v & self.FTX_EMPTY:
         s += "TX FIFO empty, "
      else:
         s += "TX FIFO has data, "

      if v & self.FRX_FULL:
         s += "RX FIFO full, "
      elif v & self.FRX_EMPTY:
         s += "RX FIFO empty"
      else:
         s += "RX FIFO has data"

      return s

   # DYNPD

   DPL_P5 = 1 << 5
   DPL_P4 = 1 << 4
   DPL_P3 = 1 << 3
   DPL_P2 = 1 << 2
   DPL_P1 = 1 << 1
   DPL_P0 = 1 << 0

   def format_DYNPD(self):

      v = self._NRFReadReg(self.DYNPD, 1)[0]

      s = "DYNPD: "

      for i in range(6):
         if v & (1<<i):
            s += "P{}:on ".format(i)
         else:
            s += "P{}:off ".format(i)

      return s

   # FEATURE

   EN_DPL =     1 << 2
   EN_ACK_PAY = 1 << 1
   EN_DYN_ACK = 1 << 0

   def format_FEATURE(self):

      v = self._NRFReadReg(self.FEATURE, 1)[0]

      s = "FEATURE: "

      if v & self.EN_DPL:
         s += "Dynamic payload on, "
      else:
         s += "Dynamic payload off, "

      if v & self.EN_ACK_PAY:
         s += "ACK payload on, "
      else:
         s += "ACK payload off, "

      if v & self.EN_DYN_ACK:
         s += "W_TX_PAYLOAD_NOACK on"
      else:
         s += "W_TX_PAYLOAD_NOACK off"

      return s

if __name__ == "__main__":

   import sys
   import time
   import pigpio
   import NRF24

   if len(sys.argv) > 1:
      SENDING = False
   else:
      SENDING = True

   pi = pigpio.pi()
   if not pi.connected:
      exit()

   end_time = time.time() + 60

   nrf = NRF24.NRF24(pi, CE=4, payload=NRF24.NRF24.ACK_PAYLOAD, pad='*', address_bytes=3, crc_bytes=2)

   nrf.showRegisters();

   if SENDING:

      count = 1

      nrf.setLocalAddress("h1")
      nrf.setRemoteAddress("h2")

      while time.time() < end_time:
         print(nrf.format_FIFO_STATUS())
         print(nrf.format_OBSERVE_TX())
         if not nrf.isSending():
            print("tx {}".format(count))
            nrf.send(map(ord, "msg:{:d}".format(count)))
            count += 1
         time.sleep(0.5)

   else:

      nrf.setLocalAddress("h2")
      nrf.setRemoteAddress("h1")

      while time.time() < end_time:
         print(nrf.format_FIFO_STATUS())
         #print(nrf.format_OBSERVE_TX())
         while nrf.dataReady():
            print("rx: {}".format(nrf.getPayload()))
         time.sleep(0.5)

   pi.spi_close(nrf.spih)

   pi.stop()

Both Pis were running the pigpio daemon.

sudo pigpiod

On one Pi I used the command ./NRF24.py rx

On the other Pi I used the command ./NRF24.py

The first few receiver debugs.

$ ./NRF24.py rx
CONFIG: RX_DR IRQ, TX_DS IRQ, MAX_RT IRQ, CRC on, CRC 2 byte, Power up, RX
EN_AA: P0:ACK P1:ACK P2:ACK P3:ACK P4:ACK P5:ACK 
EN_RXADDR: P0:on P1:on P2:off P3:off P4:off P5:off 
SETUP_AW: address width bytes 3
SETUP_RETR: retry delay 500 us, retries 15
RF_CH: channel 1
RF_SETUP: no continuous carrier, no force PLL lock, 2 Mbps, 0 dBm
STATUS: no RX data, no TX, TX retries ok, no pipe data, TX FIFO not full
OBSERVE_TX: lost packets 0, retries 0
RPD: received power detector 0
RX ADDR_PX: P0=e7:e7:e7:e7:e7 P1=c2:c2:c2:c2:c2 P2=c3 P3=c4 P4=c5 P5=c6
TX_ADDR: e7:e7:e7:e7:e7
RX_PW_PX: P0=0 P1=0 P2=0 P3=0 P4=0 P5=0 
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
DYNPD: P0:on P1:on P2:off P3:off P4:off P5:off 
FEATURE: Dynamic payload on, ACK payload on, W_TX_PAYLOAD_NOACK off
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data
rx: msg:1
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data
rx: msg:2
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data
rx: msg:3
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data
rx: msg:4
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data
rx: msg:5
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO has data

The first few transmitter debugs.

$ ./NRF24.py 
CONFIG: RX_DR IRQ, TX_DS IRQ, MAX_RT IRQ, CRC on, CRC 2 byte, Power up, RX
EN_AA: P0:ACK P1:ACK P2:ACK P3:ACK P4:ACK P5:ACK 
EN_RXADDR: P0:on P1:on P2:off P3:off P4:off P5:off 
SETUP_AW: address width bytes 3
SETUP_RETR: retry delay 500 us, retries 15
RF_CH: channel 1
RF_SETUP: no continuous carrier, no force PLL lock, 2 Mbps, 0 dBm
STATUS: no RX data, no TX, TX retries ok, no pipe data, TX FIFO not full
OBSERVE_TX: lost packets 0, retries 0
RPD: received power detector 0
RX ADDR_PX: P0=e7:e7:e7:e7:e7 P1=c2:c2:c2:c2:c2 P2=c3 P3=c4 P4=c5 P5=c6
TX_ADDR: e7:e7:e7:e7:e7
RX_PW_PX: P0=0 P1=0 P2=0 P3=0 P4=0 P5=0 
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
DYNPD: P0:on P1:on P2:off P3:off P4:off P5:off 
FEATURE: Dynamic payload on, ACK payload on, W_TX_PAYLOAD_NOACK off
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 1
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 2
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 3
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 4
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 5
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0
tx 6
FIFO_STATUS: TX reuse not set, TX FIFO empty, RX FIFO empty
OBSERVE_TX: lost packets 0, retries 0

I used the following connections.

nRF24L01
pin side
+---+----------------------
|       *    *
+---+
|7|8|
+-+-+
|5|6|
+-+-+
|3|4|
+-+-+
|1|2|
+-+-+----------------------

nRF24L01             Pi
pin               pin  GPIO
 1   GND   <--->   6     -       GND
 2   3.3V  <--->   1     -       3V3
 3   CE    <--->   7     4
 4   CSN   <--->   24    8
 5   SCKL  <--->   23   11
 6   MOSI  <--->   19   10
 7   MISO  <--->   21    9
 8   IRQ   <--->   N/C   -
  • Okay humm. Thanks for the code, i am gonna try it, especially the daemon part. Anyway: – Alessandro Perla Jan 6 '18 at 22:24
  • Which SPI library are you using (subclass of pigpio?) i am not getting wether you connected it, i mean the CE you declare, is CE on nRF, or CSN? The communication speed is 50kpbs, does it work with more? Can you setup just the operation I'm trying to do, i.e. read config register, set it to 0x0B and read it again? Many thanks – Alessandro Perla Jan 6 '18 at 22:39
  • 1
    @AlessandroPerla I use pigpio's own SPI driver. I have added the connections I made. I use 50 kbps for testing so I can use piscope to see the signals. You can use any speed you want. If I get time I'll look at the change you suggest. – joan Jan 6 '18 at 23:12
  • I'm gonna try that library to see if the problem persists, thanks again – Alessandro Perla Jan 7 '18 at 1:57
  • Hi again. For now, i only had time to try the library and i found it works. I can read config, set it as 0x0b and read it back with correct behavior. Now i will try it also with picMicros but i got no reason to think it won't work too (maybe by changing clock polarity and sampling time but luckily micros are pretty flexible to adapt). Thank you again, still i can't understand what went wrong with the libraries i was trying before. Just to be complete, CE on nRF was still floating – Alessandro Perla Jan 7 '18 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.