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

SAADC consistnetly reads low, regardless of source

The SAADC on the nRF52832 consistently reads 20-30mV low, regardless of the source (AIN channel or VCC), Tacq, Resolution, or gain. All of the measurements are using the internal 0.6v reference. The readings are low even after calibrating the ADC. This happens across multiple devices.

I am bare-metal programming. Here's an example program:

int main(void)
{
  SEGGER_RTT_Init();

  NRF_SAADC->ENABLE = 1;

  NRF_SAADC->EVENTS_STOPPED = 0;
  NRF_SAADC->TASKS_STOP = 1;
  while (NRF_SAADC->EVENTS_STOPPED != 1) {}

  NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
  NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
  while (NRF_SAADC->EVENTS_CALIBRATEDONE != 1) {}

  NRF_SAADC->EVENTS_STOPPED = 0;
  NRF_SAADC->TASKS_STOP = 1;
  while (NRF_SAADC->EVENTS_STOPPED != 1) {}

  SEGGER_RTT_printf(0, "Calibrate done\n");

  NRF_SAADC->CH[0].PSELP = SAADC_CH_PSELP_PSELP_VDD << SAADC_CH_PSELP_PSELP_Pos;
  NRF_SAADC->CH[0].PSELN = SAADC_CH_PSELN_PSELN_NC << SAADC_CH_PSELN_PSELN_Pos;

  float internalReference = 0.6f;
  float gain = 1.0f / 6.0f;
  uint32_t resolutionDigits = 14;
  NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;
  NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Over256x << SAADC_OVERSAMPLE_OVERSAMPLE_Pos;
  NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;

  uint16_t sample = 0;
  NRF_SAADC->RESULT.PTR = uint32_t(&sample); //sample is a uint16_t
  NRF_SAADC->RESULT.MAXCNT = 1;

  NRF_SAADC->CH[0].CONFIG =
    (SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) |
    (SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) |
    (SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) |
    (SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
    (SAADC_CH_CONFIG_TACQ_3us << SAADC_CH_CONFIG_TACQ_Pos) |
    (SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) |
    (SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos);

  SEGGER_RTT_printf(0, "SAADC configuration complete\n");

  while (true)
  {
    NRF_SAADC->EVENTS_STARTED = 0;
    NRF_SAADC->TASKS_START = 1;
    while (NRF_SAADC->EVENTS_STARTED != 1) {}

    NRF_SAADC->EVENTS_RESULTDONE = 0;
    NRF_SAADC->TASKS_SAMPLE = 1;
    while (NRF_SAADC->EVENTS_RESULTDONE != 1) {}

    float vcc = sample * (internalReference / (1 << resolutionDigits) / gain);
    SEGGER_RTT_printf(0, "VCC: %d mV\n", (uint32_t)(vcc * 1000));

    NRF_SAADC->EVENTS_STOPPED = 0;
    NRF_SAADC->TASKS_STOP = 1;
    while (NRF_SAADC->EVENTS_STOPPED != 1) {}
  }
}

There doesn't appear to be any difference in the ADC results between uncalibrated and calibrated. Do I have the calibration sequence set correctly? I followed the workaround in this errata: infocenter.nordicsemi.com/.../anomaly_832_86.html

On the PCA10040 dev kit, this above code is showing VCC of 2.814V. My Tektronix DMM-4050 and Fluke 115 multimeters are showing VCC at 2.825V across C8 (decoupling cap close to the nRF52832).

Parents Reply Children
No Data
Related