Proximity Profile (Battery Measurement) not updating when SAADC LP mode Enabled

mvreddy gravatar image

asked 2017-05-19 14:40:12 +0200

I am using SDK 12.2.0 with soft device s132 3.0.0 using NRF52 Development Board(PCA10040).

I want to update Battery level to central device/APP.As i want to use code for my custom Board i.e, battery operated ,so i want to configure in Low power mode.In 12.0.0 proximity example .there is an option to enable Low power mode.So,i Enabled.But it is not updating the Values.

#ifndef SAADC_CONFIG_LP_MODE
#define SAADC_CONFIG_LP_MODE 1
#endif

I am using the exact example problem,But it is not Updating the Values.

If i test the SAADC seperatly,There it is working.All code is similar Don't know how it is not working.

void SAADC_IRQHandler(void)
{
    if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
    {
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_END));
                NRF_LOG_INFO(" SAADC in SAADC_IRQHandler  : Inside NRF_SAADC_EVENT_END \r\n");

        if (!m_cb.low_power_mode || m_cb.conversions_end)
        {
            NRF_LOG_INFO(" SAADC in SAADC_IRQHandler  : Inside !m_cb.low_power_mode || m_cb.conversions_end. \r\n");
                        nrf_drv_saadc_evt_t evt;
            evt.type               = NRF_DRV_SAADC_EVT_DONE;
            evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
            evt.data.done.size     = m_cb.buffer_size;

            if (m_cb.p_secondary_buffer == NULL)
            {
                m_cb.adc_state = NRF_SAADC_STATE_IDLE;
            }
            else
            {
                m_cb.p_buffer           = m_cb.p_secondary_buffer;
                m_cb.buffer_size        = m_cb.secondary_buffer_size;
                m_cb.p_secondary_buffer = NULL;
                if (!m_cb.low_power_mode)
                {
                    nrf_saadc_task_trigger(NRF_SAADC_TASK_START);
                                        NRF_LOG_INFO(" SAADC in SAADC_IRQHandler  : Inside !m_cb.low_power_mode || m_cb.conversions_end. : Inside low power.\r\n");
                }
            }
            m_cb.event_handler(&evt);
            m_cb.conversions_end = false;
        }
                NRF_LOG_INFO(" SAADC in SAADC_IRQHandler  : Inside !m_cb.low_power_mode || m_cb.conversions_end. \r\n");
                nrf_drv_saadc_evt_t evt;
        evt.type               = NRF_DRV_SAADC_EVT_DONE;
        evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer;
        evt.data.done.size     = m_cb.buffer_size;
                m_cb.event_handler(&evt);
        m_cb.conversions_end = false;

    }
    if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
    {
                NRF_LOG_INFO(" SAADC in SAADC_IRQHandler  : Inside m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)\r\n");
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_STARTED));

        if (m_cb.buffer_size_left == 0) 
        {
            // Sampling finished, next buffer in progress.
            m_cb.buffer_size_left = m_cb.buffer_size - m_cb.active_channels;
            nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size -
                                                                      m_cb.buffer_size_left],
                                  m_cb.active_channels);
        }
        else if (m_cb.buffer_size_left > m_cb.active_channels)
        {
            // More samples to convert than for single event.
            m_cb.buffer_size_left -= m_cb.active_channels;
            nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size -
                                                                      m_cb.buffer_size_left],
                                  m_cb.active_channels);
        }
        else if ((m_cb.buffer_size_left == m_cb.active_channels) &&

                 (m_cb.p_secondary_buffer != NULL)) 
        {
            // Samples to convert for one event, prepare next buffer.
            m_cb.conversions_end  = true;
            m_cb.buffer_size_left = 0;
            nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer,
                                  m_cb.active_channels);
        }

        else if (m_cb.buffer_size_left == m_cb.active_channels) 
        {
            // Samples to convert for one event, but no second buffer.
            m_cb.conversions_end  = true;
            m_cb.buffer_size_left = 0;
        }
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE);
    }
    if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
    {
        nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE));
        m_cb.adc_state = NRF_SAADC_STATE_IDLE;

        nrf_drv_saadc_evt_t evt;
        evt.type = NRF_DRV_SAADC_EVT_CALIBRATEDONE;
        m_cb.event_handler(&evt);
    }
    if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
    {
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
        NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
        m_cb.adc_state = NRF_SAADC_STATE_IDLE;
    }
    else
    {
        uint32_t          limit_flags = m_cb.limits_enabled_flags;
        uint32_t          flag_idx;
        nrf_saadc_event_t event;

        while (limit_flags)
        {
            flag_idx     = __CLZ(limit_flags);
            limit_flags &= ~((1UL << 31) >> flag_idx);
            event        = FLAG_IDX_TO_EVENT(flag_idx);
            if (nrf_saadc_event_check(event))
            {
                nrf_saadc_event_clear(event);
                nrf_drv_saadc_evt_t evt;
                evt.type                  = NRF_DRV_SAADC_EVT_LIMIT;
                evt.data.limit.channel    = LIMIT_EVENT_TO_CHANNEL(event);
                evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event);
                NRF_LOG_DEBUG("Event limit, channel: %d, limit type: %s.\r\n", evt.data.limit.channel, (uint32_t)EVT_TO_STR(evt.data.limit.limit_type));
                m_cb.event_handler(&evt);
            }
        }
    }
}

It is Entering into the above function.From this it is not calling the below function.(Where as when SAADC LP mode disabled ,it is calling the below Function.)

void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
        NRF_LOG_INFO("Entered into SAADC event Handler.\r\n");
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
                NRF_LOG_INFO("Entered into SAADC event Done.\r\n");
        nrf_saadc_value_t adc_result;
        uint16_t          batt_lvl_in_milli_volts;
        uint8_t           percentage_batt_lvl;
        uint32_t          err_code;

        adc_result = p_event->data.done.p_buffer[0];
                NRF_LOG_INFO("Loaded Buffer into adc result.\r\n");

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
                NRF_LOG_INFO("Coverting data Buffer as Read.\r\n");
        APP_ERROR_CHECK(err_code);
                NRF_LOG_INFO("The adc Value : %d. \r\n",adc_result);

        batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) +
                                  DIODE_FWD_VOLT_DROP_MILLIVOLTS;
        percentage_batt_lvl = battery_level_in_percent(batt_lvl_in_milli_volts);

        err_code = ble_bas_battery_level_update(&m_bas, percentage_batt_lvl);
        if (
            (err_code != NRF_SUCCESS)
            &&
            (err_code != NRF_ERROR_INVALID_STATE)
            &&
            (err_code != BLE_ERROR_NO_TX_PACKETS)
            &&
            (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
           )
        {
            APP_ERROR_HANDLER(err_code);
        }
    }
}

Please, Help out if any one aware of it.

edit retag flag offensive close delete report spam

Comments

There are some bugs related to LP mode and some wrong interrupts being set/cleared in the SAADC driver in SDK 12.x. Could you try upgrading to SDK 13, or use the SAADC driver from SDK 13 in your SDK 12 project?

Jørgen Holmefjord ( 2017-05-22 14:06:12 +0200 )editconvert to answer

Hi Jørgen Holmefjord,

Thank you.I checked with SDK13 ,Still i get the same issue.

MVR ( 2017-05-22 14:16:36 +0200 )editconvert to answer

I tested both with SDK 13 and SDK 12.2 with SAADC driver from SDK 13, and both seems to work fine. SDK 12.2 with original driver does not seem to work in LP mode, as the SAADC event handler is only called once. Are you sure you tested it with SDK 13?

Jørgen Holmefjord ( 2017-05-22 17:07:03 +0200 )editconvert to answer