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

Sampling data with 4 ADC channels on NRF52 (BL654 module)

Hello,

I'm using BL654 module (nrf52840 inside); SDK15; softdevice s140; IAR.

In my projects I'm using peripherals: I2C(TWI), SPI. Project based on ble_app_uart example (most of sdk_config.h are default, exept TWI/SPI instances and timer3)

My goal is to add sampling data from 4 analog input channels:

Channel 1 - input 0;

Channel 2 - input 5;

Channel 3 - input 4;

Channel 4 - input 7;

My code for SAADC:

#define SAMPLES_IN_BUFFER        4
#define BUFFERS_IN_CH            2
#define SAADC_SAMPLE_PERIOR_MS   1000
volatile uint8_t state = 1;


static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3);
static nrf_saadc_value_t     m_buffer_pool[BUFFERS_IN_CH][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;


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);

    // setup m_timer for compare event every X ms
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, SAADC_SAMPLE_PERIOR_MS);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL3,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE3_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_CHANNEL3);
    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_callback(nrf_drv_saadc_evt_t const * p_event)
{
   if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        ret_code_t err_code;
     
        // set buffers
        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
						
        // print samples on hardware UART and parse data for BLE transmission
        NRF_LOG_INFO("ADC event number: %d\r\n",(int)m_adc_evt_counter);
        for (int i = 0; i < SAMPLES_IN_BUFFER; i++)
        {
          NRF_LOG_INFO("CH_[%d] adc_value: %d\r\n", i, p_event->data.done.p_buffer[i]);
        }					
        m_adc_evt_counter++;
    }
}

void saadc_init(void)
{
    ret_code_t err_code;
	
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
	
    nrf_saadc_channel_config_t channel_1_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0);
	
    nrf_saadc_channel_config_t channel_2_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
	
    nrf_saadc_channel_config_t channel_3_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
	
    nrf_saadc_channel_config_t channel_4_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);		
	
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_1_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(5, &channel_2_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(4, &channel_3_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(7, &channel_4_config);
    APP_ERROR_CHECK(err_code);	

    err_code = nrf_drv_saadc_buffer_convert(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);
}



void SAADC_Init(void)
{   
    saadc_sampling_event_init();
    saadc_init();
    saadc_sampling_event_enable();
}

Main(removed stuff with TWI and SPI):

int main(void)
{
    uart_init();
    log_init();  
    timers_init();
    power_management_init();
    ble_stack_init();
        //printf("ble_stack started...\r\n");
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    SAADC_Init();

    // Start execution.  
    advertising_start();

    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

Problem:

Channel's position numbers doest match their positions in output. And sometimes hopping in arrays...

For example, I'm shorting AIN0 (channel #1) to GND and thats what I see under debug:

AIN5 (channel #2):

AIN4 (channel #3):

AIN7 (channel #4):

And one more things I would like to ask:

Since TIMER0 is used by softdevice, I'm using TIMER3 for SAADC. Am I correct that in saadc_sampling_event_init() I shoud compare events/adresses for TIMER3?

Regards

  • Hi,

     

    I setup your configuration in the peripheral/saadc example, and tried to replicate the issue, but unfortunately; I was not able to do so.

    I connected AIN0 and AIN4 to VDD, AIN5 and AIN7 to GND, and the output is always consistent (+/- a bit of jitter):

    <info> app: ADC event number: 118
    <info> app: channel: 0 value: 854
    <info> app: channel: 5 value: -2
    <info> app: channel: 4 value: 840
    <info> app: channel: 7 value: -2

     

    Do you see this issue often? Or is it something that occurs only in corner cases?

     

    Kind regards,

    Håkon

Related