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

nRF52840 saadc results are in the wrong order

Hi. In our application we are reading the voltage on 3 Analog input pins via saadc. System is also a BLE central and UBD CDC device so lots going on.

Quite often the 3 analog results are shifted so if they were in the order A,B,C normally they could randomly become B,A,C or C,B,A etc.

I have seen a few threads on the forum about this but no clear answers.

I am trying to avoid adding a separate ADC to SPI IC on the board, but the SAADC on the nRF52840 is not up to the job which is a shame since.

Here are some code snippets. Maybe I could re-initialise the saadc after every sample? I only need to read them every second or so.

nrf_drv_saadc_sample(); Is triggered every few seconds from timer interrupt.

Thanks

void saadc_init(void)
{
    ret_code_t err_code;
    nrf_saadc_channel_config_t channel_config6 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6); //P0.30 = AN6 = Regulated voltage
    nrf_saadc_channel_config_t channel_config4 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4); //P0.28 = AN4 = Current sense input
    nrf_saadc_channel_config_t channel_config5 
      = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5); //P0.29 = AN5 = Voltage In

    err_code = nrf_drv_saadc_init(NULL, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_config6);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(1, &channel_config4);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &channel_config5);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(m_buffer, SAMPLES_IN_BUFFER);
    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;

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);

        output[0] = p_event->data.done.p_buffer[0];
        output[1] = p_event->data.done.p_buffer[1];
        output[2] = p_event->data.done.p_buffer[2];

        if(output[0] > 50000) output[0] = 0; //We don't want 65535 etc negative about 0 to get into average
        if(output[1] > 50000) output[1] = 0;
        if(output[2] > 50000) output[2] = 0;

        voltage_reg_ave = ((output[0] - voltage_reg_ave) / mov_ave_divisor) + voltage_reg_ave;
        voltage_in_ave = ((output[2] - voltage_in_ave) / mov_ave_divisor) + voltage_in_ave;
        current_sense_ave = ((output[1] - current_sense_ave) / mov_ave_divisor) + current_sense_ave;
    }
}

Parents Reply
  • Hi Haakonsh.

    Sample rate is about 50Hz.

    Only have the issue when the CPU is under heavy load, i.e. lots of BLE comms and UART serial comms. It can be running for days with no issue, but as soon as lots going on the values swap.

    I tried the following so sample can only happen when callback finished, but didn't help;

            if(saadc_sample_count < SAMPLES_IN_BUFFER)
            {
                nrf_drv_saadc_sample(); //Tigger saadc samples
                saadc_sample_count++;
            }     

    I am going to try this next;

            nrf_drv_saadc_sample_convert(0, &output[0]);
            nrf_drv_saadc_sample_convert(1, &output[1]);
            nrf_drv_saadc_sample_convert(2, &output[2]);

    Phil

Children
Related