This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Loss of connection between rf24 transmitter & receiver

Loss of comms between nRF24L01+ transmitter and receiver after successful data transfer.

One rf24 is configured as a PTX (sensor device) communicating in a simple point-point link with a second in PRX mode (base unit) over pipe 0. Both are connected to a small

microcomputer (not an Arduino). Example Code used for them to ping-pong between each other works well. But modified code when used in this Tx ->Rx mode fails after a random period?

My intended operational mode is for the PTX to send a radio code when a sensor is triggered - which could be every few minutes to every few hours.  At first this works on the bench with

PTX and PRX side by side, but despite a sequence of successful transmissions over a period between 5 minutes to 30 minutes, the PTX generally freezes first, sometime it's the Base PRX

which freezes first.  So my code seems to work ok until it suddendly doesn't. As far as I can tell, my code correctly implements the RF24 state diagrams, the registers appear to be correctly 

configured and the TX-FIFO & RX-FIFO are flushed as necessary. After device power up I do leave the PTX in Tx mode and the PRX in Rx mode the whole time and don't set the

power-down but? This random freezing of communication suggests a timing issue somewhere, but I've tried various code modifications without success. 

Question: Could there be an un-documented issue with these radios that may explain the sudden freezing of communication after a sequence of good operation, or am I missing

sometime more obvious.  Your help would be greatly appreciated!

I can send the configs if there's not an obvious answer.

thanks

Parents
  • Hi,

     

    Can you share your configuration? Address used, crc configuration, and so forth.

    As far as I can tell, my code correctly implements the RF24 state diagrams, the registers appear to be correctly 

    configured and the TX-FIFO & RX-FIFO are flushed as necessary.

    Do you have a register dump of the expected values, and when the issue occurs?

     

    Kind regards,

    Håkon

  • Morning Håkon,

    I decided to explore my problem further over the weekend before replying and have some extra information for you. Firstly, I don't have a register dump - but I'm fairly confident that the registers have the correct values. Each RF24 is initialised with the same subroutine code: which includes setting the CRC for 2 bytes:

    def init_rf24_radio():
    utime.sleep_ms(5)
    reg_write(SETUP_AW,0b11) # addr width to 5 bytes
    res = reg_read(SETUP_AW,nop)
    if res != 0b11:
    display.scroll("E1") # check comms with hw
    sleep(1000)
    reg_write(EN_AA,0x01) # enable auto ack on pipe0 only
    reg_write(SETUP_RETR,0x68) # auto re-tx delay 1750us & count 8
    #reg_write(SETUP_RETR,0xFF) # auto re-tx delay 4ms & count 15 attempts
    reg_write(RF_CH,0x6C) # rf chan 108
    reg_write(RF_SETUP, 0x22) # 250KB, -12dBm low power
    #reg_write(RF_SETUP, 0x26) # 250KB, 0dBm max power
    reg_write(DYNPD,0) # disable dynamic payloads
    set_crc(2) # CRC 2 bytes
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags
    flush_rx()
    flush_tx()

    My code tries to keep both units in Standby-I mode, so neither uses the PWR_UP = 0 command.

    I tried reducing the SETUP_RETR values (above) from their maximum, but I don't think this changed matters. The CRC subr is called, but as I only use 2 bytes, I could just replace with it a single command, but the CRC subr is:

    def set_crc(length):
    config = reg_read(CONFIG,nop) & ~(CRCO | EN_CRC)
    if length == 0:
    pass
    elif length == 1:
    config |= EN_CRC
    else:
    config |= EN_CRC | CRCO
    reg_write(CONFIG, config)

    Secondly, I reduced the code in both the Sensor (PTX) and Base unit (PRX) and run just the RF24 relevant code - and this *seemed to have worked*  - well as least kept the RF24 link up in point-point mode for intervals of up to 1 hour.  I had my Sensor unit send one (3 byte) transmission every hour. ....This apparent progress led me to realize an important admission from my original problem description: Namely  that my base unit has a second different radio transmitting source, also working on the 2.4GHz band, but not on the same channel - RF24 chan is 108 (2508MHz) and the 2nd radio on chan 7 (2407MHz).  This led me to change my code so that instead of having both radios simultaneously receiving/transmitting, the Base Unit now disables the 2nd radio while the main code loop allows the RF24 to receive (listen) for an incoming code, and then when one is received, the RF24 is stopped listening and the 2nd radio turned on long just enough to transmit its code before being switched off again for the RF24 to go back into its listening mode.  So far.. as of this morning.. the Sensor is working in a stable manner, succesfully transmitting a code every hour to the Base station ......

    However,

    i) Given that I haven't yet had the time to run this for, say, 24 hours between  RF24 code transmissions, I'm not yet confident that the RF24 link will stay up that long without any activity. My hope is that the RF24 system could go for days between brief transmissions.

    2) Also, although I now suspect it, I have no understanding of how the Base unit's second radio might interfere with RF24 radios.  The pattern was that it's the Sensor unit which freezes far more often than the Base unit (although both are side by side on the bench within radio range of the second radio system during this development phase).

    3) Thirdly, I use the following subroutines to set the RF24 radios into Tx or Rx mode. But I've added the "open_tx/rx" and 'start_listening/stop_listening'  subrs into the start of the Main loop code.......I think that this helps but I'm not sure! I'd welcome your advice on this please.

    PRX Base Unit :

    A1 = b'\x78\x78\x78\x78\x78'

    # RF24 Base unit starts in Rx mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) | PWR_UP)) # set PUP
    sleep(2) # wait for 1.5msec start up time
    # now in Standby-I mode
    reg_write(CONFIG,reg_read(CONFIG,nop) | PRIM_RX) # Set RX mode
    utime.sleep_us(150) # wait for TX setting time
    open_rx_pipe(A1)
    start_listening()

    def open_rx_pipe(addr):
    #EN_AA & SETUP_AW already set in init_radio for pipe0 & 5 byte addr width
    reg_write(EN_RXADDR,0x01) # enable data pipe 0
    reg_write(RX_PW_P0,payload_size) # RX payload bytes in pipe0
    reg_write_bytes(RX_ADDR_P0,addr) # set pipe0 rx addr

    def start_listening():
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags extra
    flush_rx()
    flush_tx()
    pin12.write_digital(1) ### set CE Chip Enable to start active RX mode ###
    utime.sleep_us(150) # wait Rx setting time

    PTX Sensor Unit :

    A1 = b'\x78\x78\x78\x78\x78'

    # RF24 Sensor unit starts in Tx mode
    # PUP & set Tx mode, then go into Standby I mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) | PWR_UP)) # set PUP
    sleep(2) # wait for 1.5msec start up time
    # now in Standby-I mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) & ~PRIM_RX)) # set TX mode
    utime.sleep_us(150) # wait for TX setting time

    def open_tx_pipe(addr):
    #EN_AA & SETUP_AW already set in init_radio for pipe0 & 5 byte addr width
    reg_write(RX_PW_P0,payload_size) # RX payload bytes in pipe0
    reg_write_bytes(RX_ADDR_P0,addr) # set pipe0 rx addr
    reg_write_bytes(TX_ADDR,addr) # set tx addr to same

    def stop_listening():
    pin12.write_digital(0) ### reset CE Chip Enable ###
    utime.sleep_us(150)
    # returned to Standby-I mode
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags extra
    flush_rx()
    flush_tx()

    def flush_rx():
    buf_out[0] = FLUSH_RX
    pin16.write_digital(0)
    spi.write_readinto(buf_out,buf_in)
    pin16.write_digital(1)

    def flush_tx():
    buf_out[0] = FLUSH_TX
    pin16.write_digital(0)
    spi.write_readinto(buf_out,buf_in)
    pin16.write_digital(1)

    I hope that this is enough information for you to assess my problem, but please let me know if not.  Thank you again for looking into this for me.

    Kind Regards

    Mike Byrne

Reply
  • Morning Håkon,

    I decided to explore my problem further over the weekend before replying and have some extra information for you. Firstly, I don't have a register dump - but I'm fairly confident that the registers have the correct values. Each RF24 is initialised with the same subroutine code: which includes setting the CRC for 2 bytes:

    def init_rf24_radio():
    utime.sleep_ms(5)
    reg_write(SETUP_AW,0b11) # addr width to 5 bytes
    res = reg_read(SETUP_AW,nop)
    if res != 0b11:
    display.scroll("E1") # check comms with hw
    sleep(1000)
    reg_write(EN_AA,0x01) # enable auto ack on pipe0 only
    reg_write(SETUP_RETR,0x68) # auto re-tx delay 1750us & count 8
    #reg_write(SETUP_RETR,0xFF) # auto re-tx delay 4ms & count 15 attempts
    reg_write(RF_CH,0x6C) # rf chan 108
    reg_write(RF_SETUP, 0x22) # 250KB, -12dBm low power
    #reg_write(RF_SETUP, 0x26) # 250KB, 0dBm max power
    reg_write(DYNPD,0) # disable dynamic payloads
    set_crc(2) # CRC 2 bytes
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags
    flush_rx()
    flush_tx()

    My code tries to keep both units in Standby-I mode, so neither uses the PWR_UP = 0 command.

    I tried reducing the SETUP_RETR values (above) from their maximum, but I don't think this changed matters. The CRC subr is called, but as I only use 2 bytes, I could just replace with it a single command, but the CRC subr is:

    def set_crc(length):
    config = reg_read(CONFIG,nop) & ~(CRCO | EN_CRC)
    if length == 0:
    pass
    elif length == 1:
    config |= EN_CRC
    else:
    config |= EN_CRC | CRCO
    reg_write(CONFIG, config)

    Secondly, I reduced the code in both the Sensor (PTX) and Base unit (PRX) and run just the RF24 relevant code - and this *seemed to have worked*  - well as least kept the RF24 link up in point-point mode for intervals of up to 1 hour.  I had my Sensor unit send one (3 byte) transmission every hour. ....This apparent progress led me to realize an important admission from my original problem description: Namely  that my base unit has a second different radio transmitting source, also working on the 2.4GHz band, but not on the same channel - RF24 chan is 108 (2508MHz) and the 2nd radio on chan 7 (2407MHz).  This led me to change my code so that instead of having both radios simultaneously receiving/transmitting, the Base Unit now disables the 2nd radio while the main code loop allows the RF24 to receive (listen) for an incoming code, and then when one is received, the RF24 is stopped listening and the 2nd radio turned on long just enough to transmit its code before being switched off again for the RF24 to go back into its listening mode.  So far.. as of this morning.. the Sensor is working in a stable manner, succesfully transmitting a code every hour to the Base station ......

    However,

    i) Given that I haven't yet had the time to run this for, say, 24 hours between  RF24 code transmissions, I'm not yet confident that the RF24 link will stay up that long without any activity. My hope is that the RF24 system could go for days between brief transmissions.

    2) Also, although I now suspect it, I have no understanding of how the Base unit's second radio might interfere with RF24 radios.  The pattern was that it's the Sensor unit which freezes far more often than the Base unit (although both are side by side on the bench within radio range of the second radio system during this development phase).

    3) Thirdly, I use the following subroutines to set the RF24 radios into Tx or Rx mode. But I've added the "open_tx/rx" and 'start_listening/stop_listening'  subrs into the start of the Main loop code.......I think that this helps but I'm not sure! I'd welcome your advice on this please.

    PRX Base Unit :

    A1 = b'\x78\x78\x78\x78\x78'

    # RF24 Base unit starts in Rx mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) | PWR_UP)) # set PUP
    sleep(2) # wait for 1.5msec start up time
    # now in Standby-I mode
    reg_write(CONFIG,reg_read(CONFIG,nop) | PRIM_RX) # Set RX mode
    utime.sleep_us(150) # wait for TX setting time
    open_rx_pipe(A1)
    start_listening()

    def open_rx_pipe(addr):
    #EN_AA & SETUP_AW already set in init_radio for pipe0 & 5 byte addr width
    reg_write(EN_RXADDR,0x01) # enable data pipe 0
    reg_write(RX_PW_P0,payload_size) # RX payload bytes in pipe0
    reg_write_bytes(RX_ADDR_P0,addr) # set pipe0 rx addr

    def start_listening():
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags extra
    flush_rx()
    flush_tx()
    pin12.write_digital(1) ### set CE Chip Enable to start active RX mode ###
    utime.sleep_us(150) # wait Rx setting time

    PTX Sensor Unit :

    A1 = b'\x78\x78\x78\x78\x78'

    # RF24 Sensor unit starts in Tx mode
    # PUP & set Tx mode, then go into Standby I mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) | PWR_UP)) # set PUP
    sleep(2) # wait for 1.5msec start up time
    # now in Standby-I mode
    reg_write(CONFIG,(reg_read(CONFIG,nop) & ~PRIM_RX)) # set TX mode
    utime.sleep_us(150) # wait for TX setting time

    def open_tx_pipe(addr):
    #EN_AA & SETUP_AW already set in init_radio for pipe0 & 5 byte addr width
    reg_write(RX_PW_P0,payload_size) # RX payload bytes in pipe0
    reg_write_bytes(RX_ADDR_P0,addr) # set pipe0 rx addr
    reg_write_bytes(TX_ADDR,addr) # set tx addr to same

    def stop_listening():
    pin12.write_digital(0) ### reset CE Chip Enable ###
    utime.sleep_us(150)
    # returned to Standby-I mode
    reg_write(STATUS,RX_DR|TX_DS|MAX_RT) # clr flags extra
    flush_rx()
    flush_tx()

    def flush_rx():
    buf_out[0] = FLUSH_RX
    pin16.write_digital(0)
    spi.write_readinto(buf_out,buf_in)
    pin16.write_digital(1)

    def flush_tx():
    buf_out[0] = FLUSH_TX
    pin16.write_digital(0)
    spi.write_readinto(buf_out,buf_in)
    pin16.write_digital(1)

    I hope that this is enough information for you to assess my problem, but please let me know if not.  Thank you again for looking into this for me.

    Kind Regards

    Mike Byrne

Children
  • Hi  Håkon,

    Just to report that after the RF24 link staying alive this morning for a couple of consecutive periods of 1 hour and 1.5 hours between brief transmissions, it eventually failed again sometime over a 3 hr 20 minute period this afternoon - despite no transmission activity from my Base's second radio source!!  This time it was the Base unit which froze and requiring a re-boot to start responding to the Sensor transmissions again (itself not needing a reboot this time). Dissapointing but somehow not a surprise. Hopefully you will know better, but to me that suggests that the second radio source may not be the cause of the problem, whatever help my re-coding did to try to separate the transmissions of the two radio systems may have had.  Will I really need to get my Sensor unit to send a regular 'heatbeat' transmission to keep the link alive?

  • Hi,

    My apologies for the late reply. Its been Easter holiday here in Norway. 

    mikebyrne said:
    i) Given that I haven't yet had the time to run this for, say, 24 hours between  RF24 code transmissions, I'm not yet confident that the RF24 link will stay up that long without any activity. My hope is that the RF24 system could go for days between brief transmissions.

    There's no "link" in that sense. These are quite simple radio protocols, as long as the on-air physical parameters match, and the CRC is OK; the payload is received, regardless of when this was received in time. 

    mikebyrne said:
    2) Also, although I now suspect it, I have no understanding of how the Base unit's second radio might interfere with RF24 radios.  The pattern was that it's the Sensor unit which freezes far more often than the Base unit (although both are side by side on the bench within radio range of the second radio system during this development phase).

    It would be very informative if you were able to get a readback of the nRF24L01+ registers when the radio locked up. There was not much radio handling in the code that you posted, for instance; how do you handle the interrupt from the radio? Do you poll the radio or use the IRQ pins?

    mikebyrne said:
    3) Thirdly, I use the following subroutines to set the RF24 radios into Tx or Rx mode. But I've added the "open_tx/rx" and 'start_listening/stop_listening'  subrs into the start of the Main loop code.......I think that this helps but I'm not sure! I'd welcome your advice on this please.

     Those routines seems to flush RX + TX FIFOs, then also clear all interrupt flags.

    Its hard to say what exactly can be the problem here, especially without seeing the logic for interrupt/radio payload handling, but it sounds like the RX FIFO is filled up without your host controller reading/clearing. Note that the RX FIFO is 3 levels deep, meaning that for one interrupt you can have up to 3 payload queued up. You can read the "FIFO_STATUS" register to see if you have more payloads that needs to be read out.

     

    Kind regards,

    Håkon

Related