PPI delay due to interrupt disable.

Hello,
I implemented the function to receive an external 62.5KHz clock as an interrupt and repeat the process at a very regular time using PPI.
However, sometimes PPI processing is delayed(No interrupt received) as shown in the following figure. What could be the reason for this?


I guess the ability to receive an external 62.5KHz as an interrupt is delayed because of the interrupt inhibition of the MCU.
Is there a way to solve this interrupt receive delay and PPI delay?

Best Regards,

SunBae Yim.

  • Hello SunBae Yim,

    It looks to me like your PPI might not be set up correctly. Could you share the section of your code in which this takes place?
    When PPI is set up correctly you will not need the CPU to handle any interrupts, in order for the connected TASK to be triggered by the generated EVENT.
    Therefore, there should be no delay on the triggering of the TASK as well, since it will happen as soon as the connected EVENT is generated.

    Are you using the nRF5 SDK, and if so, are also using the SoftDevice in your project?

    Best regards,
    Karl

  • My source code is here;

    /*******************************************************************************
     * @file	
     * @author	
     * @version	V1.0.0
     * @date	2022-09-05
     * @brief   
     ******************************************************************************/
    
    #include "sdk_common.h"
    			
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    #include "nrf.h"
    #include "boards.h"
    #include "app_error.h"
    #include "nrf_drv_saadc.h"
    #include "nrfx_gpiote.h"
    #include "app_timer.h"
    #include "nrf_drv_timer.h"
    #include "nrf_delay.h"
    #include "nrf_drv_ppi.h"
    #include "ada2200_spi.h"
    #include "ble_nus.h"
    #include "fstorage.h"
    #include "measurements.h"
    #include "meas_pd_voltage_full.h"
    #include "mcp4725_i2c.h"
    #include "ad5272_i2c.h"
    #include "main_timer.h"
    #include "battery_saadc.h"
    #include "main.h"
    
    #define FULL_REF_VOLTAGE_IN_MILLIVOLTS   	600.0f                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
    #define FULL_PRE_SCALING_COMPENSATION    	6.0f                                       /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
    #define FULL_ADC_RES_10BITS             	1024.0f                                    /**< Maximum digital value for 10-bit ADC conversion. */
    
    /**@brief Macro to convert the result of ADC conversion in millivolts.
     *
     * @param[in]  ADC_VALUE   ADC result.
     *
     * @retval     Result converted to millivolts.
     */
    #define FULL_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
    				((((ADC_VALUE) * FULL_REF_VOLTAGE_IN_MILLIVOLTS) / FULL_ADC_RES_10BITS) * FULL_PRE_SCALING_COMPENSATION)
    
    #define FULL_SAMPLES_IN_BUFFER 		1
    static nrf_saadc_value_t pd_full_adc_buf[2][FULL_SAMPLES_IN_BUFFER];
    bool  pd_adc_full_start	= false;
    
    
    uint8_t led_full_list[6];
    uint8_t pd_full_list[12];
    
    uint8_t led_full_list_a[6]	= {1,2,3,4,5,6};
    uint8_t pd_full_list_a[12]	= {5,6,7,8,9,10,15,16,17,18,19,20};
    
    uint8_t led_full_list_b[6]	= {7,8,9,10,11,12};
    uint8_t pd_full_list_b[12]	= {6,5,4,3,2,1,16,15,14,13,12,11};
    
    uint8_t led_full_list_c[6]	= {13,14,15,16,17,18};
    uint8_t pd_full_list_c[12]	= {15,16,17,18,19,20,5,6,7,8,9,10};
    
    uint8_t led_full_list_d[6]	= {19,20,21,22,23,24};
    uint8_t pd_full_list_d[12]	= {16,15,14,13,12,11,6,5,4,3,2,1};
    
    
    static uint16_t FULL_DELAY_CLK = 0;
    static bool full_main_delay = false;
    static bool full_main_testing = false;
    #define full_main_clock_delay(delay_cnt) 	full_main_delay = true;\
    										full_main_testing = false;\
    										FULL_DELAY_CLK = delay_cnt;
    
    #define FULL_CYCLE_CNT 			32	/* Dummy=16, Cycle_Max_Cnt=32*/
    /* ----------------  +  --------                         */
    /*       Dummy 16       Cycle = 8                        */
    /*                                                       */
    /* ----------------  +  ----------------                 */
    /*       Dummy 16       Cycle = 16                       */
    /*                                                       */
    /* ----------------  +  ------------------------         */
    /*       Dummy 16       Cycle = 24                       */
    /*                                                       */
    /* ----------------  +  -------------------------------- */
    /*       Dummy 16       Cycle = 32                       */
    /*                                                       */
    
    #define FULL_CYCLE_SEND_CNT 	12
    
    static float	full_cycle_buff[FULL_CYCLE_CNT] = {0,};
    static float	full_cycle_send_buff[FULL_CYCLE_SEND_CNT] = {0,};
    
    uint8_t	FULL_IRQ_NO			= 7;
    #define FULL_PD_NO			11
    #define FULL_LED_NO			5
    
    static int16_t 	buf_seq		= 0;
    static int16_t 	irq_no 		= 0;
    static int8_t 	pd_no 		= 0;
    static int8_t 	led_no 		= 0;
    
    extern bool pd_adc_full_a_start; 
    extern bool pd_adc_full_a_end; 
    
    extern bool pd_adc_full_b_start; 
    extern bool pd_adc_full_b_end; 
    
    extern bool pd_adc_full_c_start; 
    extern bool pd_adc_full_c_end; 
    
    extern bool pd_adc_full_d_start;
    extern bool pd_adc_full_d_end; 
    
    
    static nrf_ppi_channel_t	m_ppi_channel;
    
    extern char		ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
    
    
    void full_ppi_init(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        uint32_t gpiote_event_addr = nrf_drv_gpiote_in_event_addr_get(ADA2200_SYNCO_PIN);	
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get();
    
        /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                              gpiote_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_ppi_uninit(void)
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_uninit();
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_sampling_event_enable(void)
    {
        ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void full_sampling_event_disable(void)
    {
    	ret_code_t err_code = nrf_drv_ppi_channel_disable(m_ppi_channel);
    	APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief Function for handling the ADC interrupt.
     *
     * @details  This function will fetch the conversion result from the ADC, convert the value into
     *           percentage and send it to peer.
     */
    static inline void full_main_meas_process(void)
    {
    	static float sum = 0.0f;
    
    	if(irq_no < FULL_IRQ_NO) {
    		irq_no++;
    	} else if(irq_no >= FULL_IRQ_NO) {
    
    		///////////////////////////////////////////				/* Calculation Cycle-8, Cycle-16, Cycle-24, Cycle-32 */
    		for(uint8_t i = 0; i <= FULL_IRQ_NO; i++) {
    			sum += full_cycle_buff[i];
    		}
    
    		full_cycle_send_buff[buf_seq] = sum;
    //#if FEATURE_PRINTF
    //		printf("\r\n===============\r\n");
    //		printf("sum = %f\r\nfull_cycle_send_buff=\r\n", sum);
    //
    //		for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    //			printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    //		}
    //		printf("===============\r\n\r\n");
    //#endif
    
    		sum = 0;
    
    		for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    			full_cycle_buff[i] = 0.0f;
    		}
    
    		buf_seq++;
    		irq_no = 0;
    		
    		///////////////////////////////////////////				/* PD Changed */
    		if(pd_no < FULL_PD_NO) {
    			
    			pd_no++;
    #if FEATURE_PRINTF
    			printf("\r\nPD changed(a) to %d ---------------------------\r\n\r\n", pd_no);
    #endif
    
    			led_pd_matching_value_set(led_full_list[led_no], pd_full_list[pd_no]); /* MCP4725 DAC setting and PD on */
    			full_main_clock_delay(m_config.pd_delay_us/16);
    
    		} else if(pd_no >= FULL_PD_NO) {
    			pd_no = 0;
    			buf_seq = 0;
    
    			printf("Tj%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n", led_full_list[led_no], full_cycle_send_buff[0], full_cycle_send_buff[1], full_cycle_send_buff[2], full_cycle_send_buff[3], full_cycle_send_buff[4], full_cycle_send_buff[5], full_cycle_send_buff[6], full_cycle_send_buff[7], full_cycle_send_buff[8], full_cycle_send_buff[9], full_cycle_send_buff[10], full_cycle_send_buff[11]);
    			sprintf(ble_tx_buffer, "Tj%d,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n", led_full_list[led_no], full_cycle_send_buff[0], full_cycle_send_buff[1], full_cycle_send_buff[2], full_cycle_send_buff[3], full_cycle_send_buff[4], full_cycle_send_buff[5], full_cycle_send_buff[6], full_cycle_send_buff[7], full_cycle_send_buff[8], full_cycle_send_buff[9], full_cycle_send_buff[10], full_cycle_send_buff[11]);
    			data_tx_handler(ble_tx_buffer);
    			
    #if FEATURE_PRINTF
    			printf(">>>>> SEND 12 data <<<<<\r\n");
    			printf("PD changed(b) to %d ---------------------------\r\n", pd_no);
    #endif
    			for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    				full_cycle_send_buff[i] = 0.0f;
    			}
    
    			/////////////////////////////////////////////
    			led_pd_matching_value_set(led_full_list[led_no], pd_full_list[pd_no]); /* MCP4725 DAC setting and PD on */
    //			full_main_clock_delay(m_config.pd_delay_us/16);				/* PD와 LED 딜레이가 이중으로 적용되므로 하나 막는다. */
    			/////////////////////////////////////////////
    
    			////////////////////////////////////////////////////	/* LED Changed */
    			if(led_no < FULL_LED_NO) {
    				led_no++;
    #if FEATURE_PRINTF
    				printf("LED changed to %d ---------------------------\r\n", led_no);
    #endif
    				////////////////////////////////////////////////
    				led_on(led_full_list[led_no]);
    				full_main_clock_delay(m_config.led_delay_us/16);
    				////////////////////////////////////////////////
    
    			} else if(led_no >= FULL_LED_NO) {
    				if(pd_adc_full_a_start == true) {
    					pd_adc_full_a_start = false;
    					pd_adc_full_a_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_b_start == true) {
    					pd_adc_full_b_start = false;
    					pd_adc_full_b_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_c_start == true) {
    					pd_adc_full_c_start = false;
    					pd_adc_full_c_end = true;
    								
    					main_timer_start();
    				}
    
    				if(pd_adc_full_d_start == true) {
    					pd_adc_full_d_start = false;
    					pd_adc_full_d_end = true;
    								
    					main_timer_start();
    				}
    				
    				printf("\r\n");
    				full_adc_end();
    				return;
    			}
    		}
    	}
    } 
    
    
    static void full_voltage_handler(nrf_drv_saadc_evt_t const * p_event)	/* PD Voltage reading */
    {
    
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {	
    		static uint16_t main_delay_cnt = 0;
    		static float imsi_voltage = 0;
    
    #if FEATURE_FOR_SCOPE    
    		nrf_gpio_pin_set(ADC_CLK_18);
    		nrf_gpio_pin_clear(ADC_CLK_18);
    #endif
    
            nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, FULL_SAMPLES_IN_BUFFER);
    		imsi_voltage = FULL_VOUT_IN_MILLI_VOLTS(p_event->data.done.p_buffer[0]);
    
    		if(full_main_testing == true) {
    
    #if FEATURE_PRINTF
    			printf("[buf_seq=%d], led_no=%d(%d), pd_no=%d(%d), irq_no=%d V=%f\r\n", buf_seq, led_no, led_full_list[led_no], pd_no, pd_full_list[pd_no], irq_no, imsi_voltage);
    #endif			
    			full_cycle_buff[irq_no] = imsi_voltage;
    
    //#if FEATURE_PRINTF
    //			printf("full_cycle_buff=\r\n");
    //			switch(m_config.pd_adc_cnt){
    //				case 8:
    //					for(uint8_t i = 16; i < 24; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 16:
    //					for(uint8_t i = 16; i < 32; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 24:
    //					for(uint8_t i = 16; i < 40; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				case 32:
    //					for(uint8_t i = 16; i < 48; i++) {
    //						printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    //					}
    //					break;
    //			
    //				default:
    //					break;
    //			}
    //			printf("===============\r\n");
    //		
    //			printf("full_cycle_send_buff=\r\n");
    //			for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    //				printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    //			}
    //			printf("===============\r\n\r\n");
    //#endif
    
    			full_main_meas_process();
    			
    		}else if(full_main_delay) {
    #if FEATURE_PRINTF
    			printf("m_d = %d  ", main_delay_cnt);
    #endif			
    			if(main_delay_cnt++ >= FULL_DELAY_CLK-1) {
    #if FEATURE_PRINTF
    				printf("\r\n");
    #endif					
    				main_delay_cnt = 0;
    				full_main_delay = false;
    				full_main_testing = true;
    			}
    		}
        }
    }
    
    
    void full_adc_init(void)
    {
    	static nrfx_saadc_config_t default_config;
    	default_config.resolution			= (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION; /* Resolution is 10bits */
    	default_config.oversample			= (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE; /* Over Sampling Disabled */
    	default_config.interrupt_priority	= NRFX_SAADC_CONFIG_IRQ_PRIORITY;						/* Interrupt Priority is 0(Highest) */
    	default_config.low_power_mode		= NRFX_SAADC_CONFIG_LP_MODE;							/* Low Power Mode is Disabled */
    
    	static nrf_saadc_channel_config_t config;
    	config.resistor_p	= NRF_SAADC_RESISTOR_DISABLED;
    	config.resistor_n	= NRF_SAADC_RESISTOR_DISABLED;
    	config.gain 		= NRF_SAADC_GAIN1_6;
    	config.reference	= NRF_SAADC_REFERENCE_INTERNAL;
    	config.acq_time 	= NRF_SAADC_ACQTIME_10US;
    	config.mode 		= NRF_SAADC_MODE_DIFFERENTIAL;
    	config.burst		= NRF_SAADC_BURST_DISABLED;
    	config.pin_p		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
    	config.pin_n		= (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN1);
    	
    	ret_code_t err_code = nrf_drv_saadc_init(&default_config, full_voltage_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_channel_init(0, &config);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_buffer_convert(pd_full_adc_buf[0], FULL_SAMPLES_IN_BUFFER);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_drv_saadc_buffer_convert(pd_adc_buf[1], SIM_SAMPLES_IN_BUFFER);
    	APP_ERROR_CHECK(err_code);	
    }
    
    
    
    void full_adc_uninit(void)
    {
    #if FEATURE_PRINTF
    	printf("pd_full_adc_uninit\r\n");
    #endif
    
    	nrf_drv_saadc_uninit();
    	nrf_drv_saadc_channel_uninit(0);
    }
    
    
    void full_adc_start(void)
    {
    
    	battery_timer_stop();
    
    	full_adc_init();
    	full_irq_init();
    	full_ppi_init();
    	ada2200_start();
    
    	full_sampling_event_enable();	
    
    	if(pd_adc_full_a_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_A start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_a, 6);
    		memcpy(pd_full_list, pd_full_list_a, 12);
    	}
    
    	if(pd_adc_full_b_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_B start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_b, 6);
    		memcpy(pd_full_list, pd_full_list_b, 12);
    	}
    
    	if(pd_adc_full_c_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_C start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_c, 6);
    		memcpy(pd_full_list, pd_full_list_c, 12);
    	}
    
    	if(pd_adc_full_d_start == true) {
    #if FEATURE_PRINTF
    		printf("\r\n===============================================================\r\n");
    		printf("===== Full_D start ============================================\r\n");
    		printf("===============================================================\r\n");
    #endif
    		memcpy(led_full_list, led_full_list_d, 6);
    		memcpy(pd_full_list, pd_full_list_d, 12);
    	}
    
    #if FEATURE_PRINTF
    	printf("LED(0) ON, PD(0) ON\r\n");
    #endif
    
    	led_on(led_full_list[0]);
    
    	led_pd_matching_value_set(led_full_list[0], pd_full_list[0]); /* MCP4725 DAC setting And PD on */
    	nrf_delay_us(m_config.pd_delay_us);
    
    #if FEATURE_PRINTF
    	printf("\r\nfull_cycle_buff Cleared<start>\r\n");
    	printf("full_cycle_send_buff Cleared<start>\r\n");
    #endif
    	
    	for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    		full_cycle_buff[i] = 0.0f;
    	}
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		full_cycle_send_buff[i] = 0.0f;
    	}
    
    #if FEATURE_PRINTF
    	printf("full_cycle_buff=\r\n");
    	switch(m_config.pd_adc_cnt){
    		case 8:
    			for(uint8_t i = 16; i < 24; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 16:
    			for(uint8_t i = 16; i < 32; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 24:
    			for(uint8_t i = 16; i < 40; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 32:
    			for(uint8_t i = 16; i < 48; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		default:
    			break;
    	}
    	printf("===============\r\n");
    
    	printf("===============\r\n");
    
    	printf("full_cycle_send_buff=\r\n");
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    	}
    	printf("===============\r\n\r\n");
    #endif
    
    	buf_seq		= 0;
    	irq_no		= 0;
    	pd_no 		= 0;
    	led_no		= 0;
    
    	full_main_testing = true;
    	
    }
    
    
    void full_adc_end(void) 
    {
    #if FEATURE_PRINTF
    	printf("full_adc_end\r\n");
    #endif
    
    	battery_timer_start();
    
    	ada2200_stop();
    	full_sampling_event_disable();
    
    	full_irq_uninit();
    	full_adc_uninit();
    	full_ppi_uninit();
    
    #if FEATURE_PRINTF
    	printf("\r\nfull_cycle_buff Cleared<end>\r\n");
    	printf("full_cycle_send_buff Cleared<end>\r\n");
    #endif
    
    	for(uint8_t i = 0; i < FULL_CYCLE_CNT; i++) {
    		full_cycle_buff[i] = 0.0f;
    	}
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		full_cycle_send_buff[i] = 0.0f;
    	}
    
    #if FEATURE_PRINTF
    	printf("full_cycle_buff=\r\n");
    	switch(m_config.pd_adc_cnt){
    		case 8:
    			for(uint8_t i = 16; i < 24; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 16:
    			for(uint8_t i = 16; i < 32; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 24:
    			for(uint8_t i = 16; i < 40; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		case 32:
    			for(uint8_t i = 16; i < 48; i++) {
    				printf("<%d>= %f\r\n", i, full_cycle_buff[i]);
    			}
    			break;
    	
    		default:
    			break;
    	}
    	printf("===============\r\n");
    
    	printf("===============\r\n");
    
    	printf("full_cycle_send_buff=\r\n");
    	for(uint8_t i = 0; i < FULL_CYCLE_SEND_CNT; i++) {
    		printf("<%d>= %f\r\n", i, full_cycle_send_buff[i]);
    	}
    	printf("===============\r\n\r\n");
    #endif
    
    	led_off(99);
    	pd_off(99);
    
    	full_main_testing = false;
    	full_main_delay = false;
    }
    
    
    void full_irq_init(void){
        ret_code_t err_code;
    #if FEATURE_PRINTF
    	printf("full_irq_init\r\n");
    #endif
    
    	/* Initialize int pin */
    	if (!nrfx_gpiote_is_init())
    	{
    	  err_code = nrfx_gpiote_init();
    	  APP_ERROR_CHECK(err_code);
    	}
    
        nrfx_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
        in_config.pull = NRF_GPIO_PIN_PULLDOWN;
    
        err_code = nrfx_gpiote_in_init(ADA2200_SYNCO_PIN, &in_config, NULL);
        APP_ERROR_CHECK(err_code);
    
        nrfx_gpiote_in_event_enable(ADA2200_SYNCO_PIN, true);
    }
    
    
    void full_irq_uninit(void){
    #if FEATURE_PRINTF
    	printf("full_irq_uninit\r\n");
    #endif	
    	nrfx_gpiote_in_event_disable(ADA2200_SYNCO_PIN);
    	nrfx_gpiote_in_uninit(ADA2200_SYNCO_PIN);
    }
    
    

    Please review whether PPI, EasyDMA, etc. are implemented well.

    And I use 2 channels for ADC sampling with DIFFRENTIAL Mode. It takes a register value and calculates the actual voltage value using the following formula:

    #define FULL_REF_VOLTAGE_IN_MILLIVOLTS   	600.0f                                     /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
    #define FULL_PRE_SCALING_COMPENSATION    	6.0f                                       /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
    #define FULL_ADC_RES_10BITS             	1024.0f                                    /**< Maximum digital value for 10-bit ADC conversion. */
    
    #define FULL_VOUT_IN_MILLI_VOLTS(ADC_VALUE)\
    				((((ADC_VALUE) * FULL_REF_VOLTAGE_IN_MILLIVOLTS) / FULL_ADC_RES_10BITS) * FULL_PRE_SCALING_COMPENSATION)

    Is it correct to use this formula? Or should the formula be changed?

    Best Regards,

    SunBae Yim.

  • Hello SunBae Yim,

    Thank you for your patience with this.

    Briefly looking through the provided code it looks alright to me, 
    is there anything specifically you would like for me to take a look at in the code? Is there anything that is not working as expected?

    Two minor comment:

    - it seems that you do not check the error the returned error code from nrf_drv_saadc_buffer_convert, which I would recommend that you do.

    - you have a lot of clutter in the code; magic numbers and commented out code lines. To increase maintainability I would recommend that you replace the magic numbers with appropriate defines, and that you move the scrap code into a separate file if you feel like you might need it again later.

    ParanBada said:
    Is it correct to use this formula? Or should the formula be changed?

    Yes, this is correct.
    The formula can be derived from the Digital Output section in the SAADC documentation.

    Best regards,
    Karl

  • Hello,

    I improved the ADC sampling using PPI technique. It performs ADC sampling in synchronization with an external 62.5KHz clock.


    However, ADC sampling may be delayed as shown by the arrow in the figure.
    Why is there such a delay? What is the solution?
    This is a very important and urgent issue.
    I would appreciate it if you could help me.

    Best Regards,

    SunBae Yim.

  • I am glad to hear that you improved the sampling through PPI! :) 

    ParanBada said:
    However, ADC sampling may be delayed as shown by the arrow in the figure.

    What exactly are the green lines set by? What are you scoping here, and where exactly is the setup for this in your code?
    It seems to me that the green lines are not exactly aligned with the 62.5 kHz input, and so I suspect that the delay here is not an actual delay of the sampling, but rather a delay on the processing of the tasks/events on the measuring side.
    Since PPI is used to trigger the sampling then the SAMPLE task will be triggered immediately by the triggering event.

    Best regards,
    Karl

Related