Hi everyone,
I have written a code that sends data over BLE notifications (IMU data). It works great so far and now I want to read the analog values from eight force sensors and send them also as well.
Using the SAADC,PPI AND TIMER drivers I wrote a code that works great. I am using an eight-channel multiplexer in order to read the 8 analog sensors
Due to the fact that I am trying to design a low power application I want to use the app_timer (RTC) rather than the TIMER driver. I am trying to combine my BLE and SAADC codes but I fail.
In the BLE code, I have created an app_timer that starts as soon as notification is enabled. When the timer expires the notification_timeout_handler function is called
static void timers_init(void) { // Initialize timer module. ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(err_code); // Create timers. err_code = app_timer_create(&m_notification_timer_id, APP_TIMER_MODE_REPEATED, notification_timeout_handler); APP_ERROR_CHECK(err_code); } // This is the handler function static void on_cus_evt(ble_cus_t *p_cus_service, ble_cus_evt_t *p_evt) { ret_code_t err_code; switch (p_evt->evt_type) { case BLE_CUS_EVT_NOTIFICATION_ENABLED: err_code = app_timer_start(m_notification_timer_id, NOTIFICATION_INTERVAL, NULL); APP_ERROR_CHECK(err_code); break; case BLE_CUS_EVT_NOTIFICATION_DISABLED: err_code = app_timer_stop(m_notification_timer_id); APP_ERROR_CHECK(err_code); break; }
Inside the notification_timeout_handler function, I read the data from the IMU and I update the payload that will be sent through BLE notification.
static void notification_timeout_handler(void *p_context) { UNUSED_PARAMETER(p_context); ret_code_t err_code; m_xfer_done = false; bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL | BMI160_TIME_SEL), &accel, &gyro, &sensor); bmi160_read_aux_data_auto_mode(mag_data, &sensor); bmm150_aux_mag_data(mag_data, &bmm150); NRF_LOG_INFO("AccelX:%d , AccelY:%d , AccelZ:%d", accel.x, accel.y, accel.z); NRF_LOG_INFO("GyroX:%d , GyroY:%d , GyroZ:%d", gyro.x, gyro.y, gyro.z); NRF_LOG_INFO("MagX:%d , MagY:%d , MagZ:%d", bmm150.data.x, bmm150.data.y, bmm150.data.z); // Passing an array of data through notification to the central int16_t m_array[] = {accel.x, accel.y, accel.z, gyro.x, gyro.y, gyro.z, bmm150.data.x, bmm150.data.y, bmm150.data.z}; // you can set either decimal or hex values until 20bytes!! err_code = ble_cus_custom_value_update(&m_cus, m_array); APP_ERROR_CHECK(err_code); }
Until this point, everything works fine.
Now inside the notification_timeout_handler() function I want to read also the analog sensors...
I tried to call the nrf_drv_saadc_sample() inside a for loop in order to read the 8 sensors but it fails :
static void notification_timeout_handler(void *p_context) { UNUSED_PARAMETER(p_context); ret_code_t err_code; // na - read flexi forces for (int i = 0; i < NO_SENSORS; i++) { nrf_drv_saadc_sample(); // na - trigger sampling NRF_LOG_INFO("i = %d", i); } ..........rest of code...... }
This is the callback function as well the function to switch the channels of the multiplexer:
void saadc_callback(nrf_drv_saadc_evt_t const *p_event) { if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { // na - when the buffer is filled then the NRF_DRV_SAADC_EVT_DONE is generated ret_code_t err_code; err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); ADC_RawData[callback_counter] = p_event->data.done.p_buffer[0]; // na - Store the ADC values from flexi force NRF_LOG_INFO("ADC_Sensor%d: %d ", callback_counter + 1, ADC_RawData[callback_counter]); NRF_LOG_INFO("Callback_counter %d ", callback_counter); if (callback_counter == NO_SENSORS - 1) { memset(ADC_RawData, 0, sizeof(ADC_RawData)); // na - Initialize ADC_RawData to 0 callback_counter = 0; } else { callback_counter++; } selectMuxPin(callback_counter); // na - change MUX channel to read the next sensor } } // Function to switch multiplexer's channel void selectMuxPin(int channel) { for (int i = 0; i < MUX_CTRL_CHA; i++) { if (channel & (1 << i)) { nrf_gpio_pin_set(ctrlPins[i]); } else { nrf_gpio_pin_clear(ctrlPins[i]); } } }
My problem is that the nrf_drv_saadc_sample() function inside the for loop does not work. I was expecting to call nrf_drv_saadc_sample() function eight times, store the data in ADC_RawData[] array, and then send the data over BLE. But when I run the code and while the loop iterates the nrf_drv_saadc_sample() is being called only once...
Any advice of how could I solve this issue?
p.s SAMPLES_IN_BUFFER is 1
Thanks in advance
Nick