This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LOCOMP function failed when reference level being changed periodically

Dear all,

I ran LPCOMP example from SDK16 on nRF52 DK and it works just fine.

But I've occurred some problem modifying reference voltage. I init the lpcomp the same way as SDK shows, then I manually triggerred a SAMPLE TASK to get the compare RESULT. I need to distinguish the input voltage into three levels so I need to compare the analog input with two different reference. So I do nrf_drv_lpcomp_uninit() and run nrf_drv_lpcomp_init() with another refence voltage. But the comparator result will remain 0 no matter what input is appllied on input pin.

If I initialize the lpcomp with fixed refence voltage and not doing uninit and init during system running, the comparator works well. So I assume there must be something wrong with the uninit part?

Code is shown as follows and your help is appreciated!

static void batt_level_deinit()
{
	nrf_drv_lpcomp_uninit();
}


static void lpcomp_event_handler(nrf_lpcomp_event_t event)
{
	
}


static void level_set(nrf_lpcomp_ref_t ref, nrf_lpcomp_detect_t det)	//NRF_LPCOMP_REF_SUPPLY_4_8  NRF_LPCOMP_DETECT_UP
{
    uint32_t	err_code;

    nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
    config.input = NRF_LPCOMP_INPUT_0;
		config.hal.hyst = NRF_LPCOMP_HYST_50mV;
		config.hal.reference = ref;
		config.hal.detection = det;

    // initialize LPCOMP driver, from this point LPCOMP will be active and provided
    // event handler will be executed when defined action is detected
    err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
    APP_ERROR_CHECK(err_code);
		nrf_drv_lpcomp_enable();
}


static uint8_t get_comp_result()
{
	NRF_LPCOMP->TASKS_SAMPLE=1;
	while(!nrf_lpcomp_event_check(NRF_LPCOMP_EVENT_READY));
	
	return NRF_LPCOMP->RESULT;
}


static uint8_t batt_level_ergodic()
{
	level_set(NRF_LPCOMP_REF_SUPPLY_13_16, NRF_LPCOMP_DETECT_DOWN);
	

	if(get_comp_result())
	{
		batt_level_deinit();
		return 3;
	}
	
//	batt_level_deinit();
//	level_set(NRF_LPCOMP_REF_SUPPLY_9_16, NRF_LPCOMP_DETECT_DOWN);
//	if(get_comp_result())
//	{
//		batt_level_deinit();
//		return 2;
//	}

//	batt_level_deinit();
//	level_set(NRF_LPCOMP_REF_SUPPLY_3_16, NRF_LPCOMP_DETECT_DOWN);
//	if(get_comp_result())
//	{
//		batt_level_deinit();
//		return 1;
//	}
	batt_level_deinit();
	return 0;
}


/****************** MAIN *********************/
int main()
{
	uint32_t result;
	
	NRF_LOG_INIT(NULL);
	NRF_LOG_DEFAULT_BACKENDS_INIT();
	NRF_LOG_INFO("start!\r\n");

	while(1)
	{
		result = batt_level_ergodic();
		NRF_LOG_INFO("%d\r\n", result);

		nrf_delay_ms(1000);
		NRF_LOG_FLUSH();

	}
}

Parents
  • Hi,

    I wasn't able to reproduce this on my side, but I tried modifying the lp-comp example by adding your level_set() and see if it was able to change the reference voltage, which it did. Here is the code I used:

    #define WAVE_ON_PIN_NUMBER 2
    
    static volatile uint32_t voltage_falls_detected = 0;
    static volatile uint32_t voltage_falls_total    = 0;
    
    /**
     * @brief LPCOMP event handler is called when LPCOMP detects voltage drop.
     *
     * This function is called from interrupt context so it is very important
     * to return quickly. Don't put busy loops or any other CPU intensive actions here.
     * It is also not allowed to call soft device functions from it (if LPCOMP IRQ
     * priority is set to APP_IRQ_PRIORITY_HIGH).
     */
    static void lpcomp_event_handler(nrf_lpcomp_event_t event)
    {
        if (event == NRF_LPCOMP_EVENT_DOWN)
        {
            bsp_board_led_invert(BSP_BOARD_LED_0); // just change state of first LED
            voltage_falls_detected++;
            voltage_falls_total++;
        }
    }
    
    
    /**
     * @brief Print out detection statistics.
     */
    static void print_statistics(void)
    {
        while (voltage_falls_detected)
        {
            voltage_falls_detected--;
            NRF_LOG_INFO("#%d fall detected", (int)voltage_falls_total);
        }
    }
    
    
    /**
     * @brief Initialize LPCOMP driver.
     */
    static void lpcomp_init(void)
    {
        uint32_t                err_code;
    
        nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
        config.input = NRF_LPCOMP_INPUT_2;
        // initialize LPCOMP driver, from this point LPCOMP will be active and provided
        // event handler will be executed when defined action is detected
        err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
        APP_ERROR_CHECK(err_code);
        nrf_drv_lpcomp_enable();
    }
    
    
    
    
    static void level_set(nrf_lpcomp_ref_t ref, nrf_lpcomp_detect_t det)	//NRF_LPCOMP_REF_SUPPLY_4_8  NRF_LPCOMP_DETECT_UP
    {
        uint32_t	err_code;
    
        nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
        config.input = NRF_LPCOMP_INPUT_2;
    		config.hal.hyst = NRF_LPCOMP_HYST_50mV;
    		config.hal.reference = ref;
    		config.hal.detection = det;
    
        // initialize LPCOMP driver, from this point LPCOMP will be active and provided
        // event handler will be executed when defined action is detected
        err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
        APP_ERROR_CHECK(err_code);
    		nrf_drv_lpcomp_enable();
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        nrf_gpio_cfg_output(WAVE_ON_PIN_NUMBER); // on this pin 2Hz wave will be generated
    
    #ifdef BSP_BUTTON_0
        // configure pull-up on first button
        nrf_gpio_cfg_input(BSP_BUTTON_0, NRF_GPIO_PIN_PULLUP);
    #endif
    
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        lpcomp_init();
    
        NRF_LOG_INFO("LPCOMP driver usage example started.");
    
        int i = 0;
    
        while (true)
        {
    
          if(i == 10)
            { 
              nrf_drv_lpcomp_uninit();
              level_set(NRF_LPCOMP_REF_SUPPLY_13_16, NRF_LPCOMP_DETECT_DOWN);
              NRF_LOG_INFO("New reference voltage set to 13_16");
            
            }
            
            if(i == 20)
            { 
              i = 0;
              nrf_drv_lpcomp_uninit();
              level_set(NRF_LPCOMP_REF_SUPPLY_9_16, NRF_LPCOMP_DETECT_DOWN);
              NRF_LOG_INFO("New reference voltage set to 9_16");
            
            }
    
            i++;
            print_statistics();
            bsp_board_led_on(BSP_BOARD_LED_1);
            NRF_GPIO->OUTCLR = (1 << WAVE_ON_PIN_NUMBER);
            nrf_delay_ms(100); // generate 100 ms pulse on selected pin
            print_statistics();
            bsp_board_led_off(BSP_BOARD_LED_1);
            NRF_GPIO->OUTSET = (1 << WAVE_ON_PIN_NUMBER);
            nrf_delay_ms(400);
            NRF_LOG_FLUSH();
        }
    }

    regards

    Jared

Reply
  • Hi,

    I wasn't able to reproduce this on my side, but I tried modifying the lp-comp example by adding your level_set() and see if it was able to change the reference voltage, which it did. Here is the code I used:

    #define WAVE_ON_PIN_NUMBER 2
    
    static volatile uint32_t voltage_falls_detected = 0;
    static volatile uint32_t voltage_falls_total    = 0;
    
    /**
     * @brief LPCOMP event handler is called when LPCOMP detects voltage drop.
     *
     * This function is called from interrupt context so it is very important
     * to return quickly. Don't put busy loops or any other CPU intensive actions here.
     * It is also not allowed to call soft device functions from it (if LPCOMP IRQ
     * priority is set to APP_IRQ_PRIORITY_HIGH).
     */
    static void lpcomp_event_handler(nrf_lpcomp_event_t event)
    {
        if (event == NRF_LPCOMP_EVENT_DOWN)
        {
            bsp_board_led_invert(BSP_BOARD_LED_0); // just change state of first LED
            voltage_falls_detected++;
            voltage_falls_total++;
        }
    }
    
    
    /**
     * @brief Print out detection statistics.
     */
    static void print_statistics(void)
    {
        while (voltage_falls_detected)
        {
            voltage_falls_detected--;
            NRF_LOG_INFO("#%d fall detected", (int)voltage_falls_total);
        }
    }
    
    
    /**
     * @brief Initialize LPCOMP driver.
     */
    static void lpcomp_init(void)
    {
        uint32_t                err_code;
    
        nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
        config.input = NRF_LPCOMP_INPUT_2;
        // initialize LPCOMP driver, from this point LPCOMP will be active and provided
        // event handler will be executed when defined action is detected
        err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
        APP_ERROR_CHECK(err_code);
        nrf_drv_lpcomp_enable();
    }
    
    
    
    
    static void level_set(nrf_lpcomp_ref_t ref, nrf_lpcomp_detect_t det)	//NRF_LPCOMP_REF_SUPPLY_4_8  NRF_LPCOMP_DETECT_UP
    {
        uint32_t	err_code;
    
        nrf_drv_lpcomp_config_t config = NRF_DRV_LPCOMP_DEFAULT_CONFIG;
        config.input = NRF_LPCOMP_INPUT_2;
    		config.hal.hyst = NRF_LPCOMP_HYST_50mV;
    		config.hal.reference = ref;
    		config.hal.detection = det;
    
        // initialize LPCOMP driver, from this point LPCOMP will be active and provided
        // event handler will be executed when defined action is detected
        err_code = nrf_drv_lpcomp_init(&config, lpcomp_event_handler);
        APP_ERROR_CHECK(err_code);
    		nrf_drv_lpcomp_enable();
    }
    
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
    
        nrf_gpio_cfg_output(WAVE_ON_PIN_NUMBER); // on this pin 2Hz wave will be generated
    
    #ifdef BSP_BUTTON_0
        // configure pull-up on first button
        nrf_gpio_cfg_input(BSP_BUTTON_0, NRF_GPIO_PIN_PULLUP);
    #endif
    
        uint32_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
        lpcomp_init();
    
        NRF_LOG_INFO("LPCOMP driver usage example started.");
    
        int i = 0;
    
        while (true)
        {
    
          if(i == 10)
            { 
              nrf_drv_lpcomp_uninit();
              level_set(NRF_LPCOMP_REF_SUPPLY_13_16, NRF_LPCOMP_DETECT_DOWN);
              NRF_LOG_INFO("New reference voltage set to 13_16");
            
            }
            
            if(i == 20)
            { 
              i = 0;
              nrf_drv_lpcomp_uninit();
              level_set(NRF_LPCOMP_REF_SUPPLY_9_16, NRF_LPCOMP_DETECT_DOWN);
              NRF_LOG_INFO("New reference voltage set to 9_16");
            
            }
    
            i++;
            print_statistics();
            bsp_board_led_on(BSP_BOARD_LED_1);
            NRF_GPIO->OUTCLR = (1 << WAVE_ON_PIN_NUMBER);
            nrf_delay_ms(100); // generate 100 ms pulse on selected pin
            print_statistics();
            bsp_board_led_off(BSP_BOARD_LED_1);
            NRF_GPIO->OUTSET = (1 << WAVE_ON_PIN_NUMBER);
            nrf_delay_ms(400);
            NRF_LOG_FLUSH();
        }
    }

    regards

    Jared

Children
No Data
Related