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

Radio locks in the state of NRF_ESB_STATE_PTX_RX_ACK

Hello, I am trying to broadcast a data among 2 receivers with a special ACK payload. I transmit and gather ACK with one receiver properly yet m_nrf_esb_mainstate locks in NRF_ESB_STATE_PTX_RX_ACK. As I understand from nrf_esb.c after a certain time if no ack is recieved radio must disable itself am I correct?

I can not start transmitting payloads unless m_nrf_esb_mainstate changed to NRF_ESB_STATE_IDLE.

static void on_radio_disabled_tx()
{
    // Remove the DISABLED -> RXEN shortcut, to make sure the radio stays
    // disabled after the RX window
    NRF_RADIO->SHORTS           = m_radio_shorts_common;

    // Make sure the timer is started the next time the radio is ready,
    // and that it will disable the radio automatically if no packet is
    // received by the time defined in m_wait_for_ack_timeout_us
    NRF_ESB_SYS_TIMER->CC[0]    = m_wait_for_ack_timeout_us;
    NRF_ESB_SYS_TIMER->CC[1]    = m_config_local.retransmit_delay - 130;
    NRF_ESB_SYS_TIMER->TASKS_CLEAR = 1;
    NRF_ESB_SYS_TIMER->EVENTS_COMPARE[0] = 0;
    NRF_ESB_SYS_TIMER->EVENTS_COMPARE[1] = 0;

    NRF_PPI->CHENSET            = (1 << NRF_ESB_PPI_TIMER_START) |
                                  (1 << NRF_ESB_PPI_RX_TIMEOUT) |
                                  (1 << NRF_ESB_PPI_TIMER_STOP);
    NRF_PPI->CHENCLR            = (1 << NRF_ESB_PPI_TX_START);
    NRF_RADIO->EVENTS_END       = 0;

    if (m_config_local.protocol == NRF_ESB_PROTOCOL_ESB)
    {
        update_rf_payload_format(0);
    }

    NRF_RADIO->PACKETPTR        = (uint32_t)m_rx_payload_buffer;
    on_radio_disabled           = on_radio_disabled_tx_wait_for_ack;
    m_nrf_esb_mainstate         = NRF_ESB_STATE_PTX_RX_ACK;
}

And this is my code, a bit sloppy but meh,

/*********************************************************************
*               SEGGER MICROCONTROLLER GmbH & Co. KG                 *
*       Solutions for real time microcontroller applications         *
**********************************************************************
*                                                                    *
*       (c) 2014 - 2017  SEGGER Microcontroller GmbH & Co. KG        *
*                                                                    *
*       www.segger.com     Support: [email protected]               *
*                                                                    *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File    : main.c
Purpose : Generic application start
*/

#include <stdio.h>
#include <stdlib.h>
#include "sdk_config.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_uart.h"
#include "nrf_saadc.c"
#include "nrf_drv_pwm.c"
#include "radio_config.c"
#include "nrf_esb_error_codes.h"
#include "nrf_esb.c"
#include <math.h>
#include <string.h>


#define ID 0x01 //  ID
#define gravity 23.1821 // ADC Reading of g
#define acc_offset 127  //0 Acceleration offset 
#define ldr_limit 80  //Mean of daylight measurement
#define PIR_PIN 22  // Input of the HCSR501 PIR Motion Sensor
#define SPEAKER_PIN 17 // Sound output (Speakers will be drived by a N-Channel FET
#if ID == 0x01
  #define x_pos 0
  #define y_pos 0
#elif ID == 0x02
  #define x_pos 6
  #define y_pos 0
#elif ID == 0x03
  #define x_pos 12
  #define y_pos 0
#else
  #define x_pos NULL
  #define y_pos NULL
#endif
#ifdef x_pos
static nrf_esb_payload_t tx_payload=NRF_ESB_CREATE_PAYLOAD(0,ID,x_pos,y_pos,0x31,0x32,0x33,0x34);  // (ID,pos_X,pos_y, broadcast order...)
#endif
static nrf_esb_payload_t rx_payload;
nrf_esb_config_t esb_config=NRF_ESB_DEFAULT_CONFIG;
uint8_t base_addr_0 = 0xe7;
uint8_t addr_prefix = 0xa5;
bool tx_flag=true;
struct{
  int8_t id;
  double pos_x;
  double pos_y;
  int8_t rssi;
  float distance;
}data[150];
double distances[4][4]; // distance[ID][position_x,position_y,RSSI,distance]
int8_t order[4];
nrf_esb_evt_t const * p_event;
int index=0;
static int8_t references[3]={0x01,0x02,0x03};
static nrf_pwm_values_common_t duty_cycle[1]={0};  // Duty cycle value array
nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);  // PWM0 is used
uint8_t adc_buffer[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};   //ADC Buffer. ADC somehow transfers the result as mirrored. There is a bitwise mirror script in radio_config.c !

void nrf_esb_event_handler(nrf_esb_evt_t const * p_event);

bool arrsrc(int8_t *array,int8_t id){
  for(int i=0;i<150;i++){
    if(array[i]==id){
    return true;
    break;
    }
    else{
    return false;
    break;
    }
  }
}
void clocks_start( void )
{
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;

    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
}

int32_t init_esb(char mode){
  tx_payload.noack=false;
  uint32_t err_code=0;
  err_code = nrf_esb_disable();
  nrf_delay_us(150);
  if(err_code != NRF_SUCCESS) return err_code;
  esb_config.payload_length=7;
  esb_config.event_handler=nrf_esb_event_handler;
  if(mode == 'r') esb_config.mode=NRF_ESB_MODE_PRX;
  else if (mode == 't') esb_config.mode = NRF_ESB_MODE_PTX;
  else return NRF_ERROR_INVALID_PARAM;
  err_code = nrf_esb_init(&esb_config);
  if(err_code != NRF_SUCCESS) return err_code;
  err_code = nrf_esb_set_base_address_0(&base_addr_0);
  if(err_code != NRF_SUCCESS) return err_code;
  err_code = nrf_esb_set_prefixes(&addr_prefix,1);
  if(err_code != NRF_SUCCESS) return err_code;
  if(mode == 'r') err_code = nrf_esb_start_rx();
  else if (mode == 't') err_code = nrf_esb_start_tx();


  return NRF_SUCCESS;
  
}
void init_adc(){

  nrf_saadc_channel_config_t adc_channel_conf[8];
  nrf_saadc_enable();
  nrf_delay_us(100);
  while(nrf_saadc_enable_check() == 0){
    printf("ADC enable failed, trying again...");
    nrf_saadc_enable();
    nrf_delay_us(100);
    }
  nrf_saadc_buffer_init((int16_t *)&adc_buffer,16);
  nrf_saadc_resolution_set(NRF_SAADC_RESOLUTION_8BIT);
  nrf_saadc_oversample_set(NRF_SAADC_OVERSAMPLE_DISABLED);
  for(int i=0;i<4;i++){
    adc_channel_conf[i].acq_time=NRF_SAADC_ACQTIME_3US;   // tconv<2us 
    adc_channel_conf[i].burst=NRF_SAADC_BURST_DISABLED;
    adc_channel_conf[i].gain=NRF_SAADC_GAIN1_4;
    adc_channel_conf[i].mode=NRF_SAADC_MODE_SINGLE_ENDED;
    adc_channel_conf[i].pin_n=NRF_SAADC_INPUT_DISABLED;
    adc_channel_conf[i].pin_p=(NRF_SAADC_INPUT_AIN0+i);
    adc_channel_conf[i].reference=NRF_SAADC_REFERENCE_VDD4;
    adc_channel_conf[i].resistor_n=NRF_SAADC_RESISTOR_DISABLED;
    adc_channel_conf[i].resistor_p=NRF_SAADC_RESISTOR_DISABLED;
    nrf_saadc_channel_init(i,&adc_channel_conf[i]);

    }

  nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
  }

void init_pwm(void){

  nrf_drv_pwm_config_t pwm_conf=NRF_DRV_PWM_DEFAULT_CONFIG;   //Base clock 250khz , counter_top=5 -> freq=50khz
  nrf_drv_pwm_init(&m_pwm0,&pwm_conf,NULL);
  nrf_pwm_sequence_t seq_pmw;
  seq_pmw.values.p_common=&duty_cycle;
  seq_pmw.repeats=2;
  seq_pmw.length=1;
  seq_pmw.end_delay=0;
  nrf_drv_pwm_simple_playback(&m_pwm0,&seq_pmw,1,NRF_DRV_PWM_FLAG_LOOP);
}

 void main(void) {
  nrf_gpio_cfg_output(0);
  nrf_gpio_pin_clear(0);
  for(int i=0;i<4;i++){
    order[i]=0;
  }
  
  uint32_t err_code_main=0;
  init_adc();
  init_pwm();
  clocks_start();
  if(ID==0x01)err_code_main = init_esb('t');
  else err_code_main = init_esb('r');

  while(1){

    err_code_main = nrf_esb_write_payload(&tx_payload);

    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
    nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
    nrf_saadc_event_clear(NRF_SAADC_EVENT_RESULTDONE);



}
}


void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
{

    if(p_event->evt_id == NRF_ESB_EVENT_TX_SUCCESS)
    {
    tx_flag=false;
    }
    else if(p_event->evt_id == NRF_ESB_EVENT_TX_FAILED)
    {
    nrf_esb_flush_tx();
    }
    else if(p_event->evt_id == NRF_ESB_EVENT_RX_RECEIVED){
    if(nrf_esb_read_rx_payload(&rx_payload) == NRF_SUCCESS){
      nrf_esb_stop_rx();
      if(!arrsrc(&data->id,rx_payload.data[0])){
        
        data[index].id=rx_payload.data[0];
        data[index].pos_x=rx_payload.data[1];
        data[index].pos_y=rx_payload.data[2];
        data[index].rssi=rx_payload.rssi;
        data[index].distance= pow(10,(20.0*log10(2.4*pow(10,9))+20.0*log10(4*M_PI/299792458.0)+20.0-data[index].rssi)/(-20.0)); // RSSI to Distance ,in meters
        index++;
        }
      }
    }

}

  • Hello,

    Not sure what the problem is, but a few things to check:

    - If you are using ACK then make sure you are only transmitting from one transmitter to one receiver, otherwise both receivers may ACK the packet, which cause interference between the two ACK packets.

    - If you are receiving a packet (NRF_ESB_EVENT_RX_RECEIVED), then there is no need to call nrf_esb_stop_rx(), as this will stop receive mode and also may prevent outgoing ACK.

    - It might be a good idea to use the example project from the SDK as-is before doing modifications, just to make sure basic functionality works as intended.

    Best regards,
    Kenneth

     

Related