NRF54L15-DK : ADC Threshold Event Configuration using LPCOMP and ANADETECT

Hello Nordic Team,

I am currently working with the NRF54L15-DK. I have successfully configured the simple ADC on AIN4 (P1.11) and am able to read the raw sensor values.

Overlay : 

&adc {
	#address-cells = <1>;
	#size-cells = <0>;
	
	channel@4 {
		reg = <4>;
		zephyr,gain = "ADC_GAIN_1"; //"ADC_GAIN_1_4"
		zephyr,reference = "ADC_REF_INTERNAL";
		zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
		zephyr,input-positive = <NRF_SAADC_AIN4>; /* P1.11 */
		zephyr,resolution = <12>;
		//zephyr,oversampling = <2>;
	};
};


However, I would like to understand how to configure and set an ADC threshold using the ANADETECT feature. Specifically, I want to know how to detect when the ADC value crosses a defined threshold, either up , down or cross  and how to receive an event when this occurs. Additionally, I would like guidance on configuring the LPCOMP for this purpose.

Please provide the necessary prj.conf settings, .overlay configuration, and a sample example to help me implement this functionality.

Thanks & Regards,
Pratik Panchal

Parents
  • Hello  

    Thank you for your response.

    I reviewed the Nordic thread you shared and used the referenced code to configure and integrate a comparator into my application. I connected a potentiometer to the defined ADC pin for input variation.

    However, I expected to receive specific up or down events based on the configured threshold up/down values.
    I referred to the overlay file from the provided GitHub repository, but despite defining th_up and th_down values, the test_callback function does not increment the count on defined up or down threshold, but it only increments when we fully increase the potentiometer value to 4092 = 0.899V, and the event 
    bool event = comparator_get_output(test_dev); Returns 1 on 0.899V.

    Even I modified the value of th-up to 40, then also the event returns 1 only at 0.899V.

    Here, my application overlay for the comparator :

    &comp {
    	compatible = "nordic,nrf-comp";
    	main-mode = "SE";
    	psel = "AIN4"; /* P1.11 */
    	refsel = "VDD";
    	sp-mode = "HIGH";
    	th-up = <63>;
    	th-down = <31>;//<59>;
    	isource = "DISABLED";
    	status = "okay";
    };
     

    Could you please provide a sample that demonstrates the detailed usage of the APIs for configuring up/down thresholds and handling the corresponding events?

    Thanks & Regards,
    Pratik Panchal

  • Hi,

    Dont' have time to test the code, but make sure you understand the difference between COMP and LPCOMP:
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/comp.html 
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/lpcomp.html 

    One can be used in sleep and wakeup the chip (lpcomp), the other is only active while the CPU is running (comp).

    Kenneth

  • Hi Kenneth,

    Thank you for your response.

    I have reviewed the documents you provided and, based on that, I have defined the comparator.

    The comparator configuration is provided below in the overlay.

    .Overlay

    &comp {
    	compatible = "nordic,nrf-comp";
    	main-mode = "SE";
    	psel = "AIN4"; /* P1.11 */
    	refsel = "VDD";
    	sp-mode = "HIGH";
    	th-up = <63>;
    	th-down = <31>;//<59>;
    	isource = "DISABLED";
    	enable-hyst;
    	status = "okay";
    };

    and define the init_comparator() function and the IRQ interrupt. When the threshold is crossed (either upward or downward), the function comp_event_handler() should be invoked.

    Code:

    //comparator node
    static const struct device *test_dev = DEVICE_DT_GET(DT_ALIAS(test_comp));
    
    bool event_flag = true;  //<----------- this flag needed because sometime when we adc fall from up to down then both event triggered down and up
    
    void comp_event_handler(void)
    {
       if (NRF_COMP->EVENTS_UP) {
    		if(!event_flag)
    		{
    			printk("\tEVENTS_UP >>>>>> : [%d]\n", NRF_COMP->EVENTS_UP);
            	NRF_COMP->EVENTS_UP = 0;
    			NRF_COMP->EVENTS_DOWN = 0;
    			event_flag = true;
    		}
        }
    
    	if (NRF_COMP->EVENTS_DOWN)
    	{
    		if (event_flag)
    		{
    			printk("\tEVENTS_DOWN <<<<<< : [%d]\n", NRF_COMP->EVENTS_DOWN);
    			NRF_COMP->EVENTS_DOWN = 0;
    			NRF_COMP->EVENTS_UP = 0;
    			event_flag = false;
    		}
    	}
    
    int init_comparator()
    {
    struct comp_nrf_comp_se_config comp_config = {
    		.psel = COMP_NRF_COMP_PSEL_AIN4,
    		.sp_mode = COMP_NRF_COMP_SP_MODE_HIGH,
    		.isource = COMP_NRF_COMP_ISOURCE_DISABLED,
    		.refsel = COMP_NRF_COMP_REFSEL_VDD,
    		.th_down = 5, //<---- up threshold  
    		.th_up = 16, // <----- down threshold
    	};
    	comp_nrf_comp_configure_se(test_dev, &comp_config);
    	
    	// Configure event UP to publish
    	NRF_COMP->PUBLISH_UP = COMP_PUBLISH_UP_EN_Enabled;
    
    	// Define handler for event UP
    	NRF_COMP->INTENSET = COMP_INTENSET_UP_Msk;
    
    	// Check if the IRQ is already registered before connecting
    	if (!irq_is_enabled(DT_IRQN(DT_NODELABEL(comp)))) {
    		// Register the interrupt handler
    		IRQ_CONNECT(DT_IRQN(DT_NODELABEL(comp)), DT_IRQ(DT_NODELABEL(comp), priority), comp_event_handler, NULL, 0);
    
    		// Enable the interrupt
    		irq_enable(DT_IRQN(DT_NODELABEL(comp)));
    	} else {
    		printk("IRQ %d is already registered.\n", DT_IRQN(DT_NODELABEL(comp)));
    	}
    	
    		// Enable and start COMP
    	NRF_COMP->ENABLE = 2;
    	NRF_COMP->TASKS_START = 1;
    }


    Proj.conf
    # Comparator
    CONFIG_COMPARATOR=y
    CONFIG_NRFX_COMP=y
    CONFIG_SHARED_INTERRUPTS=y

    According to the formula provided in the documentation for the TH threshold registers.

    VDOWN = (THDOWN+1)/64*VREF
    VUP = (THUP+1)/64*VREF

    For example, with a threshold of 5, the expected voltage is 104 mV based on the given formula.

    e.g, Threshold =  5   
           Voltage(mv)  = 104
         
    I expected mv value as per the above formula, but it is not.

    However, in my testing, I observed:

    e.g, Threshold =  5   
           Voltage(mv)  = 168.75

    After reverse engineering, I found that the voltage calculation in the system follows this formula:

    V = ((TH + 1)/32) * Vref  // divided by 32 not 64

    Please find attached the log table in .txt.  

    Could you please clarify what changes or settings are required to achieve the voltage readings as per the formula provided in the documentation?

    Thanks & Regards,
    Pratik

    Formula : V = ((TH + 1)/32) * Vref
    Where Vref = 0.9V
    
    Threshold |       Voltage (mV)      |   ADC Raw
    -------------------------------------------------
        0     |          28.12          |        128       
        1     |          56.25          |        256       
        2     |          84.38          |        384       
        3     |          112.50         |        512       
        4     |          140.62         |        640       
        5     |          168.75         |        768       
        6     |          196.88         |        896       
        7     |          225.00         |       1024       
        8     |          253.12         |       1152       
        9     |          281.25         |       1280       
       10     |          309.38         |       1408       
       11     |          337.50         |       1536       
       12     |          365.62         |       1664       
       13     |          393.75         |       1792       
       14     |          421.88         |       1920       
       15     |          450.00         |       2048       
       16     |          478.12         |       2176       
       17     |          506.25         |       2304       
       18     |          534.38         |       2432       
       19     |          562.50         |       2560       
       20     |          590.62         |       2688       
       21     |          618.75         |       2816       
       22     |          646.88         |       2944       
       23     |          675.00         |       3072       
       24     |          703.12         |       3200       
       25     |          731.25         |       3328       
       26     |          759.38         |       3456       
       27     |          787.50         |       3584       
       28     |          815.62         |       3712       
       29     |          843.75         |       3840       
       30     |          871.88         |       3968       
       31     |          900.00         |       4096       
       32     |          928.12         |       4224       
       33     |          956.25         |       4352       
       34     |          984.38         |       4480       
       35     |         1012.50         |       4608       
       36     |         1040.62         |       4736       
       37     |         1068.75         |       4864       
       38     |         1096.88         |       4992       
       39     |         1125.00         |       5120       
    								  

  • Hello Kenneth,

    Just a quick reminder—have there been any updates or findings regarding my query?

    Thanks & Regards,
    Pratik




Reply Children
No Data
Related