Hey guys,
I'm working with SES, nRF52832 and SDK14.2.0.
I have a timing problem and would like to describe the problem from the beginning.
I have a 1-wire temperature sensor that is read by the slave and then the slave sends the sensor data to the master via BLE every second. (That is my goal.)
1) First I measured the "temperature conversion time" of the sensor with the project: peripheral / uart, which I modified with a timer for the interval transmission (of 1 second) and with a timer for measuring the time.
Timer for sending in intervals:
... /**< Driver instance for timer 1 */ const nrf_drv_timer_t TIMER_SEND_DATA = NRF_DRV_TIMER_INSTANCE(1); /** * @brief Handler for timer events. */ void timer_event_handler(nrf_timer_event_t event_type, void* p_context) { switch (event_type) { case NRF_TIMER_EVENT_COMPARE1: send_telegram(); //with temperature data break; default: //Do nothing. break; } } /** * @brief Init for timer events. */ static void timer_SendData_init() { uint32_t time_ms = 1000; /**< Time(in miliseconds) between consecutive compare events */ uint32_t time_ticks; uint32_t err_code = NRF_SUCCESS; nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; err_code = nrf_drv_timer_init(&TIMER_SEND_DATA, &timer_cfg, timer_event_handler); APP_ERROR_CHECK(err_code); time_ticks = nrf_drv_timer_ms_to_ticks(&TIMER_SEND_DATA, time_ms); nrf_drv_timer_extended_compare( &TIMER_SEND_DATA, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true); nrf_drv_timer_enable(&TIMER_SEND_DATA); }
Timer for measuring:
///////Function to measure time /**< Temperature request and read */ int OneWire_Read_Temperature(void) { uint32_t captured_value = 0; ..... /**< Start of the time measurement */ NRF_TIMER2->TASKS_CLEAR = 1; NRF_TIMER2->TASKS_START = 1; /**< DS18B20 store thermal data in the scratchpad (2-byte temp register) */ while (! OneWire_Read_Byte()); /**< Sensor respond by transmitting a 0 while temperatur conversion is in progress and a 1 when conversion is done * after storing the Sensor returns to its low power idle state */ /**< End of the time measurement */ NRF_TIMER2->TASKS_CAPTURE[1] = 1; captured_value = NRF_TIMER2->CC[1]; NRF_TIMER2->TASKS_STOP = 1; printf("Cycles: %u. ", captured_value); /**< Print captured value in cycles; 1 cycle = 1 us */ } /** * @brief Init the measurement. */ void Timer_Timing_init(void) { NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit; /**< Timer range: 0 to 4294 secondes */ NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos| TIMER_SHORTS_COMPARE2_STOP_Enabled << TIMER_SHORTS_COMPARE2_STOP_Pos; /**< Enable clear and stop timer */ NRF_TIMER2->PRESCALER = 4; /**< Prescaler = 4 -> f(TIMER) = 16MHz / (2^PRESCALER) = 1MHz -> t(TIMER) = 1us (1 cycle = 1us) */ }
And I get the measured time around 702 milliseconds (with small deviations in the microsecond range). And this value is ok.
When I measure all the code that is triggered by the timer (case NRF_TIMER_EVENT_COMPARE1), I get a measured value of approx. 720 milliseconds.
Everything fits up to here.
2) Now I would like to send the sensor data via BLE and have selected the following programs for the slave and the master:
Slave: ble_peripheral/ble_app_uart
Master: ble_central/ble_app_uart_c
I set the timer for sending after every second exactly as in the "peripheral / uart" project. I have installed the timer for measuring in "case NRF_NRF_TIMER_EVENT_COMPARE1":
/** * @brief Handler for timer events. */ void timer_event_handler(nrf_timer_event_t event_type, void* p_context) { int RetVal; uint32_t captured_value = 0; switch (event_type) { case NRF_TIMER_EVENT_COMPARE1: /**< Start of the runtime measurement */ NRF_TIMER2->TASKS_CLEAR = 1; NRF_TIMER2->TASKS_START = 1; RetVal = send_temperature(); /**< Function call to send the temperature value to the master */ if (RetVal != READ_TEMP_SUCCESSFUL) /**< When an error occurs: report it */ { printf("ERROR: %x \r\n", RetVal); } NRF_TIMER2->TASKS_CAPTURE[1] = 1; captured_value = NRF_TIMER2->CC[1]; NRF_TIMER2->TASKS_STOP = 1; printf("Cycles: %u. ", captured_value); /**< Print captured value in cycles; 1 cycle = 1 us */ break; default: //Do nothing. break; } }
But here I get totally random values like: 140.000 ticks, 69.000 ticks or 12.000 ticks, although the temperature conversion alone takes about 702.000 ticks (702 milliseconds). Is that because of the softdevice (ble)? If so, what can I change? I'm a bit baffled here...
For this reason, I configured the measurement timer in the master-program in "ble_nus_c_evt_handler":
/**@brief Callback handling NUS Client events. * * @details This function is called to notify the application of NUS client events. * * @param[in] p_ble_nus_c NUS Client Handle. This identifies the NUS client * @param[in] p_ble_nus_evt Pointer to the NUS Client event. */ /**@snippet [Handling events from the ble_nus_c module] */ static void ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt) { ret_code_t err_code; uint32_t captured_value = 0; switch (p_ble_nus_evt->evt_type) { .... case BLE_NUS_C_EVT_NUS_TX_EVT: /**< End of the runtime measurement */ NRF_TIMER2->TASKS_CAPTURE[1] = 1; captured_value = NRF_TIMER2->CC[1]; NRF_TIMER2->TASKS_STOP = 1; printf("Cycles: %u. ", captured_value); /**< Print captured value in cycles; 1 cycle = 1 us */ /**< Start of the runtime measurement */ NRF_TIMER2->TASKS_CLEAR = 1; NRF_TIMER2->TASKS_START = 1; ble_nus_chars_received_uart_print(p_ble_nus_evt->p_data, p_ble_nus_evt->data_len); break; .... } } /**@snippet [Handling events from the ble_nus_c module] */
Here I get values in 1 second intervals, but the values fluctuate very strongly (up to 200 ms) ... That means the master gets values in an interval between 0.8 and 1.2 seconds, but I need an accurate interval of 1 second... Does anyone know what I can do? I would be very happy about any help ..
Best regards,
Christoph