SAADC results unclear.

Using the NRF5 SDK V17.0.2

Once again finding myself struggling to understand the structure of the SDK as a result of lacking documentation, there seem to be so many layers of abstraction used accross the example code. functions using nrf/nrfx/nrf_drv prefixes & endless redirect header files. I'm trying to review one of the SAADC example projects. There are less than 10 annotations accross the main.c file & it's not made clear why functions are called at given times.

In my own code, I am inputting to a single ended channel of the SAADC peripheral, a sinusoid that is centred about -30mv (or sometimes 0V). The signal has been AC coupled, but in future this coupling will be removed. For now i must try to conduct some testing regardless, the negative voltage doesn't go anywhere near the -0.3V absolute maximum & features plenty of positive components.

I am using a single ended ADC channel, with a gain of 1 & resolution of 14 bits. Reference voltage 0.6V internal. The SAADC samples are coming out around 8000 (~0.3V).

When i try adjusting the resolution to 12 bits, i get samples around 2000 (again, ~0.3V).

Why is it my samples are centered around the 0.3V region. When i know they are in fact centred around 0V...

It's worth noting that the waveforms i'm seeing, while centred around the wrong value, are roughly correct & in keeping with what i would expect).

I have also noticed that if i invert my signal (signal is an ECG type signal, that i can invert by swapping chest electrodes), the ADC results, do NOT invert to match.

Am i converting the sample values to voltages correctly? (I'm following the standard equations shown on the infocentre).

Parents
  • Hi,

    The nrf saadc driver should be tightly coupled with the saadc hardware description, so I suggest to read it if you haven't already
    https://infocenter.nordicsemi.com/topic/ps_nrf52840/saadc.html

    The analog input must be in the range VSS - VDD, ref for instance:
    "Inputs AIN0 through AIN7 cannot exceed VDD or be lower than VSS."

    The -0.3V you refer to is related to when the part can take damage if you go below this.

    If you are using single ended input then make sure you have a common ground, and ensure the analog signal input is within the VSS - VDD range. If you have simply connected a series capacitor on the input it likely will be measuring a value in the middle of the range.

    Best regards,
    Kenneth

  • Hi Kennith,

    Thanks for answering, i've read the above documentation a number of times, the top half is informative, but the lower half of the document refers to what i presume is classes as register level programming. While i've normally no issue programming at register level, i'd prefer to maintain a consistent level of abstraction throughout the project & continue using the SDK functions. Which is where the disconnect in documentation seems to sit. All the examples follow bits of the SDK & offer little explanation as to why such funtions are run.

    I was aware of the input ranges being an issue (thanks anyhow), & that the -0.3V is an absolute maximum characteristic, i was hoping someone might have some insight into the likely behaviour of the chip when it is exposed to conditions outside of the specified input range? So i could have some explanation as to it's behaviour. As i mentioned before, these are not ideal conditions, i'm working on a bespoke board that i cant modify at the moment & subsequently dont have much of a choice about the negative voltages.That said, I am currently attempting to remove the coupling.

    I do have a common ground present & no ive not just connected a series capactitor, the AC coupling is technically a 0.3Hz high pass filter, as the circuit required a current path to GND to be preset, hence the use of an RC filter.

    I'm curious, (even though this is not the case) what makes you say it would likely meave a middle of the range value?

    -S

  • Keep in mind the SAADC only measures positive voltages above GND. ECG signals of (say) 1mV really require a differential input otherwise most of the resolution is lost handling the DC offset even when AC coupled. This can be handled by using a true differential input, which requires two pins. Both input pins have both bias pull-up and bias pull-down enabled, ie 160k pull-up and 160k pull-down, which biases the signal to mid-rail (VDD/2) on both SAADC input pins. Leaving both pins disconnected now allows high gain measurement of random noise. AC couple the positive signal to the 1mV ECG waveform (which may sit at any DC level) now allows high amplification of the small ECG signal. Reversing the ECG leads (not the SAADC inputs) will invert the ECG waveform as one would expect.

    Optionally the normally-unconnected -ve input pin can be connected via an identical CR network to the ECG signal -ve output (quite possibly the ECG GND). Doing so balances both input impedance and noise pickup, which in SAADC differential mode will cancel out.

    // Differential SAADC Mode
    //                                                     |    VDD
    //                                                     |   --#--
    //                                                     |     |
    //                                                     |     +-|   (160k)
    //                                                     |       |<- CFG.RESP
    //   ECG Sensor                                        |     +-|
    //   +--------+                                        |     |
    //   |        |     ECG Signal         | |             |     |
    //   |        0------------------------| |-------------O-----#-----------------#--> P0.nn ADC +ve input
    //   |        |                        | |             |     |                 |          Ref = 0.6
    //   |        0--+  ECG Gnd                            |     +-|  (160k)       |
    //   |        |  |  negative reference                 |       |<-CFG.RESN   -----
    //   +--------+  |  optional                           |     +-|             -----
    //               |                                     |     |                 |
    //               |                                     |     |                 |
    //               |                                     |   =====             =====
    //               |                                     |    ===               ===
    //               |                                     |     =                 =
    //               |                                     |
    //               |                                     |
    //               |                                     |    VDD
    //               |                                     |   --#--
    //               |                                     |     |
    //        +====  | =============================+      |     +-|  (160k)
    //        !      |                              !      |       |<-CFG.RESP
    //        !      |                              !      |     +-|
    //        !      |                              !      |     |
    //        !      |                  | |         !      |     |
    //        !      +------------------| |----------------O-----#-----------------#--> P0.nn ADC -ve input
    //        !                         | |         !      |     |                 |          Ref = 0.6
    //        !                                     !      |     +-|  (160k)       |
    //        ! Optional, can leave pin unconnected !      |       |<-CFG.RESN   -----
    //        +=====================================+      |     +-|             -----
    //                                                     |     |                 |
    //                                                     |     |                 |
    //                                                     |   =====             =====
    //                                                     |    ===               ===
    //                                                     |     =                 =
    //                                                     | nRF52832
    //                                                     +----------------------------------

  • Kenneth,

    Problem solved. So the signal described above. Seeingly just wan't having any affect on the input pin. (tapping & touching the ECG electrodes had no effect, normally this should induce huge spike).

    As mentioned, in the past i was pretty confident that the pin i had defined was not the issue. As i'd definitely seen ECG on the screen, & been able to influence the ADC readings by tapping the input to the sensor circuit etc.

    However, prompted by your earlier post, i swapped the definition for the EEG pin from  NRF_GPIO_PIN_MAP(0,04)

    to

    NRF_SAADC_INPUT_AIN2

    ...Which to my understanding would map to the same pin.... apparently not. it now works.

    Thanks for the prompt in the right direction.

  • Hiya,

    Thanks for the answer & appreciate the insight. The ECG signal i mentioned had already been engineered to be suitable for use with the single ended input, amplified to a magnitude where resolution isn't lost, run through an INA to improve CMRR etc etc. I've now somehow managed to remove from the ac coupling from the circuit (after a great deal of agro & inappropriate tools for the job). Even if it is possible to use an AC coupled signal as you suggest above, it helped to just eliminate some variables & see a little clearer...i also didn't see your post in time before i began pulling components!.

    Subsequently, without this (0.3Hz high pass) filter the signal is not centered around the midrail anyway, so, currently no need for the internal biasing, however, i do have 5 more boards which i would prefer not to modify, so i'll certainly give your approach a shot. Thanks for this!

    The primary problem with the system was actually the PIN id defined for the ADC, irritatingingly simple, still not quite sure what the difference was with the two definitions i used in FW. Hence i've marked that as the answer for the thread, but i still really appreciate the input!

    -Sean

  • still not quite sure what the difference was with the two definitions i used

    If you follow the trail of macros for definition of NRF_SAADC_INPUT_AIN2, you'll eventually reach the bit description:

    /* Bits 4..0 : Analog positive input channel */
    #define SAADC_CH_PSELP_PSELP_Pos (0UL) /*!< Position of PSELP field. */
    #define SAADC_CH_PSELP_PSELP_Msk (0x1FUL << SAADC_CH_PSELP_PSELP_Pos) /*!< Bit mask of PSELP field. */
    #define SAADC_CH_PSELP_PSELP_NC (0UL) /*!< Not connected */
    #define SAADC_CH_PSELP_PSELP_AnalogInput0 (1UL) /*!< AIN0 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput1 (2UL) /*!< AIN1 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput2 (3UL) /*!< AIN2 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput3 (4UL) /*!< AIN3 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput4 (5UL) /*!< AIN4 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput5 (6UL) /*!< AIN5 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput6 (7UL) /*!< AIN6 */
    #define SAADC_CH_PSELP_PSELP_AnalogInput7 (8UL) /*!< AIN7 */
    #define SAADC_CH_PSELP_PSELP_VDD (9UL) /*!< VDD */
    #define SAADC_CH_PSELP_PSELP_VDDHDIV5 (0x0DUL) /*!< VDDH/5 */
    
    So they are not equal to the gpio pin number.

  • Trouble with ECG is the potentially very wide dynamic range caused by outside influences (skin, patch, silver-silver chloride, motion, sweat, etc) which have to be handled by Right Leg Drive or other compensation; offset feedback and/or AC coupling can help with that which allows a trade off between very wide dynamic range and per-bit resolution. Perhaps there is already some form of coupling around the LNA. ECG ADCs typically have 18-, 19- or 24-bit resolution to help handle this; the 12- or 14-bits on the SAADC requires some external processing. The Maxim chipset would be better than the TI chipset for this reason (and cost), as you probably know already.

Reply
  • Trouble with ECG is the potentially very wide dynamic range caused by outside influences (skin, patch, silver-silver chloride, motion, sweat, etc) which have to be handled by Right Leg Drive or other compensation; offset feedback and/or AC coupling can help with that which allows a trade off between very wide dynamic range and per-bit resolution. Perhaps there is already some form of coupling around the LNA. ECG ADCs typically have 18-, 19- or 24-bit resolution to help handle this; the 12- or 14-bits on the SAADC requires some external processing. The Maxim chipset would be better than the TI chipset for this reason (and cost), as you probably know already.

Children
No Data
Related