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

Using Comparator as "Window" for potentiometer wake up.

I am trying to use the comparator to wake me up when a potentiometer is moved a certain amount.

Before I sleep I read the ADC value of the comparator and use this to set the upper and lower value of the comparator.

My issue is this only works when I move the POT down.  For some reason the UP direction is not working.

I am including the NRF_DRV_COMP_EVT_EN_UP_MASK in my nrf_drv_comp_start  command.  What else needs to be added to get an event when the voltage crosses the upper threshold?

This is using the nRF52832 , SDK14

#define COMPTH_MAX 63
#define COMPTH_INTERVAL 5

void zoom_comp_init(void)
{

    uint32_t err_code;

    nrf_saadc_value_t vdd, adcval;

    nrf_drv_comp_uninit();

    APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(4, &vdd));

    APP_ERROR_CHECK(nrf_drv_saadc_sample_convert(0, &adcval));

    // hw_adc_disable();

    float frac = (float)adcval / (float)vdd;

    // ref_setting = frac*16.0;
    static uint8_t myrefval = 0; //(0-16)
    frac *= 64.0;
    myrefval = (uint8_t)frac;
    
    nrf_drv_comp_config_t myCompConfig = NRF_DRV_COMP_DEFAULT_CONFIG(NRF_COMP_INPUT_0);

    myCompConfig.input = NRF_COMP_INPUT_0;
    myCompConfig.main_mode = NRF_COMP_MAIN_MODE_SE;
    myCompConfig.reference = NRF_COMP_REF_VDD;
    myCompConfig.speed_mode = NRF_COMP_SP_MODE_Normal;
    //myCompConfig.hyst = NRF_COMP_HYST_50mV;
    myCompConfig.isource = COMP_ISOURCE_ISOURCE_Off;
    myCompConfig.interrupt_priority = 6;

    if (myrefval > (COMPTH_MAX - COMPTH_INTERVAL) )
    {
	myCompConfig.threshold.th_down = COMPTH_MAX - COMPTH_INTERVAL*2;
	myCompConfig.threshold.th_up = COMPTH_MAX;
    }
    else if (myrefval < COMPTH_INTERVAL)
    {
	myCompConfig.threshold.th_down = 0;
	myCompConfig.threshold.th_up = COMPTH_INTERVAL*2;
    }
    else
    {
	myCompConfig.threshold.th_down = myrefval - COMPTH_INTERVAL;
	myCompConfig.threshold.th_up = myrefval + COMPTH_INTERVAL;
    }

    NRF_LOG_INFO("ZOOM |  Reference Value=%d", myrefval);
    NRF_LOG_INFO("ZOOM |  TH_DOWN=%d  TH_UP=%d", myCompConfig.threshold.th_down, myCompConfig.threshold.th_up);

    err_code = nrf_drv_comp_init(&myCompConfig, comp_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_comp_start( NRF_DRV_COMP_EVT_EN_DOWN_MASK | NRF_DRV_COMP_EVT_EN_UP_MASK ,
        NRF_DRV_COMP_SHORT_STOP_AFTER_UP_EVT | NRF_DRV_COMP_SHORT_STOP_AFTER_DOWN_EVT | NRF_DRV_COMP_SHORT_STOP_AFTER_CROSS_EVT);

static void comp_event_handler(nrf_comp_event_t event)
{

    asm("nop;");
    NRF_LOG_INFO("Comp Event.");
    switch (event)
    {
	case NRF_COMP_EVENT_CROSS:
	    NRF_LOG_INFO("Comp CROSS Event.");
	    sysEvents.zoom_change = 1;
	    break;
	case NRF_COMP_EVENT_DOWN:

	    // sysEvents.zoom_change = 1;
	    //if (update_zoom())
	    {
		NRF_LOG_INFO("Comp DOWN Event.");
		sysEvents.zoom_change = 1;
	    }
	    break;
	case NRF_COMP_EVENT_UP:

	    //if (update_zoom())
	    {
		NRF_LOG_INFO("Comp UP Event.");
		sysEvents.zoom_change = 1;
	    }
	    // sysEvents.zoom_change = 1;
	    break;
    }
}

  • Hi,

    This looks correct. Are you not getting any UP events at all? I tried this without ADC reading on the DK, and I get both UP and DOWN events. Had to change your code to call nrf_drv_comp_start() in the callback to receive multiple events, as the NRF_DRV_COMP_SHORT_STOP_AFTER_XX_EVT parameters will stop the comp after one event.

    What values are you normally passing to threshold.th_down and myCompConfig.threshold.th_up? If these are way off, you might not reach the upper treashold to trigger the up event.

    Best regards,
    Jørgen

  • I am verifying the up/down threshhold view an NRF_LOG print out.

    Perhaps I am misunderstanding what causes an event?

    My thinking was that if the input went outside of just one of the thresholds, then an event would be generated for that threshold.

    What I am seeing is that it seems like the input as to move past both thresholds.  Is this right?  That would invalidate my approach.

    I tried forcing the system to only see UP events and to not stop after event.

    nrf_drv_comp_start( NRF_DRV_COMP_EVT_EN_UP_MASK ,
    NULL );

    I just hard coded some different thresholds to see what happens.

    myCompConfig.threshold.th_down = 20;
    myCompConfig.threshold.th_up = 40;

      It seems like I have to go under the lower threshold and back up to trip the upper.  That doesn't seem right to me, but again maybe I misunderstand how the thresholds work.

  • I think your understanding should be correct. This is taken from the product specifications:

    Event generation on output changes

    • UP event on VIN- > VIN+
    • DOWN event on VIN- < VIN+
    • CROSS event on VIN+ and VIN- crossing
    • READY event on core and internal reference (if used) ready

    Use the PSEL register to select any of the AIN0-AIN7 pins as VIN+ input, irregardless of the operation mode selected for the comparator. The source of VIN- depends on which operation mode is used:

    • Differential mode: Derived directly from AIN0 to AIN7
    • Single-ended mode: Derived from VREF. VREF can be derived from VDD, AIN0-AIN7 or internal 1.2 V, 1.8 V and 2.4 V references.

    The events should be generated on output changes (OUTPUT: 0 = BELOW (VIN+ < VIN-), 1 = ABOVE (VIN+ > VIN-)). When the events will be generated will depend on the initial value of VIN+. Please study the diagram in Figure 5 in the single-ended mode chapter.

  • So, the end conclusion of this would then mean I cannot set the upper and lower thresholds above and below my current input voltage and interrupt when the potentiometer is moved up or down correct?  If VIN has to cross both thresholds to get an event then I would have to pick one direction for the POT to move in order to get an event.

    Are there any other means to do this?  The only other option i can think of is to wake periodically and read the input as an ADC to see if the user changed the POT position.  This seems like it would cause much worse battery life and average power consumption.

  • Yes, this is correct. You will only get events when the output change.

    What is your detection delay and current consumption requirements? The SAADC can do periodic sampling with quite low average current consumption, and it might not be that much higher than the COMP run current.

Related