 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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:
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!
Solved! Go to Solution.
 Labels:

PSoC 6 MCU
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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 selfregulating bandgap 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 :
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 LiIon batteries), then a 1V analog input will have the ADC count of (1V/3.6V) *( 2^12) = 1137 for a 12bit 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 12bit AC.
Again, if your assumption is that VDDA = 3.3V your reading will reflect 1.65V
However if you use a bandgap vref like 1.024V, this voltage selfregulates very close to 1.024V across temperature. The good thing is that this bandgap 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 bandgap vref is the closest thing you're going to get to an absolute reference.
"Engineering is an Art. The Art of Compromise."
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
With this new configuration,
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?
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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 selfregulating bandgap 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 :
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 LiIon batteries), then a 1V analog input will have the ADC count of (1V/3.6V) *( 2^12) = 1137 for a 12bit 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 12bit AC.
Again, if your assumption is that VDDA = 3.3V your reading will reflect 1.65V
However if you use a bandgap vref like 1.024V, this voltage selfregulates very close to 1.024V across temperature. The good thing is that this bandgap 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 bandgap vref is the closest thing you're going to get to an absolute reference.
"Engineering is an Art. The Art of Compromise."
 Mark as New
 Bookmark
 Subscribe
 Mute
 Subscribe to RSS Feed
 Permalink
 Report Inappropriate Content
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.44.2 to well, about a third of that, which is what the SAR ADC is reading. Thank you everyone.