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

How to identify adc value from its adc channel?

I use nRF52840 and SDK16 with S140 softdevice. I need 3 ADC ports. The initial code as follows.

static void adc_configure(void)
{
ret_code_t err_code = nrf_drv_saadc_init(NULL, saadc_event_handler);
APP_ERROR_CHECK(err_code);

nrf_saadc_channel_config_t config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);

err_code = nrf_drv_saadc_channel_init(0, &config);
APP_ERROR_CHECK(err_code);

config.pin_p = NRF_SAADC_INPUT_AIN0;
err_code = nrf_drv_saadc_channel_init(1, &config);
APP_ERROR_CHECK(err_code);

config.pin_p = NRF_SAADC_INPUT_AIN4;
err_code = nrf_drv_saadc_channel_init(2, &config);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_buffer_convert(&adc_buf[0], 1);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_buffer_convert(&adc_buf[1], 1);
APP_ERROR_CHECK(err_code);
}

I call the function of nrf_drv_saadc_sample() once 2 seconds.  And the event handler will be called 3 times. The function of saadc_event_handler will display the channel information.

But it shows as follows: How to identify adc value from which channel? Why the channel isn't display 0/1/2?

<info> app: channel=156

<info> app: channel=158

<info> app: channel=156

void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
NRF_LOG_INFO("channel=%d", p_event->data.limit.channel);

....
}

Parents
  • Hello,

    I see that you print using the p_event->data.limit.channel, but I suspect that this is not a limit event. You can check this like this:

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_LIMIT)
        {
            NRF_LOG_INFO("reached limit on channel %d", p_evt->data.limit.channel);
            return;
        }
        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);
    
            int i;
            NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
            m_adc_evt_counter++;
        }
    }

    You can't use the p_evt->data.limit. ... pointer if the event is not a NRFX_SAADC_EVT_LIMIT event, but a NRFX_SAADC_EVT_DONE event. In that case, the data in this pointer is not what you think it is.

    So in the "normal" event callbacks, you don't have a field saying what channel the measurements come from. But they will always come in the order of the channels. This is why you should have SAMPLES_IN_BUFFER = n*number of channels. Let us say you have 3 channels, and n=1, then SAMPLES_IN_BUFFER should be 3.

    If so, then p_buffer[0] will always belong to channel 0, buffer[1] to channel 1 and buffer[2] to channel 2. 

    If you set SAMPLES_IN_BUFFER = 4, then in the first event:

    buffer[0] belongs to channel 0,
    buffer[1] belongs to channel 1,
    buffer[2] belongs to channel 2,
    buffer[3] belongs to channel 0

    But in the next event, this will be shifted by one:

    buffer[0] belongs to channel 1,
    buffer[1] belongs to channel 2,
    buffer[2] belongs to channel 0,
    buffer[3] belongs to channel 1,

    This is because the channels are sampled in the order of the channels, but the buffer isn't aware of how many channels that are in use.

    Best regards,

    Edvin

Reply
  • Hello,

    I see that you print using the p_event->data.limit.channel, but I suspect that this is not a limit event. You can check this like this:

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_LIMIT)
        {
            NRF_LOG_INFO("reached limit on channel %d", p_evt->data.limit.channel);
            return;
        }
        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);
    
            int i;
            NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter);
    
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
            m_adc_evt_counter++;
        }
    }

    You can't use the p_evt->data.limit. ... pointer if the event is not a NRFX_SAADC_EVT_LIMIT event, but a NRFX_SAADC_EVT_DONE event. In that case, the data in this pointer is not what you think it is.

    So in the "normal" event callbacks, you don't have a field saying what channel the measurements come from. But they will always come in the order of the channels. This is why you should have SAMPLES_IN_BUFFER = n*number of channels. Let us say you have 3 channels, and n=1, then SAMPLES_IN_BUFFER should be 3.

    If so, then p_buffer[0] will always belong to channel 0, buffer[1] to channel 1 and buffer[2] to channel 2. 

    If you set SAMPLES_IN_BUFFER = 4, then in the first event:

    buffer[0] belongs to channel 0,
    buffer[1] belongs to channel 1,
    buffer[2] belongs to channel 2,
    buffer[3] belongs to channel 0

    But in the next event, this will be shifted by one:

    buffer[0] belongs to channel 1,
    buffer[1] belongs to channel 2,
    buffer[2] belongs to channel 0,
    buffer[3] belongs to channel 1,

    This is because the channels are sampled in the order of the channels, but the buffer isn't aware of how many channels that are in use.

    Best regards,

    Edvin

Children
No Data
Related