Using Analog pin for battery voltage detection
-
- Senior User
- Posts: 21
- Joined: Thu 2018-03-01 15:45
Using Analog pin for battery voltage detection
Hi all,
As the title explains, I would like to use one of the available analog pins to determine the battery voltage so that I can monitor it.
I read through this thread:
viewtopic.php?f=8&t=2065&p=11044&hilit= ... ead#p11044
but it didn't seem to specify what chipset they were implementing on. I don't know if this is a generic function that can be used across all chips or not. It seems to make reference to the Hi-res Player, which is based off of the VS1005 so it should be a fairly simple edit if so.
Anyway, is this implementation usable for my purposes? If not, is there an example of voltage monitoring on an analog pin for the VS1005 that is readily available? If not, how can I effectively implement my own solution?
As the title explains, I would like to use one of the available analog pins to determine the battery voltage so that I can monitor it.
I read through this thread:
viewtopic.php?f=8&t=2065&p=11044&hilit= ... ead#p11044
but it didn't seem to specify what chipset they were implementing on. I don't know if this is a generic function that can be used across all chips or not. It seems to make reference to the Hi-res Player, which is based off of the VS1005 so it should be a fairly simple edit if so.
Anyway, is this implementation usable for my purposes? If not, is there an example of voltage monitoring on an analog pin for the VS1005 that is readily available? If not, how can I effectively implement my own solution?
Re: Using Analog pin for battery voltage detection
Hello!
The Hi-Res player monitors the battery voltage so it can be done. The best example can be found from VS1010.
viewtopic.php?f=15&t=2131 Only differences are the ANA_CFx registers. To enable SAR you need to use PERIP(ANA_CF1) |= ANA_CF1_SAR_ENA; Rest of the code isn't that much chip specific.
You can also search the implementation from the hires player sources.
If you use external resistor divider, it consumes power all the time. If you take power straight from the battery to VHIGH, you can measure it too. VHIGH has internally connected SAR channel.
The Hi-Res player monitors the battery voltage so it can be done. The best example can be found from VS1010.
viewtopic.php?f=15&t=2131 Only differences are the ANA_CFx registers. To enable SAR you need to use PERIP(ANA_CF1) |= ANA_CF1_SAR_ENA; Rest of the code isn't that much chip specific.
You can also search the implementation from the hires player sources.
If you use external resistor divider, it consumes power all the time. If you take power straight from the battery to VHIGH, you can measure it too. VHIGH has internally connected SAR channel.
Re: Using Analog pin for battery voltage detection
That's right. The VS1010 ReadVoltage - GetBatteryVoltage example, to which Hannu linked to, is in fact derived from the VS1005 Hi-Res player code. The Hi-Res player uses an analog pin to measure the battery voltage because it wants to measure the battery voltage ALSO when USB power is connected. And then VHIGH is obviously in the USB voltage and measuring VHIGH is pretty much useless.
So the external voltage divider is needed to measure the battery when USB is present and VHIGH is at 5 volts. It drains a couple of microamperes from the battery, decreasing the self discharge time a little. That's unfortunate, but I felt that I can live with it.
-Panu
So the external voltage divider is needed to measure the battery when USB is present and VHIGH is at 5 volts. It drains a couple of microamperes from the battery, decreasing the self discharge time a little. That's unfortunate, but I felt that I can live with it.
-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo
Panu-Kristian Poiksalo
-
- Senior User
- Posts: 21
- Joined: Thu 2018-03-01 15:45
Re: Using Analog pin for battery voltage detection
Thanks for the replies and guidance.
My particular solution uses a lithium battery with a voltage regulator to 5V. I was planning on connecting the battery directly to an AUX pin to read the value.
My followup question then is that I saw the voltage rating for the AUX pins is 3.6V. This is the nominal voltage for lithium cell batteries, however they do charge up to 4.2V. If I connect the battery directly to the pin, is that okay? Will voltages above the stated 3.6V cause damage, or simply cause the 10-bit value to be all 1's? I am fine with reading all values above 3.6V as 3.6V, but I don't want to damage the board. If damage is a concern, I would assume that I would just create a voltage divider to bring it back to safe values.
My particular solution uses a lithium battery with a voltage regulator to 5V. I was planning on connecting the battery directly to an AUX pin to read the value.
My followup question then is that I saw the voltage rating for the AUX pins is 3.6V. This is the nominal voltage for lithium cell batteries, however they do charge up to 4.2V. If I connect the battery directly to the pin, is that okay? Will voltages above the stated 3.6V cause damage, or simply cause the 10-bit value to be all 1's? I am fine with reading all values above 3.6V as 3.6V, but I don't want to damage the board. If damage is a concern, I would assume that I would just create a voltage divider to bring it back to safe values.
Re: Using Analog pin for battery voltage detection
3.6V is the maximum rating for the silicon process.
Also, if a voltage on the analog pin is above the AVDD voltage (or below AGND), current starts to flow through the protection diodes to try to protect the IC.
Measuring 4.2V would need a voltage divider.
Also, if a voltage on the analog pin is above the AVDD voltage (or below AGND), current starts to flow through the protection diodes to try to protect the IC.
Measuring 4.2V would need a voltage divider.
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook
-
- Senior User
- Posts: 21
- Joined: Thu 2018-03-01 15:45
Re: Using Analog pin for battery voltage detection
Thanks again for the quick response.
I have a quick question in regards to implementation of this code now.
I would like to take the solution as mentioned and have it run as a separate task that spends the majority of the time asleep and once every few minutes wakes up to check the voltage to see the battery life.
From the Playfiles driver, I see that the Startask() function is used to created a separate task for the audio decoding so that it may run in the background. This lets me know that the Startask() function is what I want to use.
The second parameter passed is the function to run in the background. In the case of the audio decoding in playFiles, it is the playerThread function. In my case, I would name it something along the lines of monitorVoltage(). So, now my command looks something like:
StartTask(TASK_DECODER, monitorVoltage)
From what I read the task_decoder variable has something to do with specifying the memory for the task. My question then is if I am allowed to have two tasks running, both with the TASK_DECODER variable passed? If not, what are the other possibilities here that will allow both to work at the same time?
Also, I see in the programmer documentation that it says the DELAY() function is used to release the CPU for a specified time. This is what I want to do, so I would place that within my monitorVoltage() function somewhere. I just wanted to verify that this function actually places the task to sleep and does not continue to waste power through busy waiting, like a for loop would do.
Thanks in advance for all the help.
I have a quick question in regards to implementation of this code now.
I would like to take the solution as mentioned and have it run as a separate task that spends the majority of the time asleep and once every few minutes wakes up to check the voltage to see the battery life.
From the Playfiles driver, I see that the Startask() function is used to created a separate task for the audio decoding so that it may run in the background. This lets me know that the Startask() function is what I want to use.
The second parameter passed is the function to run in the background. In the case of the audio decoding in playFiles, it is the playerThread function. In my case, I would name it something along the lines of monitorVoltage(). So, now my command looks something like:
StartTask(TASK_DECODER, monitorVoltage)
From what I read the task_decoder variable has something to do with specifying the memory for the task. My question then is if I am allowed to have two tasks running, both with the TASK_DECODER variable passed? If not, what are the other possibilities here that will allow both to work at the same time?
Also, I see in the programmer documentation that it says the DELAY() function is used to release the CPU for a specified time. This is what I want to do, so I would place that within my monitorVoltage() function somewhere. I just wanted to verify that this function actually places the task to sleep and does not continue to waste power through busy waiting, like a for loop would do.
Thanks in advance for all the help.
Re: Using Analog pin for battery voltage detection
You need to allocate the task memory space.
From auxplay:
struct TaskAndStack *taskAndStack = NULL;
taskAndStack = CreateTaskAndStack(AudioTask, "AUXPLAY", 256, 2)
And the auxplay task starts. See AUXPLAY solution
After task has exited: FreeTaskAndStack(taskAndStack);
However... I as you already said, the monitor is sleeping most of the time, you could use cyclic interface
From auxplay:
struct TaskAndStack *taskAndStack = NULL;
taskAndStack = CreateTaskAndStack(AudioTask, "AUXPLAY", 256, 2)
And the auxplay task starts. See AUXPLAY solution
After task has exited: FreeTaskAndStack(taskAndStack);
However... I as you already said, the monitor is sleeping most of the time, you could use cyclic interface
Code: Select all
#include <cyclic.h>
void MyCyclicFunc(register struct CyclicNode *cyclicNode) {
// ....
}
struct CyclicNode myCyclicNode = {{0}, MyCyclicFunc};
ioresult main() {
// ...
AddCyclic(&myCyclicNode, TICKS_PER_SEC/10, TICKS_PER_SEC/10);
// ...
}
void fini() {
DropCyclicNode(&myCyclicNode)
}
-
- Senior User
- Posts: 21
- Joined: Thu 2018-03-01 15:45
Re: Using Analog pin for battery voltage detection
Thanks again for the information. I may stick to the first approach rather than use the Cyclic command.
Quick testing gives me unexpected results. When I run a modified version of the provided code, I have an RCAP and AUX value of 438. Since they are both 438, the voltage reported ends up being 1.66. This seems okay, I just need to subtract the 1.66 from the value to get back to the value I expect then.
However, when I connect IOVDD to the analog pin, the value changes to AUX = 646 and voltage = 2.45. I'm expecting 3.3V + 1.66V as the output for it to be correct.
I don't know if this is an issue with the AUX value I am receiving back or if it is an issue with the resolution of each bit. For example, that 200 difference in AUX could be used to to calculate the LSB value and then scale it appropriately to 3.3V. I haven't tried other voltage values yet to determine if that is the case, but it seemed off regardless.
I provided my very minimally modified code to look at.
Quick testing gives me unexpected results. When I run a modified version of the provided code, I have an RCAP and AUX value of 438. Since they are both 438, the voltage reported ends up being 1.66. This seems okay, I just need to subtract the 1.66 from the value to get back to the value I expect then.
However, when I connect IOVDD to the analog pin, the value changes to AUX = 646 and voltage = 2.45. I'm expecting 3.3V + 1.66V as the output for it to be correct.
I don't know if this is an issue with the AUX value I am receiving back or if it is an issue with the resolution of each bit. For example, that 200 difference in AUX could be used to to calculate the LSB value and then scale it appropriately to 3.3V. I haven't tried other voltage values yet to determine if that is the case, but it seemed off regardless.
I provided my very minimally modified code to look at.
Code: Select all
#define SAR_AUX2 (0x0 << 8)
#define SAR_RCAP (0x8 << 8)
s_int16 GetSarValue(register u_int16 channelShifted) {
// Configure SAR and start the conversion.
PERIP(SAR_CF) = SAR_CF_ENA | (10) | channelShifted;
// Wait until the conversion is complete.
while (PERIP(SAR_CF) & SAR_CF_ENA);
// Return the conversion result (0...4095)
return PERIP(SAR_DAT);
}
void monitorVoltage(void)
{
u_int16 sar_aux, sar_rcap;
float volts;
//while (1)
//{
// Read the AUX channel level using the SAR.
sar_aux = GetSarValue(SAR_AUX2);
// Read also the reference voltage using SAR. Since the reference voltage is
// known, this protects against inaccuracies caused by fluctuations in the
// analog supply voltage.
sar_rcap = GetSarValue(SAR_RCAP);
// Remove the commenting to print the raw SAR values.
//printf("aux=%4d, rcap=%4d ",sar_aux,sar_rcap);
// Convert SAR_AUX conversion result to millivolts using the resistor
// divide factor and a known 1.662V reference voltage (RCAP).
// Resistor divide factor (1M vs 2M) * bandgap voltage (1.662 millivolts)
sar_aux = ((s_int32)sar_aux * 1662) / sar_rcap;
// Convert integer millivolts to float volts.
volts = sar_aux * 0.001;
printf("Voltage: %2.2f\n",volts);
// Delay(FIVE_MINUTES); // Only check voltage once every 5 minutes
//}
}
int main(char *filespec) {
FILE *fp = NULL;
static char fnumMode[10];
PERIP(ANA_CF1) |= ANA_CF1_SAR_ENA; // Powers and enables the SAR
ioctl(stdaudioout, IOCTL_AUDIO_SET_VOLUME, (void *)(volume+256));
monitorVoltage();
...
}
Re: Using Analog pin for battery voltage detection
Any measured voltages are valid only between 0 and AVDD. Can you measure the value of AVDD with a multimeter just to be sure everything is powered up properly?
-Panu
-Panu
Info: Line In and Line Out, VS1000 User interface, Overlay howto, Latest VSIDE, MCU Howto, Youtube
Panu-Kristian Poiksalo
Panu-Kristian Poiksalo
Re: Using Analog pin for battery voltage detection
Which value do you get when AUX is connected to GND?
If you don't have anything connected to a pin, it probably biases to the reference voltage, which is why you get the same value for the reference voltage and the other input.
And like Panu asks, what are you measuring for IOVDD and AVDD voltages with multimeter?
If you don't have anything connected to a pin, it probably biases to the reference voltage, which is why you get the same value for the reference voltage and the other input.
And like Panu asks, what are you measuring for IOVDD and AVDD voltages with multimeter?
Visit https://www.facebook.com/VLSISolution VLSI Solution on Facebook