I am trying to time a capacitor discharge through different resistance sensors for greater resolution than an ADC. I did this using the GPIO functions initially but the SD will sometimes interfere and cause the readings to be off. I have decided to try this via PPI and I have it just about working. The only issue I am having is the GPIOTE IN event does not seem to be triggering the timer capture task. I can use the IN Event callback to manually capture the value which does work but I really want to do it via PPI to avoid interference from the SD. I have included an annotated example; hopefully I am just missing something really simple:
#define TEMP_COMP_LINE 11 #define TEMP_THERM_LINE 12 #define TEMP_SENSE_LINE 13 // Use a counter so we can manually increment it and start the PPI chain nrf_drv_timer_t start_counter = NRF_DRV_TIMER_INSTANCE(2); // Timer for capacitor discharge nrf_drv_timer_t discharge_timer = NRF_DRV_TIMER_INSTANCE(3); // PPI Channels nrf_ppi_channel_t ppi_1, ppi_2; uint32_t line_discharge_time = 0; void timer_event_handler(nrf_timer_event_t event_type, void * p_context){} void sense_dummy_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { // Uncommenting this will allow timer capture on IN event! //line_discharge_time = nrf_drv_timer_capture(&discharge_timer, NRF_TIMER_CC_CHANNEL0); __NOP(); } uint32_t do_thermistor_ppi(uint32_t line) { // Disable unused lines uint32_t other_line = TEMP_THERM_LINE; if (line == TEMP_THERM_LINE) { other_line = TEMP_COMP_LINE; } // GPIOTEs nrf_drv_gpiote_out_config_t line_cfg = GPIOTE_CONFIG_OUT_TASK_LOW; nrf_drv_gpiote_out_init(line, &line_cfg); nrf_drv_gpiote_out_clear(line); nrf_drv_gpiote_in_config_t sense_cfg = GPIOTE_CONFIG_IN_SENSE_HITOLO(true); // Init Manual Start Counter nrf_drv_timer_config_t sc_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; sc_cfg.mode = NRF_TIMER_MODE_COUNTER; sc_cfg.bit_width = NRF_TIMER_BIT_WIDTH_8; nrf_drv_timer_init(&start_counter, &sc_cfg, timer_event_handler); // Cause counter to trigger compare[0] on count of 1 nrf_drv_timer_compare(&start_counter, NRF_TIMER_CC_CHANNEL0, 1, true); // Init Discharge timer nrf_drv_timer_config_t dt_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; dt_cfg.mode = NRF_TIMER_MODE_TIMER; dt_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; dt_cfg.frequency = NRF_TIMER_FREQ_8MHz; nrf_drv_timer_init(&discharge_timer, &dt_cfg, timer_event_handler); // Configure a PPI channel to start the discharge timer for static compare // line when manual count is incremented to 1. nrf_drv_ppi_channel_alloc(&ppi_1); nrf_drv_ppi_channel_assign(ppi_1, nrf_drv_timer_event_address_get(&start_counter, NRF_TIMER_EVENT_COMPARE0), nrf_drv_timer_task_address_get(&discharge_timer, NRF_TIMER_TASK_START)); // Set the capacitor to discharge at the same moment the timer starts for count 1 nrf_drv_ppi_channel_fork_assign(ppi_1, nrf_drv_gpiote_out_task_addr_get(line)); // Configure a PPI channel to stop the discharge timer whenever a sense line goes low nrf_drv_ppi_channel_alloc(&ppi_2); nrf_drv_ppi_channel_assign(ppi_2, nrf_drv_gpiote_in_event_addr_get(TEMP_SENSE_LINE), nrf_drv_timer_task_address_get(&discharge_timer, NRF_TIMER_TASK_CAPTURE0)); nrf_drv_ppi_channel_enable(ppi_1); nrf_drv_ppi_channel_enable(ppi_2); // Make sure both timers are enabled and cleared nrf_drv_timer_clear(&start_counter); nrf_drv_timer_enable(&start_counter); nrf_drv_timer_clear(&discharge_timer); // This will start the timer... whoops! //nrf_drv_timer_enable(&discharge_timer); // Other line not used. set to input nrf_gpio_cfg_input(other_line, NRF_GPIO_PIN_NOPULL); // Charge the capacitor via line nrf_drv_gpiote_out_set(line); nrf_delay_ms(600); // Initialize and enable the out task (high to low) nrf_drv_gpiote_out_task_enable(line); // Initialize and enable then sense line (high to low) sense_cfg.pull = NRF_GPIO_PIN_NOPULL; nrf_drv_gpiote_in_init(TEMP_SENSE_LINE, &sense_cfg, sense_dummy_handler); nrf_drv_gpiote_in_event_enable(TEMP_SENSE_LINE, true); // Start the PPI tasks nrf_drv_timer_increment(&start_counter); nrf_delay_ms(600); // PROBLEM! -> // Register only valid if we capture from Event IN callback! line_discharge_time = discharge_timer.p_reg->CC[0]; uint32_t count = nrf_drv_timer_capture(&start_counter, NRF_TIMER_CC_CHANNEL0); // TODO: Cleanup return line_discharge_time; } uint32_t system_thermistor_resistance_ppi() { uint32_t compare_line = do_thermistor_ppi(TEMP_COMP_LINE); //uint32_t thermistor_line = do_thermistor_ppi(TEMP_THERM_LINE); return 0; }
Using nRF5_SDK_12.2.0_f012efa with s132_nrf52_3.0.0_softdevice
Any ideas?
Thanks in advance,