Help with incorrect(?) SAR ADC CountsTo_Volts readings

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
NoahP
Level 2
Level 2
5 likes given 10 sign-ins 5 replies posted

Hi,

I have a 3.7V LiPo battery powering a PCB using a PSoC 6 MCU. I am trying to implement a simple battery voltage check in firmware, but for some reason when I scan the battery's channel, I am getting values like 1.07V, when measuring the battery by hand is giving ~4.13V.

 

My project has a lot of code separate from this issue, but I will try to share what I can.

I have

// Start ADC Scanner

#define BATT_V_SCAN_CHANNEL 0
ADC_Start();
ADC_StartConvert();

then in main loop I am calling

ADC_IsEndConversion(CY_SAR_WAIT_FOR_RESULT);  // blocking method to detect end of ADC sample conversion
printf("\nBatt Value: %f\n", ADC_CountsTo_Volts(BATT_V_SCAN_CHANNEL, ADC_GetResult32(BATT_V_SCAN_CHANNEL)));

 

as far as I am aware, that is the basic code needed to get the output. I will also share my Scan_ADC config:

 

NoahP_0-1644206190151.png

NoahP_1-1644206218134.png

NoahP_2-1644206227465.png

 

From what I know, it seems like it should be scanning the battery level in a range from 0.0V to 6.6V (0 to 2*Vref), and then converting the value to volts for reading, but the value I am receiving is much lower than the actual battery voltage.

 

I would really appreciate any advice!

 

 

 

0 Likes
1 Solution
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Noah,

Two things to consider.

#1

The PSoC6 maximum operational voltage is 3.6V.  for VDDD and VDDA

VDDA and all analog inputs such not exceed VDDA.  Therefore your battery voltage input of 4.13V will have issues.  This is because any voltages on GPIO pins higher than VDDA will start to conduct current through the ESD diodes limiting the voltage at the pin to no more than VDDA+0.6V.  Additionally the input impedance will change and the worst thing is that you can damage the input (blowing the ESD diode due to excess current).

Yes.  I understand that 2*vref is allowed.  Assuming vref is set to VDDA and VDDA = 3.3V then one would assume 2*vref = 6.6V  Actually ... no.

The 2*vref is really to be used with vref = 1.024V which is a self-regulating band-gap reference.  Therefore in this case, 2*vref = 2.048V.  This is why the the 2*vref setting is available.

If you need to measure voltages higher than VDDA, you should use a resistor divider scheme to bring the resultant input voltage within VDDA range.   Using this the result then needs to be multiplied be the resistor divider factor.

For example :

 

Len_CONSULTRON_1-1644366893559.png

 

If AIN = 4V then AIN_scaled = 2V.   Res_div factor = 2.

Once you read the ADC count you would need to multiply by Res_div to recover the actual voltage.

#2

Anyone who needs to have a relatively accurate ADC count output should never use VDDA as the vref for the ADC.  This is particularly true when you are using a battery powered PSoC.  

The main reason is that the ADC uses the magnitude of vref to determine the ADC count.   The count is 'ratiometric' to the magnitude of VDDA.

For example: If VDDA is 3.6V (which can happen on freshly charged Li-Ion batteries), then a 1V analog input will have the ADC count of (1V/3.6V) *( 2^12) = 1137  for a 12-bit ADC.

If your assumption is that VDDA = 3.3V your reading will reflect 0.916V

However, if after many hours of use, VDDA drops to 2.0V then the ADC count = (1V/2.0V) * (2^12) = 2048 for the same 12-bit AC.

Again, if your assumption is that VDDA = 3.3V your reading will reflect 1.65V

However if you use a band-gap vref like 1.024V, this voltage self-regulates very close to 1.024V across temperature.  The good thing is that this band-gap remains the same even if VDDA is 1.8V or up to 3.6V.   This keeps the ratiometric measurement of the ADC count consistent across the range of VDDA.

The band-gap vref is the closest thing you're going to get to an absolute reference.

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

4 Replies
Vasanth
Moderator
Moderator
Moderator
250 sign-ins 500 solutions authored First question asked

Hi Noah,

Your Vneg for Single Ended(S/E) is connected to reference voltage, which is VDDA in your case. Can you change that to VSSA and see whether you are getting expected results ?

Best Regards,
Vasanth

0 Likes
NoahP
Level 2
Level 2
5 likes given 10 sign-ins 5 replies posted

With this new configuration, 

NoahP_0-1644332905014.png

 

I am getting ADC_GetResult16 returning ~1290 and ADC_CountsTo_Volts returning ~2.09V, so still not quite the ~4.13V I am expecting.

 

Is the PSoC able to scan voltages above 3.3V?

0 Likes
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

Noah,

Two things to consider.

#1

The PSoC6 maximum operational voltage is 3.6V.  for VDDD and VDDA

VDDA and all analog inputs such not exceed VDDA.  Therefore your battery voltage input of 4.13V will have issues.  This is because any voltages on GPIO pins higher than VDDA will start to conduct current through the ESD diodes limiting the voltage at the pin to no more than VDDA+0.6V.  Additionally the input impedance will change and the worst thing is that you can damage the input (blowing the ESD diode due to excess current).

Yes.  I understand that 2*vref is allowed.  Assuming vref is set to VDDA and VDDA = 3.3V then one would assume 2*vref = 6.6V  Actually ... no.

The 2*vref is really to be used with vref = 1.024V which is a self-regulating band-gap reference.  Therefore in this case, 2*vref = 2.048V.  This is why the the 2*vref setting is available.

If you need to measure voltages higher than VDDA, you should use a resistor divider scheme to bring the resultant input voltage within VDDA range.   Using this the result then needs to be multiplied be the resistor divider factor.

For example :

 

Len_CONSULTRON_1-1644366893559.png

 

If AIN = 4V then AIN_scaled = 2V.   Res_div factor = 2.

Once you read the ADC count you would need to multiply by Res_div to recover the actual voltage.

#2

Anyone who needs to have a relatively accurate ADC count output should never use VDDA as the vref for the ADC.  This is particularly true when you are using a battery powered PSoC.  

The main reason is that the ADC uses the magnitude of vref to determine the ADC count.   The count is 'ratiometric' to the magnitude of VDDA.

For example: If VDDA is 3.6V (which can happen on freshly charged Li-Ion batteries), then a 1V analog input will have the ADC count of (1V/3.6V) *( 2^12) = 1137  for a 12-bit ADC.

If your assumption is that VDDA = 3.3V your reading will reflect 0.916V

However, if after many hours of use, VDDA drops to 2.0V then the ADC count = (1V/2.0V) * (2^12) = 2048 for the same 12-bit AC.

Again, if your assumption is that VDDA = 3.3V your reading will reflect 1.65V

However if you use a band-gap vref like 1.024V, this voltage self-regulates very close to 1.024V across temperature.  The good thing is that this band-gap remains the same even if VDDA is 1.8V or up to 3.6V.   This keeps the ratiometric measurement of the ADC count consistent across the range of VDDA.

The band-gap vref is the closest thing you're going to get to an absolute reference.

Len
"Engineering is an Art. The Art of Compromise."

The voltage divider was the solution. Thank you for the detailed and thorough response!

For anyone looking at this later for any reason, I used 4.7k and 10k resistors in a voltage divider to bring the levels down from ~3.4-4.2 to well, about a third of that, which is what the SAR ADC is reading. Thank you everyone.

0 Likes