5
\$\begingroup\$

I am using the ADC on an STM32F030F4P6 to read a battery voltage, usually between 4.2 and 3.5 V. The resistor divider is designed to reduce the voltage so that 4.2 V input becomes ~3.1 V at the ADC and 3.5 V becomes ~2.6 V. The analog reference voltage is 3.3 V.

Circuit_all

I'm getting a strange, stable, reproducible result as shown in this graph:

Graph

I've verified that the voltage at the ADC pin is as expected (i.e. the resistor divider is working as intended).

The ADC calibration process is being run at boot as per the datasheet:

LL_ADC_Disable(ADC1);

while (LL_ADC_IsEnabled(ADC1)) {
}

LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);

LL_ADC_StartCalibration(ADC1);

while (LL_ADC_IsCalibrationOnGoing(ADC1)) {
}

LL_ADC_REG_StopConversion(ADC1);

WRITE_REG(ADC1->ISR, LL_ADC_FLAG_EOC | LL_ADC_FLAG_EOS | LL_ADC_FLAG_OVR | LL_ADC_FLAG_ADRDY | LL_ADC_FLAG_AWD1);

LL_ADC_EnableIT_EOS(ADC1);
LL_ADC_Enable(ADC1);

// wait for VREF to stabilize
for (volatile uint32 i = LL_ADC_DELAY_VREFINT_STAB_US * (SystemCoreClock / 1000000U); i != 0; i--) {
}

// wait for adc ready
while (!LL_ADC_IsActiveFlag_ADRDY(ADC1)) {
}

I've taken multiple readings and the results are always the same. I'm using 12 bit resolution and sampling for 13.5 cycles. The results are the same if I sample for longer (e.g. 239.5 cycles).

Is this expected? I understand that the ADC is non-linear to some extent and that the error is dependent on where in the capacitor ladder the voltage is. Is this what I'm seeing here?

Or is the 1 nF capacitor interfering in some way? I added it to reduce the induced noise on the power rail when the ADC was active.

[Edit]

So, the datasheet says N/A for the impedance when using 239.5 cycles but... I suspect 3 MΩ is still too much. One thing I'm considering is using a really large capacitor, 1 uF, and just sampling the voltage very occasionally

Datasheet

\$\endgroup\$
14
  • 4
    \$\begingroup\$ It looks like your potential divider resistances are too high by a factor of maybe 100. Check the data sheet to see what it tells you about source impedance of signals fed to ADC input pins. \$\endgroup\$
    – Andy aka
    Commented Mar 28, 2023 at 16:47
  • \$\begingroup\$ This was why I added the capacitor - the ADC readings are taken quite infrequently so I was expecting the capacitor to supply the low impedance source, is that not going to work? \$\endgroup\$ Commented Mar 28, 2023 at 16:49
  • 1
    \$\begingroup\$ I can't be 100% about this so check the DS is what I recommend. It will tell you but it may take a little tracking down. It may be quicker just to try it and see. You might be able to tack/bodge a 7.5 k and a 22k resistor across the existing ones rather than replace them. \$\endgroup\$
    – Andy aka
    Commented Mar 28, 2023 at 16:50
  • 4
    \$\begingroup\$ Top-tip when laying out a PCB always put test points on areas like this. In fact I put loads of test points everywhere (just in case) even though I get a massive success rate with prototype PCBs. Please feedback what you find. \$\endgroup\$
    – Andy aka
    Commented Mar 28, 2023 at 17:05
  • 1
    \$\begingroup\$ If the intention of the high resistance values is to reduce the drain on the battery, maybe something like the circuit shown in Zero-power measurement – part 2 would help, although he's working with a 6 V battery and an ATmega328. \$\endgroup\$ Commented Mar 28, 2023 at 18:08

4 Answers 4

7
\$\begingroup\$

While the issues discussed in other answers and comments (too high an impedance in the divider, perhaps sample rate) are real, I don't buy that they explain the observed behavior.

I think the effect is due to failure of the assumption "The analog reference voltage is 3.3V", as would occur if some linear regulator was used to power the MCU from VBAT. That would explain the shape of the curve quite well.

Now that we have more schematic: that would be the case if the test is conducted with the LiPo1 battery (or a voltage source replacing it for test purposes) as the source of power: because the regulator U1 is linear, the 3V3 node would drop below 3.3V when VBAT goes below about 3.8V (3.3V + drop of U1 + drop of Q1) and from then down the reading of the ADC would be off and too high, just as we see it!

A solution to this problem is to also measure VREFINT, which is internally connected to the ADCIN17 input channel, and apply a correction; as a first order approximation:

  VBAT = (R11 / R12 + 1) * (ADCPA4 / ADCIN17) * 1.23V

It's possible to improve on this by replacing 1.23V by the factory-calibrated VREFINT_CAL.

And if we go to hardware, by lowering the impedance of the voltage divider (with the important drawback of a higher drain on the battery). It's possible to connect that divider only during measurement with more components, as in that answer.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ This makes good sense. \$\endgroup\$
    – RussellH
    Commented Mar 30, 2023 at 18:43
  • 1
    \$\begingroup\$ Thanks, this is indeed it - I could get around it as you say by recalibrating the ADC each time and using ADC17, or use a 2.5V LDO which gives me enough headroom. \$\endgroup\$ Commented Apr 7, 2023 at 8:13
  • \$\begingroup\$ To wrap this up, high leakage from D1 was stopping Q1 from switching on so power was oinly flowing through the body diode which dropped around 0.5V. Replacing D1 with a low leakage diode means Q1 switches on and now the 3.3V rail is good when VBAT goes down to 3.5V which is the low range for the Li-po. \$\endgroup\$ Commented Apr 11, 2023 at 16:30
  • \$\begingroup\$ @Charlie Skilbeck: makes sense. If it's for more than one unit, I would still consider using VREFINT and VREFINT_CAL, which I think will give you a more reproducible/precise reading of VBAT than using the output of the LDO regulator as reference can. \$\endgroup\$
    – fgrieu
    Commented Apr 12, 2023 at 7:24
2
\$\begingroup\$

I'm going to agree with @RussellH that the potential divider is problematic in that it represents a source impedance of over 500kΩ. The datasheet, in fig. 24, shows some internal shenanigans with a current source of 1μA, which when pushed or pulled through 500kΩ could produce errors over 0.5V. I am not sure, though, what that source is for, or represents.

As a first measure, try replacing resistors R11 and R12 for much, much lower ones (say 7.5kΩ and 22kΩ), and remove capacitor C11, which may also be causing issues. These changes are just temporary. If the problems go away, then you've identified them.

If lower values for R11 and R12 solved the issue, then obviously you must use lower values, but of course you wish to keep current in that divider as low as possible. However, instead of buffering the divider's output, which needs an op-amp and wastes more power, I think you could switch the divider on, measure, then switch it off again.

If you have a spare digital output, or can hijack one momentarily from an LED or something, then switch in and out a much lower impedance resistor divider like this:

schematic

simulate this circuit – Schematic created using CircuitLab

Current only flows in the divider, or M2, when P?? is high. When P?? is low, that whole subsection is dormant.

\$\endgroup\$
1
  • \$\begingroup\$ I think the \$I_L\$ is a leakage current or a digital injection. It is not clear in the data sheet. Whatever it is, it will influence the sampling \$\endgroup\$
    – RussellH
    Commented Mar 30, 2023 at 18:31
1
\$\begingroup\$

The impedance of the voltage divider is way to high. If you can't lower the resistances then you should use an op-amp unity gain buffer with a rail-to-rail input and output.

Update:

The data sheet clearly indicates that the external resistance must be less than \$50k\Omega\$.

enter image description here

Table 51 (shown by OP) shows this as well.

enter image description here

With regard to the filter external capacitor, again the data sheet requires the total external capacitance be as small as possible:

enter image description here

Refer in particular to Note 2 of Figure 24 (reproduced below).

Quote: "A high \$C_{\text{parasitic}}\$ will downgrade conversion accuracy."

So the original answer still stands. The impedance is too high.
Now in addition, the capacitance is also too high.

Clearly the resistors were chosen to reduce current consumption. The capacitor is chosen for noise filtering.

If these are important then a buffer amplifier is required. There is a trade -off between of current draw between a lower impedance voltage divider and the quiescent current of the buffer amplifier.

Also from Note 2, the effect of high capacitance "... can be remedied by reducing \$f_{adc}\$". This is to increase the available sampling time based on the number of clock cycles.

Finally, notice the constant current source \$I_L\$. They aren't clear on what this is (leakage perhaps) but it will cause a voltage drop across the input resistance further introducing errors.

\$\endgroup\$
14
  • 1
    \$\begingroup\$ @Justme: Sure it can charge the S&H capacitor quickly. But with the values shown the charge on the 1nF requires 2.8ms to recover. This is way too long. \$\endgroup\$
    – RussellH
    Commented Mar 28, 2023 at 19:39
  • 1
    \$\begingroup\$ Why it is too long? How often must the battery voltage be sampled to be enough - I would guess once per second is plenty already? \$\endgroup\$
    – Justme
    Commented Mar 28, 2023 at 20:09
  • 1
    \$\begingroup\$ Yes, so if you sample at slow enough rate; it will work, and therefore the impedance with the capacitor is low enough. So the statement in the answer is false then if the impedance is low enough. \$\endgroup\$
    – Justme
    Commented Mar 29, 2023 at 5:15
  • 1
    \$\begingroup\$ @Justme: Sorry, I use “interval “ perhaps incorrectly. I am referring to the time from selecting the input to the time that the conversion starts, not the time between samples. If the droop is more than the desired resolution then the capacitor must be allowed to recover within the sample time. \$\endgroup\$
    – RussellH
    Commented Mar 29, 2023 at 13:27
  • 1
    \$\begingroup\$ The source \$I_L\$ is suspicious to me. It says ±1µA, which made me wonder if it was sourcing and then sinking, to compensate somehow for source impedance? Either way, 1µA through this source impedance of 500kΩ is 0.5V. That's huge, comparable with OP's measurement inconsistencies. \$\endgroup\$ Commented Mar 30, 2023 at 13:25
-1
\$\begingroup\$

A sampling time of 13.5 cycles maybe is the problem try a longer sampling time that leads to a more accurate measurement. You need to try different sampling times to find the optimal accuracy.

\$\endgroup\$
3
  • \$\begingroup\$ How does increasing the sampling time lead to a more accurate measurement? \$\endgroup\$
    – Arnfinn
    Commented Mar 28, 2023 at 18:50
  • 2
    \$\begingroup\$ @Arnfinn: The ADC has an on chip sample-and-hold capacitor that must be charged by the input current. High sampling impedance will require longer sampling times in order to charge that capacitor for accurate measurements. \$\endgroup\$
    – RussellH
    Commented Mar 28, 2023 at 19:21
  • \$\begingroup\$ I've tried with 239.5 cycles and the results are very similar - The last thing to try is increasing the capacitor from 1nF to 1uF (or higher if I can get it in the 0402 package). This means I can only sample infrequently but that's fine, I can measure how long it takes the capacitor to charge and just not sample faster than that. Worth a go... \$\endgroup\$ Commented Mar 29, 2023 at 9:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.