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

Debugging SAADC with variable voltage input

I am finding that the voltage measurement is about .52 volts off when measuring Vdd   I have set up a power supply and connected it to external power.  My saadc is set up with 14 bit resolution, a gain of 4, an internal reference (.6v).  I set oversample to try to improve results, as well.  With the usb connected, the saadc is reporting about 2.74 volts and my understanding is the usb is regulated to 3.3 volts.  To get the voltage I am dividing the EasyDMA result by 4551.1  (1/6 / .6) * 2^14

My solution is to subtract .52v off the measured voltage.  I was trying to get better insight into what is going on by adjusting my power supply and seeing what the reported voltage is.  Unfortunately, the USB cable power source conflicts with the external power supply so I cannot use external power to vary the voltage.  Attempting to rectify that, I removed the 5V supply from the USB cable but it appears the JLink connection requires the 5V source and JLink failed. 

I am looking for help on how to debug the adc and saadc and get around the supply source problem.

I realize that subtracting .52v is not a good way to solve this problem as something fundamental must be wrong.  Here is the saadc code and the routine to test the voltage:

static void saadc_init(void){

// Configure SAADC singled-ended channel, Internal reference (0.6V), and 1/6 gain.
NRF_SAADC->CH[0].CONFIG = (SAADC_CH_CONFIG_GAIN_Gain1_6 << SAADC_CH_CONFIG_GAIN_Pos) |
(SAADC_CH_CONFIG_MODE_SE << SAADC_CH_CONFIG_MODE_Pos) |
(SAADC_CH_CONFIG_REFSEL_Internal << SAADC_CH_CONFIG_REFSEL_Pos) |
(SAADC_CH_CONFIG_RESN_Bypass << SAADC_CH_CONFIG_RESN_Pos) |
(SAADC_CH_CONFIG_RESP_Bypass << SAADC_CH_CONFIG_RESP_Pos) |
(SAADC_CH_CONFIG_TACQ_5us << SAADC_CH_CONFIG_TACQ_Pos);
(SAADC_CH_CONFIG_BURST_Enabled << SAADC_CH_CONFIG_BURST_Pos);

// Configure the SAADC channel with VDD as positive input, no negative input(single ended).
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;

// Configure the SAADC resolution.
NRF_SAADC->RESOLUTION = SAADC_RESOLUTION_VAL_14bit << SAADC_RESOLUTION_VAL_Pos;

// Configure result to be put in RAM at the location of "result" variable.
NRF_SAADC->RESULT.MAXCNT = 1;
NRF_SAADC->RESULT.PTR = (uint32_t)&result;

// No automatic sampling, will trigger with TASKS_SAMPLE.
NRF_SAADC->SAMPLERATE = SAADC_SAMPLERATE_MODE_Task << SAADC_SAMPLERATE_MODE_Pos;
NRF_SAADC->OVERSAMPLE = SAADC_OVERSAMPLE_OVERSAMPLE_Over8x << SAADC_OVERSAMPLE_OVERSAMPLE_Pos;

// Enable SAADC (would capture analog pins if they were used in CH[0].PSELP)
NRF_SAADC->ENABLE = SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos;

// Calibrate the SAADC
NRF_SAADC->TASKS_CALIBRATEOFFSET = 1;
while (NRF_SAADC->EVENTS_CALIBRATEDONE == 0);
NRF_SAADC->EVENTS_CALIBRATEDONE = 0;
while (NRF_SAADC->STATUS == (SAADC_STATUS_STATUS_Busy <<SAADC_STATUS_STATUS_Pos));
}

static void low_battery_test(){

// Start the SAADC and wait for the started event.
NRF_SAADC->TASKS_START = 1;
while (NRF_SAADC->EVENTS_STARTED == 0);
NRF_SAADC->EVENTS_STARTED = 0;

// Do a SAADC sample, will put the result in the configured RAM buffer.
NRF_SAADC->TASKS_SAMPLE = 1;
while (NRF_SAADC->EVENTS_END == 0);
NRF_SAADC->EVENTS_END = 0;

// Convert the result to voltage
// Result = [V(p) - V(n)] * GAIN/REFERENCE * 2^(RESOLUTION)
// Result = (VDD - 0) * ((1/6) / 0.6) * 2^14
// VDD = Result / 4551.1
precise_result = (float)result / 4551.1f;

//trip low battery if voltage is less than 2.5 volts
if(precise_result < BATTERY_LOW-.52){

//update the transmit packet content
batt_low = true;

}

int main(void){

  saadc_init();

  low_battery_test();

}

Parents
  • Hi,

    I am having some problems making sense of the situation. You write that measurements are about 0,52 V off. That is far too much though, and as you are using the internal reference the measurement results should be independent of the supply voltage. This leads me to an important question. How do you know that measurements are off? Have you measured on the VDD with an oscilloscope while the SAADC operation takes place and verified it? Without knowing more about your HW I can only speculate, but it could be that some external circuitry, potentially win combination with a high current, makes the VDD voltage lower than you think. So I believe the first think to do is to verify that your target value is correct.

  • I have now tested the firmware on my production hardware and it trips correctly at my trip point.  I still do not understand why the development board is reporting incorrectly but am glad the production board works as expected.

  • Good to hear. That makes sense, then. I did not get a full overview of the DK measurement setup, but as I just wrote in the previous post it looks like you have an issue with your measurement setup when measuring the DK current consumption.

Reply Children
No Data
Related