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

SAADC + BLE UART (NUS), The saadc_callback function doesnt execute.

Hi 

I'm using NRF52840 + SDK15.0.0 and softdevice 6.0.0

I have joined two program one is ble_app_uart  and other SAADC capturing ultrasound noise. (Saadc program works perfectly alone, without softdevice, BLE, etc)

The idea is when the device is connected to cellphone, and the cellphone send "!" by UART, the device start to measure the SAADC and sends the ultrasound data by NUS.

I have assigned SAADC in the timer1. (static const nrf_drv_timer_t    m_timer = NRF_DRV_TIMER_INSTANCE(1);)  Even I testedin the timer2

My problem is when activate SAADC (saadc_sampling_event_enable();) the SAADC fuction doesnt execute event saadc_callback, it seems does nothing.

I have writen some output to terminal if the program execute the saadc_callback, but the saadc_callback doesnt running.

I have change the priority of the SAADC to 2. But It didnt work.

Any Sugestion?

Ricardo


static void nus_data_handler(ble_nus_evt_t * p_evt)
{
  
  if (p_evt->type == BLE_NUS_EVT_RX_DATA)
  {
    uint32_t err_code;
    
    NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
    NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    
    for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
    {
      do
      {
        err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
        if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
        {
          NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
          APP_ERROR_CHECK(err_code);
        }
      } while (err_code == NRF_ERROR_BUSY);
    }
    if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
    {
      while (app_uart_put('\n') == NRF_ERROR_BUSY);
    }
    

    if(p_evt->params.rx_data.p_data[0] == '!')
    {      

    Datos_Capturados_Ultrasonido    = false;
    Capturar_datos_SAADC            = true;
    saadc_sampling_event_enable();
    
    RealFFT_Instance.fftLenReal= Total_samples;
    
    // ***** HERE IS MY PROBOLEM  ************
    
    while (!Datos_Capturados_Ultrasonido){}  // HERE... 
    // I created the while, because I wait to the data is readed ok...


    saadc_sampling_event_disable();
    Datos_Capturados_Ultrasonido = false;
      
    uint16_t length = (uint16_t)index;
    uint8_t Ble_transfer[0]= FFT_Real[0];
    uint8_t Ble_transfer[1][] = (uint8_t)FFT_Real[0];
      
    uint16_t length = (uint16_t)sizeof(FFT_Real[0]);
    memcpy(Ble_transfer[0], FFT_Real[0], 0x100); //lenght
      
      
      err_code = ble_nus_data_send(&m_nus, Ble_transfer[0], &length, m_conn_handle);  //&length
      if ( (err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_BUSY) &&
          (err_code != NRF_ERROR_NOT_FOUND) )
      {
        APP_ERROR_CHECK(err_code);
      }         
    }
  }
}


void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
  ret_code_t err_code;
  
  //NRF_LOG_INFO("FUERA DEL LOOP");
  //printf("fuera del loop %d \r\n",loop_number);
  //NRF_LOG_FLUSH();
if (Capturar_datos_SAADC)
{
  if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
  {
    
    NRF_LOG_INFO("Loop ultrasonido numero");
    printf("Loop ultrasonido numero %d \r\n",loop_number);
    NRF_LOG_FLUSH();
    loop_number++;
    err_code =  nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
    
    for (int k=0;k<SAMPLES_IN_BUFFER;k++)
    {
      In_Data[muestra][k] = (int16_t)((p_event->data.done.p_buffer[k]-512)<<8); //
    }
    
    if (muestra==(muestreos))
    {
      saadc_sampling_event_disable();
      
      Datos_Capturados_Ultrasonido = true;
   
      // nrf_drv_timer_pause(&m_timer);     
      /*
      memset(FFT_Complex, 0, sizeof FFT_Complex);
      memset(In_Data, 0, sizeof In_Data);
      memset(FFT_Real, 0, sizeof FFT_Real);
      memset(p_event->data.done.p_buffer, 0, sizeof p_event->data.done.p_buffer);
      m_adc_evt_counter=0;
      //nrf_drv_timer_resume(&m_timer);
      muestra=0;
      */
    }
    else
    {
      muestra++;
    }
  }
}
}

Main

int main(void)
{
  muestra = 0;
  bool erase_bonds;
  
  uart_init();
  log_init();
  timers_init();
  buttons_leds_init(&erase_bonds);
  power_management_init();
  ble_stack_init();
  gap_params_init();
  gatt_init();
  services_init();
  advertising_init();
  conn_params_init();
  
  // SAADC START
  printf("UART 1.\r\n");
    NRF_LOG_INFO("Debug logging for UART over RTT started.");
  
  saadc_sampling_event_init();
  saadc_init();
  //saadc_sampling_event_enable();
  RealFFT_Instance.fftLenReal= Total_samples;
  
  printf("SAADC Configured.\r\n");
  NRF_LOG_INFO("Debug logging for UART over RTT started.");
  
  // Start execution.
  advertising_start();
  // Enter main loop.
  
  for (;;)
  {
    idle_state_handle();
  }
}

void timer_handler(nrf_timer_event_t event_type, void * p_context)
{
  
  
}




void saadc_sampling_event_init(void)
{
  ret_code_t err_code;
  err_code = nrf_drv_ppi_init();
  APP_ERROR_CHECK(err_code);
  
  nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
  timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
  
  err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
  APP_ERROR_CHECK(err_code);
  
  uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer,10);  //HERE THE TIMER If i use 50 it is for 10.000 hz
  nrf_drv_timer_extended_compare(&m_timer,
                                 NRF_TIMER_CC_CHANNEL0,
                                 ticks,
                                 NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                 false);
  nrf_drv_timer_enable(&m_timer);
  
  uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                              NRF_TIMER_CC_CHANNEL0);
  uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
  
  //setup ppi channel so that timer compare event is triggering sample task in SAADC 
  err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
  APP_ERROR_CHECK(err_code);
  err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                        timer_compare_event_addr,
                                        saadc_sample_task_addr);
  APP_ERROR_CHECK(err_code);
}


void saadc_sampling_event_enable(void)
{
  ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
  
  APP_ERROR_CHECK(err_code);
}

void saadc_sampling_event_disable(void)
{
  ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
  
  APP_ERROR_CHECK(err_code);
}

void saadc_init(void)
{
  ret_code_t err_code;
  nrf_saadc_channel_config_t channel_config = 
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
  
  channel_config.acq_time         = NRF_SAADC_ACQTIME_3US;
  channel_config.burst            = NRF_SAADC_BURST_ENABLED   ;                           //NRF_SAADC_BURST_DISABLED  es mas lento  ///< Burst mode is enabled. SAADC takes 2^OVERSAMPLE number of samples as fast as it can, and sends the average to Data RAM.
  channel_config.reference        = NRF_SAADC_REFERENCE_VDD4;
  channel_config.gain             = NRF_SAADC_GAIN1_4;
  err_code = nrfx_saadc_calibrate_offset();
 
   //Configure SAADC
  nrf_drv_saadc_config_t saadc_config;// = NRF_DRV_SAADC_DEFAULT_CONFIG;
  saadc_config.low_power_mode     = false;                                          //true                 
  saadc_config.resolution         = NRF_SAADC_RESOLUTION_10BIT;         
  saadc_config.oversample         = NRF_SAADC_OVERSAMPLE_DISABLED;                //NRF_SAADC_OVERSAMPLE_DISABLED;   NRF_SAADC_OVERSAMPLE_2X
  saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOWEST;                    //APP_IRQ_PRIORITY_LOW;
  
  err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_saadc_channel_init(0, &channel_config);
  APP_ERROR_CHECK(err_code);
  
  NRF_SAADC->SAMPLERATE  =  (1 << 12);                                          // Timer mode  
  NRF_SAADC->SAMPLERATE  |= 80;                                                 // 16MHz / 80 counts = 200 000 triggers per second
  // See http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52840.ps/saadc.html?cp=2_0_0_5_22_8_11#register.SAMPLERATE for details. 
  
  
  err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);  //(m_buffer_pool[0], SAMPLES_IN_BUFFER);
  APP_ERROR_CHECK(err_code);
  
  err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
  APP_ERROR_CHECK(err_code);
  
}

  • Hi,

    It could be some issue with priorities. Are you stuck at the line where you wait for Datos_Capturados_Ultrasonido? I would recommend that you exit the nus_data_handler while sampling, and disable sampling/ppi channel in saadc_callback or main context.

    Best regards,
    Jørgen

  • Hi Jørgen

    Thanks for your  fast answer, YES the programs STUCK in    ... while (!Datos_Capturados_Ultrasonido){} 

    I will do it...

    thanks

    Ricardo

  • Hi Jørgen

    you are right.. something inside happend of nus_data_handler but the SAADC_CALLBACK doesnt run..

    as your recomendation if enable the SAADC outside of nus_data_handler the saadc start working..

    Resuming I change the following in the code..

    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
      
      if (p_evt->type == BLE_NUS_EVT_RX_DATA)
      {
        Bla.. bla..
        
        bla..  bla...  bla...
        
        
        if(p_evt->params.rx_data.p_data[0] == '!')
        {      
          SAACD_Ultrasound_Enable = true;
                       
        }
      }
    }
    
    
    And in the main loop
    
    for (;;)
      {
        if (SAACD_Ultrasound_Enable)
        {
          Datos_Capturados_Ultrasonido = false;
          Capturar_datos_SAADC = true;
          SAACD_Ultrasound_Enable = false;
    
          saadc_sampling_event_enable();
    
          //RealFFT_Instance.fftLenReal= Total_samples;
    
          
          while (!Datos_Capturados_Ultrasonido){}
          saadc_sampling_event_disable();
          Datos_Capturados_Ultrasonido = false;
          nrf_drv_timer_disable(&m_timer);
          
          nrf_drv_saadc_uninit();
          
          nrf_drv_saadc_channel_uninit(0);
         }
        idle_state_handle();
    
      }
    }
    

    NOW .. I have the following problem..

    I enabled the Saadc  with "  saadc_sampling_event_enable(); "

    and the saadc_callback (function)  Starting.. 

    Why I cant stop it with saadc_sampling_event_disable(); ? 

    void saadc_sampling_event_disable(void)
    {
      ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
      
      APP_ERROR_CHECK(err_code);
    }

    Because when I execute saadc_sampling_event_disable();

    the function saadc_callback  still in loop...I know because I send a printf  a message to terminal.. 

    ONLY i can stop the SAADC when I kill everything.. doing uninit..

    nrf_drv_saadc_uninit(); 
    nrf_drv_saadc_channel_uninit(0);

    If I execute Saacd_init() the program goes to Hardfault.. 

    is there any simple way to enable and disable again the SAADC?

    Thanks

    Ricardo

  • Try removing these two lines from your saadc_init function:

    NRF_SAADC->SAMPLERATE  =  (1 << 12);                                          // Timer mode  
    NRF_SAADC->SAMPLERATE  |= 80;                                                 // 16MHz / 80 counts = 200 000 triggers per second

    These lines will configure the SAADC in continuous sampling mode, overriding the PPI sample task.

  • Hi Jørgen

    I configured the continuous Sampling, because I read 1024 datas (with the sample rate of 200.000 Hz), I used it in the FFT (fast furier transfor)  to get the sound frequency spectrum...

    Could I stop the SAADC execute

    "NRF_SAADC->SAMPLERATE = (0 << 12);"

    and 

    "saadc_sampling_event_disable(); "

    in the main loop?  

    0 = Rate is controlled from SAMPLE task

    NRF_SAADC->SAMPLERATE = (0 << 12); // 0 = Rate is controlled from SAMPLE task 

    Thanks for your support..

    Ricardo

Related