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

  • Any difference if you simply ground the input? If not, then I think you may have configured the ADC channel wrong (e.g. it is sampling the wrong input pin).

    Kenneth

  • Hi Kenneth

    I went down a similar thought pattern:
    I disabled my input signal entirely (it has a switchable supply, that i can control from the CPU). I then used the ADC config to connect resistor_p, the single-ended input to a PULLDOWN resistor.

    This gave ADC readings of around -40...which i found odd, either way it was a marked difference from the middle-of-the-range values.

    I then attached the internal PULLUP to the input, this gave readings around 16380 I.E., max value.

    With the regards to the pin, I've checked this too. Regardless, the pin must be right, as under the a few variations of my test, i'm seeing ROUGHLY the right readings coming through, i mentioned the input signal is an ECG signal, i can clearly pickout a cardiovascular signal in the readings (i have some basic SW that lets me graph the signals). But these tests are so inconsistent in terms of results VS adc config, all they really clarify is that the correct pin is connected.

  • I am starting to think it must be the ADC config as you suggest, i've now managed to un-couple the input signal, so it's now a sinusoid centered around 1V, with 0.5V pk-pk ish. No more negative voltages.

    PS, apologies for mis-spelling your name in my first reply.

  • SeanHowsonTB said:
    so it's now a sinusoid centered around 1V, with 0.5V pk-pk ish. No more negative voltages.

    For an unconnected pin? Is it possible you are picking up some noise from the power grid or USB? What is the frequency?

    Kenneth

Reply Children
  • This this is a mis-communication here.

    The only time the pin has been unconnected was while i was trialing the effects of the internal pullup's & pull downs.

    I've removed the AC coupling, from the board & replaced it with a 0603 sized peice of copper, IE the filter no longer exists. The output of the ECG circuit now runs through a single mains-noise filter as it always had & straight into the SAADC pin.

    There are no usb related components on the board.

    This 1V offset, 0.5V pk-pk is my desired signal, this is the ECG signal i'm trying to measure. The difference is that it is no longer centered around 0V, instread it has a positive offset voltage to keep it within the input range of the SAADC.

  • SeanHowsonTB said:
    This 1V offset, 0.5V pk-pk is my desired signal, this is the ECG signal i'm trying to measure. The difference is that it is no longer centered around 0V, instread it has a positive offset voltage to keep it within the input range of the SAADC.

    Ah, thanks for clarifying.

    Kenneth

  • 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

Related