This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SAADC Sampling Frequency to 10 ms

Hi, I am fairly new to the NRF and was wondering if there was a way to increase the sampling rate to 100Hz.  I have used the ble_app_uart example to configure this code:

This is the Header File 

#ifndef _BLUETOOTH_H
#define _BLUETOOTH_H

#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "ble_hci.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "app_timer.h"
#include "ble_nus.h"
#include "app_uart.h"
#include "app_util_platform.h"
#include "bsp_btn_ble.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "nrf_log.h"

#if defined (UART_PRESENT)
#include "nrf_uart.h"
#endif
#if defined (UARTE_PRESENT)
#include "nrf_uarte.h"
#endif

#include "gpio_control.h"
#include "temperature.h"

/* Define */
#define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */

#define DEVICE_NAME                     "nRF_Peripheral"                           /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

#define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */

#define APP_ADV_INTERVAL                64                                          /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */

#define APP_ADV_DURATION                18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(7.5, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(25, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY                   0                                           /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(250, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */


#define UART_TX_BUF_SIZE                256                                         /**< UART TX buffer size. */
#define UART_RX_BUF_SIZE                256                                         /**< UART RX buffer size. */

#define SAADC_SAMPLES_IN_BUFFER         4
#define SAADC_SAMPLE_RATE               1                                      /**< SAADC sample rate in ms. */               

BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */


void uart_init(void);
void buttons_leds_init(bool * p_erase_bonds);
void ble_stack_init(void);
void gap_params_init(void);
void gatt_init(void);
void services_init(void);
void conn_params_init(void);
void saadc_sampling_event_init(void);
void saadc_sampling_event_enable(void);
void advertising_start(void);
void saadc_init(void);
void advertising_init(void);


#endif

This is the C file:

In this code, I am trying to sample the 4 channels at 100Hz, but when I do, I get the NRF_RESOURCES error. 

In the ble_gatts.h I have also changed the BLE_GATTS_HVN_TX_QUE_SIZE_DEFAULT to 8 along with 

#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 6
#endif

// <o> NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size.
#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247
#endif

It seems that I am getting the error from the buffer overflow, but I am lost as to how to address this problem. Any pointers or help would be greatly appreciated. 

Thankyou!

Parents
  • Hello,

    It seems like you are describing two different issues here which we should deal with separately.

    Issue 1 regards the sampling rate of the SAADC. Are you unable to achieve the 10 ms sampling period for the SAADC? What sampling rate do you get with your current configuration?

    Issue 2 regards the possibility of having all the samples sent over the BLE connection, and the generation of the NRF_ERROR_RESOURCES error. This error is generated whenever you attempt to queue more notifications than there is buffer allocated (configured with BLE_GATTS_HVN_TX_QUE_SIZE_DEFAULT). So in order to resolve this we will need to balance how many notifications that are sent each connection event, how often the connection events occur, and how long the connection events are. Could you start by increasing your NRF_SDH_BLE_GAP_EVENT_LENGTH to 20, and which value you are seeing in the count variable of the BLE_GATTS_EVT_HVN_TX_COMPLETE event? Please also include what connection interval was used in the test.

    Furthermore, I see from your included code that you are trying to use the BLE_GATTS_EVT_HVN_TX_COMPLETE event in the SAADC callback - unless you have registered the SAADC callback as an observer to BLE events deliberately you will not receive this event in the SAADC callback.
    Instead, you will receive it in your ble_evt_handler or similar.

    Looking forward to resolving these issues together!

    Best regards,
    Karl

  • Issue 1 regards the sampling rate of the SAADC. Are you unable to achieve the 10 ms sampling period for the SAADC? What sampling rate do you get with your current configuration?

    Hi, currently I am able to get a stable connection with a rate of 25 Hertz with a SAADC_SAMPLE_RATE of 40ms 

    Could you start by increasing your NRF_SDH_BLE_GAP_EVENT_LENGTH to 20, and which value you are seeing in the count variable of the BLE_GATTS_EVT_HVN_TX_COMPLETE event? Please also include what connection interval was used in the test.

    #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(7.5, UNIT_1_25_MS)             /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL               MSEC_TO_UNITS(25, UNIT_1_25_MS)             /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY                   0                                           /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(250, UNIT_10_MS)             /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT    3                                      
    Yes my min max conn interval is shown here. Im really sorry but how would I get the count value for BLE_GATTS_EVT_HVN_TX_COMPLETE? 

    Furthermore, I see from your included code that you are trying to use the BLE_GATTS_EVT_HVN_TX_COMPLETE event in the SAADC callback - unless you have registered the SAADC callback as an observer to BLE events deliberately you will not receive this event in the SAADC callback.
    Instead, you will receive it in your ble_evt_handler or similar.

    Oh, I understand now. Thankyou!

    Oh thankyou so much for your help. I changed the  NRF_SDH_BLE_GAP_EVENT_LENGTH to 20. Things brings up another issue; is there a way to check the notification rate in respect to the increase in sampling frequency? To my knowledge I might need to use a sniffer. 

    Again thankyou so much for you help!

  • Oh ok thankyou so much again for your help!. I apologize to ask this again though; If i were to change the NRF_SDH_BLE_GAP_EVENT_LENGTH again would I be able to acheive 200 Hz with a sample rate of 5 ms? 

  • PinkSquirrel said:
    Oh ok thankyou so much again for your help!. I apologize to ask this again though;

    No need to apologize - I am happy to help!

    PinkSquirrel said:
    If i were to change the NRF_SDH_BLE_GAP_EVENT_LENGTH again would I be able to acheive 200 Hz with a sample rate of 5 ms? 

    It is likely not enough to change NRF_SDH_BLE_GAP_EVENT_LENGTH to resolve the NRF_ERROR_RESOURCES error, but when this is resolved it should be no problem at all to achieve 200 Hz sampling frequency. The maximum sampling frequency of the SAADC is 200 kHz (only SAADC, not accounting for BLE transmission of the results).
    So I suggest that we first resolve the NRF_ERROR_RESOURCES like discussed in the previous comment, and then move on to increasing the sample rate of the SAADC.

    Best regards,
    Karl

  • It is likely not enough to change NRF_SDH_BLE_GAP_EVENT_LENGTH to resolve the NRF_ERROR_RESOURCES error, but when this is resolved it should be no problem at all to achieve 200 Hz sampling frequency. The maximum sampling frequency of the SAADC is 200 kHz (only SAADC, not accounting for BLE transmission of the results).
    So I suggest that we first resolve the NRF_ERROR_RESOURCES like discussed in the previous comment, and then move on to increasing the sample rate of the SAADC.

    Ah I appreciate it! I changed the NRF_SDH_BLE_GAP_EVENT_LENGTH to 20 for 100Hz and it works fine now. Kinda kicking myself for not knowing such a simple fix of the SDK :/ .... but thankyou so much for the assistance. After 100Hz sampling rate was successful, I changed the Sample Rate to 5ms and it returned the same NRF_ERROR_RESOURCES(Error 19). Would I need to change the min and max conn interval to achieve 200Hz? 

    Thankyou!

  • PinkSquirrel said:
    I changed the NRF_SDH_BLE_GAP_EVENT_LENGTH to 20 for 100Hz and it works fine now. Kinda kicking myself for not knowing such a simple fix of the SDK :/ .... but thankyou so much for the assistance.

    I am glad to hear that you were able to achieve 100 Hz samplings and transfer with an increased connection event length! No worries - it is not always straight forward to know which parameters to tweak in order to achieve the desired functionality.

    PinkSquirrel said:
    After 100Hz sampling rate was successful, I changed the Sample Rate to 5ms and it returned the same NRF_ERROR_RESOURCES(Error 19). Would I need to change the min and max conn interval to achieve 200Hz? 

    Yes, this is then just a question of balancing connection event length, connection interval, and notification frequency again., and making sure that the hvx queue is big enough to store the notification queue in between connection events.

    You could either do this analytically by calculating the required throughput of sampling with 200 Hz, and then balancing the connection event length and interval by calculating what they need to be in order to achieve this throughput. If you are taking this approach it might also be helpful to have a look at the throughput documentation for the SoftDevice, since it lists the combination of parameters that achieve the highest throughput (note: no regards to power consumption).
    Alternatively, you can take the slightly more manual approach - calculate the number of notifications that will be queued in each connection interval (you can use the Online Power Profiler to visualize how many notifications you can fit into each connection interval and how long the connection event length therefore needs to be).

    Lastly, you should check that the desired number of notifications are actually being sent each connection event, either through using the sniffer or counting the count variable from the BLE_GATTS_HVN_TX_COMPLETE event. You should verify this to ensure that there is not a slow buildup of queued notifications which over time might lead to an NRF_ERROR_RESOURCES.

    Best regards,
    Karl

  • Alternatively, you can take the slightly more manual approach - calculate the number of notifications that will be queued in each connection interval (you can use the Online Power Profiler to visualize how many notifications you can fit into each connection interval and how long the connection event length therefore needs to be).

    Hi, Thankyou again!

    I have looked into this, and to be honest I am very new to this area so I am having trouble with configuring the settings. To my knowledge I believe the minimum value for min_conn_interval is 7.5 ms, but I am still confused as how I would configure this value to match the requirement to obtain 200Hz. I apologize for the hassle! 

Reply Children
  • PinkSquirrel said:
    I have looked into this, and to be honest I am very new to this area so I am having trouble with configuring the settings.

    It is no problem at all - we were all new to this at some point! This is also good for me to be aware of, so I may try to elaborate further in my answers. Please do not hesitate to ask whenever something should be unclear.

    PinkSquirrel said:
    To my knowledge I believe the minimum value for min_conn_interval is 7.5 ms, but I am still confused as how I would configure this value to match the requirement to obtain 200Hz. I apologize for the hassle! 

    No need to apologize! You are correct that the minimum connection interval for a BLE connection is 7.5 ms.
    Look at it this way, a shorter connection interval will give you a lower latency of the received packets, but it will also give you a smaller window in which to transfer larger packets. With larger packets, you will reduce the number of overhead bytes being sent (since each BLE packet contains overhead), and thus you can achieve a significantly higher throughput if you group data together into longer packets, in a longer connection interval - like shown in Table 2 of the SoftDevice throughput documentation
    So, say for example that you intend to sample 16 bytes worth of SAADC measurements each sampling. Sampling at 200 Hz will produce a notification every 5 ms. Assuming a connection interval of 10 ms we will need to transfer at least 32 bytes each connection event, and we should make sure that our HVN queue at minimum is 2 notifications big, I would at least double this to account for the case where a connection event or two is lost due to noise or poor signal strength. Lets say we set the hvn queue to 6 in this case. Using the Online Power Profiler we can visualize how this exchange will look, and the effects of using Data Length Extension, for example. Without DLE we see that the estimate should be roughly 700 µs for each packet exchange. We know that we will need to send at least 2 packets per connection event (we might have to retransmit some previous packets), and so we could set the connection event length to at least 2.1 ms.

    Next, we make sure that these parameters are configured on both sides of the link (central and peripheral), and then give them a try while we have the sniffer set up to listen in on the connection, to see whether everything is transpiring as expected.

    Give this a try, and let me know what you observe! If anything does not go as expected, please provide the sniffer trace so we may take a look together and see where it went wrong.

    Best regards,
    Karl

  • Thankyou so much this answers everything! I apologize again for the late reply, but I just really want to thankyou for your patience and effort in explaining all of this to me! Seriously, thankyou so much!

  • Thank you for saying that - I am glad to hear that you found my comments helpful! :)

    PinkSquirrel said:
    I apologize again for the late reply,

    No need to apologize at all, we're happy to help you!

    Please do not hesitate to open another ticket if you should encounter any issues or questions in the future.

    Good luck with your development!

    Best regards,
    Karl

Related