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? 

  • If you are using the ADC interrupt then you can't run it that fast or it''ll eat into processing time available for other matters. The best way is to use the ADC Window mode and fire an event only when it falls/rises above the threshold.

    Since you''re using the ADC chances are you have the AC comparator available? That is the most appropriate tool for the job.

    BTW you may get away with a diode, a 0.7v will bring you down to 0.5v. The problem then is 2v may not be registered 'high', but check the specification for GPIO to be sure.

  • 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

  • Thanks @snoopy20. What do you mean by "you have the AC comparator available"? Any chance you have a small sample code to illustrate your idea? I'm still learning the SDK and focused on the BLE stuff with yet little experience on the peripherals themselves. A diode might actually be helpful... good idea! I'll check it out!

  • 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. 

  • The NRF52832 has two comparators, the 810 has one. A comparator continuously 'samples' a voltage and triggers an event when it goes above or below a threshold level (which you can define). It should be your first choice. The ADC with the LIMIT feature is doing the same thing basically, just it's slower and uses more power (if you're bothered).

    No code here but it's easy to follow the direct documentation. I only use the SDK for BLE, all other peripherals I control direct as I find the SDK is bloated and an unnecessary abstraction. If I wanted that I'd use Arduino.

    infocenter.nordicsemi.com/index.jsp

    The comparator (COMP) compares an input voltage (VIN+) against a second input voltage (VIN-). VIN+ can be derived from an analog input pin (AIN0-AIN7). VIN- can be derived from multiple sources depending on the operation mode of the comparator.

    Main features of the comparator are:

    • Input range from 0 V to VDD
    • Single-ended mode
      • Fully flexible hysteresis using a 64-level reference ladder
    • Differential mode
      • Configurable 50 mV hysteresis
    • Reference inputs (VREF):
      • VDD
      • External reference from AIN0 to AIN7 (between 0 V and VDD)
      • Internal references 1.2 V, 1.8 V and 2.4 V
    • Three speed/power consumption modes: low-power, normal and high-speed
    • Single-pin capacitive sensor support
    • Event generation on output changes
      • UP event on VIN- > VIN+
      • DOWN event on VIN- < VIN+
      • CROSS event on VIN+ and VIN- crossing
      • READY event on core and internal reference (if used) ready
Related