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

Using ADC/SAADC to read data in BLE app

I am currently development an app based on the example from the experimental folder using a NRF DK52 as a relay between a central and multiple peripherals.

The app should now react on the press of a button from an external device. The device is built like that - for whatever reason the unpressed button is at voltage 2.7V whereas when pressed falls down to 1.2V. The way the device works is out of my control. Because of the high lower value I was told I cannot use a digital input as the maximum 0 value would be recognized at 0.8V.

Therefore I now think about using ADC/SAADC to read the voltage continously and act when the read values are in the range that indicate the button was pressed. 

I was looking at the peripheral/saadc example and it worked quite well so far. But then I read that it is not recommended to perform SAADC measurements while BLE RF is happening at the same time. Also SAADC measurements seem to be delayed or in general slower when BLE is active?

What is your recommendation to perform that task? Should I use plain ADC or SAADC? I believe in order to recognize the button press accurately my sampling interval should not be much slower than every 100ms? Whats the best practice here? 

Parents
  • Hello,

    Thank you for your patience.

    I was looking at the peripheral/saadc example and it worked quite well so far. But then I read that it is not recommended to perform SAADC measurements while BLE RF is happening at the same time. Also SAADC measurements seem to be delayed or in general slower when BLE is active?

    This depends on how you are initiating the sampling.
    If you are using the CPU to call the _sample function, then you will miss out on all samples that should have happened in the time the CPU is busy with higher-priority tasks - such as BLE communication. This is a very unreliable way to perform sampling, if you need them to be periodic and predictable.
    Instead, you may then connect the TASKS_START or TASKS_SAMPLE of the SAADC to a timer event that triggers periodically - like demonstrated in the SAADC peripheral example that you referenced. This is the recommended way to trigger sampling, since it does not requires CPU intervention each sample, and thus can continue even though the CPU is unavailable.

    Regardless of how you initiate sampling the event handling will not happen until the CPU is available again. So, in the case that you have a lot of higher-priority events happening, or a lot of BLE communication is going on, you may see that your SAADC event handling is delayed. To alleviate this you can increase the priority of the SAADC to the appropriate level for your application.

    What is your recommendation to perform that task? Should I use plain ADC or SAADC? I believe in order to recognize the button press accurately my sampling interval should not be much slower than every 100ms? Whats the best practice here? 

    The task you describe sounds like a use-case for the LIMIT events of the SAADC.
    This way, a LIMIT event will be generated when a set threshold is exceeded, which you then may use to handle the button-press.
    Could using the limits events be a possibility for you?

    Best practice for button-press duration is hard to say exactly, it depends on what kind of button it is being pressed, and the use-case of the button, but I would say that it is typically in the 50-300 ms range.

    Please do not hesitate to ask if any part of my reply is unclear, or if you have any other questions.

    Best regards,
    Karl

Reply
  • Hello,

    Thank you for your patience.

    I was looking at the peripheral/saadc example and it worked quite well so far. But then I read that it is not recommended to perform SAADC measurements while BLE RF is happening at the same time. Also SAADC measurements seem to be delayed or in general slower when BLE is active?

    This depends on how you are initiating the sampling.
    If you are using the CPU to call the _sample function, then you will miss out on all samples that should have happened in the time the CPU is busy with higher-priority tasks - such as BLE communication. This is a very unreliable way to perform sampling, if you need them to be periodic and predictable.
    Instead, you may then connect the TASKS_START or TASKS_SAMPLE of the SAADC to a timer event that triggers periodically - like demonstrated in the SAADC peripheral example that you referenced. This is the recommended way to trigger sampling, since it does not requires CPU intervention each sample, and thus can continue even though the CPU is unavailable.

    Regardless of how you initiate sampling the event handling will not happen until the CPU is available again. So, in the case that you have a lot of higher-priority events happening, or a lot of BLE communication is going on, you may see that your SAADC event handling is delayed. To alleviate this you can increase the priority of the SAADC to the appropriate level for your application.

    What is your recommendation to perform that task? Should I use plain ADC or SAADC? I believe in order to recognize the button press accurately my sampling interval should not be much slower than every 100ms? Whats the best practice here? 

    The task you describe sounds like a use-case for the LIMIT events of the SAADC.
    This way, a LIMIT event will be generated when a set threshold is exceeded, which you then may use to handle the button-press.
    Could using the limits events be a possibility for you?

    Best practice for button-press duration is hard to say exactly, it depends on what kind of button it is being pressed, and the use-case of the button, but I would say that it is typically in the 50-300 ms range.

    Please do not hesitate to ask if any part of my reply is unclear, or if you have any other questions.

    Best regards,
    Karl

Children
  • Dear Karl, thanks for the explanation. I think I understand what you're saying (as said above I've little experience with the peripherals yet). The SAADC priority would be a setting in the sdk_config.h then? 

    I'll have a look at the LIMIT stuff. Indeed, as I am only interested in the crossing of my threshold I would not need to react/handle any other sampling value. There isn't an example for that in the SDK, right? Still struggling a little bit with the setup of the SAADC, e.g. the GAIN settings seem to deliver "830" at the maximum voltage of 3.3V I ran the DK with (at least I think I do? ;-) Powered via USB) instead of the expected 1023. I read in another thread that I need to adjust the gain level accordingly as it accounts for voltages up to 3.6V. 

  • daubsi said:
    Dear Karl, thanks for the explanation.

    No problem at all, I am happy to help!

    daubsi said:
    I think I understand what you're saying (as said above I've little experience with the peripherals yet).

    Great! Please do not hesitate to ask if you should encounter any issues or questions in your development! :) 

    daubsi said:
    The SAADC priority would be a setting in the sdk_config.h then? 

    If you do not explicitly configure the SAADC IRQ priority when you initialize it, it will instead use the default IRQ priority specified in the sdk_config, correct.

    daubsi said:
    I'll have a look at the LIMIT stuff. Indeed, as I am only interested in the crossing of my threshold I would not need to react/handle any other sampling value.

    Great!
    It is also an option to use the comparators directly, as suggested by Snoopy20. You may read more about the COMP peripheral here

    daubsi said:
    There isn't an example for that in the SDK, right?

    Unfortunately, there is no LIMIT event examples in the SDK, no. However, as long as you have enabled the LIMITs you will have the event passed to your SAADC event handler - same as with the DONE event in the SAADC peripheral example.
    So, if you are to use the SAADC for this, you could start out by modifying the SAADC example to generate LIMIT events.

    daubsi said:
    Still struggling a little bit with the setup of the SAADC, e.g. the GAIN settings seem to deliver "830" at the maximum voltage of 3.3V I ran the DK with (at least I think I do? ;-) Powered via USB) instead of the expected 1023.

    When the nRF52 DK is powered through USB the 5 V supply is regulated down to 3.3 V.
    The input range of the default SAADC is 0 - 3.6V as explained in these formulas from the SAADC Documentation.
    However, your measurements of 830 indicate 3 V.. Could you confirm for me that you are using an nRF52 DK ( nRF52832 SoC ), and if so, could you detail what you did exactly when measuring the 830 values? 

    daubsi said:
    I read in another thread that I need to adjust the gain level accordingly as it accounts for voltages up to 3.6V. 

    This is correct - you could see how to do so in the link I referenced above.

    Best regards,
    Karl

Related