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

Comparator External Connections

I am attempting to use the COMP section to build a relaxation oscillator. There appear to be a number of interactions between sections, some of which are subtly documented and some for which I find no documentation. For instance, the inability to set a GPIO output once a task is connected to a pin is documented but well-hidden. The fact that enabling a pin as a comparator input completely disables both digital inputs and digital outputs is not documented anywhere that I can find.

Bottom line is that I have everything working nicely as it should, except that the comparator sometimes appears to miss a transition and thereafter is hung. I fundamentally just need to be able to place the comparator output on a digital output pin, but the only way I can find to do that is via the crossing events from the comparator, feeding set and clr tasks of GPIOTE. This causes the same sort of problems as the early IBM PCs using edge-triggered interrupts: If you miss one, you're dead forever. Is there a better way to get the comparator output to appear on a pin? If not, how best can I initialize things to ensure that I don't miss a transition?

Parents
  • Hi, I'm doing the same thing - I'm building an RC generator that involves the COMP module.

    So far I haven't seen any glitches, so I decided to share my init code:

    #define CONFIG_COMP_OUT_PIN 28
    
    static nrf_ppi_channel_t m_ppi_channel;
    
    nrfx_comp_config_t const comp_config = {
    	    .reference = NRF_COMP_REF_VDD,
    	    .ext_ref = NRF_COMP_EXT_REF_7, //P0.31
    	    .main_mode = NRF_COMP_MAIN_MODE_SE,
    	    .threshold = {
    	    		.th_up = 34,
    				.th_down = 30
    	    },
    	    .speed_mode = NRF_COMP_SP_MODE_Low,
    	    .hyst = NRF_COMP_HYST_50mV,
    	    .isource = NRF_COMP_ISOURCE_Off, 
    	    .input = NRF_COMP_INPUT_1, //P0.03
    	    .interrupt_priority = 0
    };
    
    void nrfx_comp_irq_handler(void){
    
    }
    
    void init(void){
    	uint32_t gpiote_task_addr;
    	uint32_t comp_event_addr;
    
    	nrfx_comp_init(&comp_config, nrfx_comp_irq_handler);
    	nrfx_comp_start(NRFX_COMP_EVT_EN_CROSS_MASK, 0);
    
    	nrf_drv_ppi_init();
    
    	nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);
        nrf_drv_gpiote_out_init(CONFIG_COMP_OUT_PIN, &config);
    
    	nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    
    	comp_event_addr = nrf_drv_comp_event_address_get(NRF_COMP_EVENT_CROSS);
    	gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(CONFIG_COMP_OUT_PIN);
    
    	nrf_drv_ppi_channel_assign(m_ppi_channel, comp_event_addr, gpiote_task_addr);
    	nrf_drv_ppi_channel_enable(m_ppi_channel);
    
    	nrf_drv_gpiote_out_task_enable(CONFIG_COMP_OUT_PIN);
    	nrf_drv_gpiote_set_task_trigger(CONFIG_COMP_OUT_PIN); //Start oscillations
    }

    I have inputs on P0.03 (-) and P0.31 (+), and an output on P0.28 (OUT) with this code.

    Hope this helps!

    Regards,

    L. B.

    p.s. My target is NRF52832 / nRF5_SDK_17.0.2_d674dde / gcc version 10.3.1 20210621 (release) (GNU Arm Embedded Toolchain 10.3-2021.07)

  • For anyone searching this, the comp if wiring both EVENT_DOWN and EVENT_UP to the GPIOTE_SET AND GPIOTE_CLEAR will eventually miss an event and go out of sync.

    The trick instead is to use the single EVENT_CROSS and wire it to GPIOTE_OUT with the polarity set to invert.

    To do this you must have a known condition with the comparator and enable GPIOTE default output to match. Then leave this be and don't change it. If you need to bypass the pin output use the GPIO drive high/low disconnect and pullup/pulldown if you need to.

    The comparator still needs to be faster than your input signal, I just leave it in high speed and it is fine with a 1MHz signal.

    I can confirm this works well!

    Andrew

Reply
  • For anyone searching this, the comp if wiring both EVENT_DOWN and EVENT_UP to the GPIOTE_SET AND GPIOTE_CLEAR will eventually miss an event and go out of sync.

    The trick instead is to use the single EVENT_CROSS and wire it to GPIOTE_OUT with the polarity set to invert.

    To do this you must have a known condition with the comparator and enable GPIOTE default output to match. Then leave this be and don't change it. If you need to bypass the pin output use the GPIO drive high/low disconnect and pullup/pulldown if you need to.

    The comparator still needs to be faster than your input signal, I just leave it in high speed and it is fine with a 1MHz signal.

    I can confirm this works well!

    Andrew

Children
No Data
Related