Can you get the supply voltage?

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
mischko
Posts: 18
Joined: Tue Feb 03, 2015 12:32 am

Re: Can you get the supply voltage?

Post by mischko » Fri Feb 06, 2015 11:25 pm

Thanks Damien!
I'll give it a try tonight or tomorrow.

mischko
Posts: 18
Joined: Tue Feb 03, 2015 12:32 am

Re: Can you get the supply voltage?

Post by mischko » Tue Feb 10, 2015 8:12 pm

I'm a bit lost here. The reference voltage I'm getting (with the latest firmware update) is:

Micro Python v1.3.9-55-g53716fc on 2015-02-10; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> adc = pyb.ADCAll(12)
>>> adc.read_core_vref()
1.204468

How do I use that with the voltage divider. Say I'm using a pair of 68K resistors.

What's the formula for the calculation of the battery voltage?

Thanks!
Scott

Damien
Site Admin
Posts: 647
Joined: Mon Dec 09, 2013 5:02 pm

Post by Damien » Tue Feb 10, 2015 11:40 pm

The fact that the vref is very close to 1.2 means that the ADC is pretty accurate and you probably don't need to use vref at all. Just read the ADC of the pin that is connected to your voltage divider and multiply it by 2 to get your battery voltage.

To improve accuracy, multiply the resulting number by 1.2 and the divide by the vref value.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Can you get the supply voltage?

Post by dhylands » Wed Feb 11, 2015 12:40 am

mischko wrote:How do I use that with the voltage divider. Say I'm using a pair of 68K resistors.

What's the formula for the calculation of the battery voltage?
In general, lets say you've got 2 resistors, R1 and R2. And that R1 is connected to some voltage V, and R2 is connected to GND and R1 and R2 are connected to each other.

The voltage that you measure across R2 will be V * R2 / (R1 + R2). or V * 68000 / (68000 + 68000) or V / 2

So if V = 5v then you should expect to see 2.5V where R1 and R2 are connected together.

As long as V doesn't exceed 6.6V then you're good. If it will exceed that, then you'll need to adjust your resistor values such that the voltage into the ADC will never exceed 3.3V

blmorris
Posts: 348
Joined: Fri May 02, 2014 3:43 pm
Location: Massachusetts, USA

Re: Can you get the supply voltage?

Post by blmorris » Wed Feb 11, 2015 2:39 pm

This discussion got me thinking about the actual utility of the internal voltage reference. I had imagined that it would be possible to set the ADC hardware to use VREFINT as the reference voltage for conversions, but that does't seem to be the case. (I've been reading the hardware documentation but it is still possible that I just missed it.)
As far as I can tell, with the 64-pin version of the STM32F405 used on the pyboard, the ADC hardware can only use VDD and GND as the reference for conversions. (Higher pin-count versions of the processor have external pins for Vref+ and Vref-)
VREFINT is hardwired to input 17 of ADC1 where it can be measured against the external voltage reference (the regulated 3.3V supply), but cannot itself be used as a conversion reference. As Damien said, it can serve as an indirect reference for the regulated 3.3V supply - as long as read_core_vref() always returns a number close to 1.21V that isn't varying too much, then you can be assured that the 3.3V supply is stable. If, on the other hand, you get an outlier reading, it may be because a spike in current consumption caused a dip in the 3.3V supply. If you are making critical measurements, you can use read_core_vref() as a check that the supply is stable before or after each measurement. This won't be necessary for most applications.
I imagine that this feature was simply a small bonus that came from the temperature measurement - the easiest way to get the PTAT (proportional to absolute temperature) signal for the temperature measurement was to use a silicon band-gap reference circuit that had already been designed. You need the PTAT signal, you get the stable reference voltage (almost) for free, so might as well connect it to an ADC input.
Could be wrong, just the way it looks to me as a hardware designer.
-Bryan

manitou
Posts: 73
Joined: Wed Feb 25, 2015 12:15 am

Re: Can you get the supply voltage?

Post by manitou » Sat Mar 07, 2015 1:03 am

on UNO's and such you can measure the supply voltage with the bandgap with the ADC. the pyboard read_core_vref() is not constructed to do that ... too bad. to see what your supply voltage is, you would want to calculate rawvalue*1.21/4095, the you could see if your battery power is sagging ...

of course, with a little arithmetic you can reverse the calculation and derive the supply voltage.
vcc = 3.3*1.21/adc.read_core_vref()

EDIT: from later in this thread, you can read the raw ADC vref on channel 17 with

Code: Select all

import pyb
a=pyb.ADC(17)
print (a.read())
Another argument for a simpler interface to the VREF is that stm32407discovery has a Vcc of 3.0v

There is a good discussion on teensy forum of calibrating the internal vref reading to get the Vcc, see
https://forum.pjrc.com/threads/26117-Te ... #post57956
Last edited by manitou on Wed May 06, 2015 10:53 pm, edited 3 times in total.

manitou
Posts: 73
Joined: Wed Feb 25, 2015 12:15 am

Re: Can you get the supply voltage?

Post by manitou » Sat Apr 04, 2015 9:49 pm

As noted above, I'd prefer that adc.read_core_vref() return the estimated Vcc value assuming the internal VREF is 1.21v, or even just return the raw 12-bit ADC values (EDIT: use ADC channel 17). I varied the input voltage to the pyboard 3.3v pin and used pyb.ADC(17).read() to get the raw ADC value. values were

Code: Select all

#adcval volts (at 3.3v pin)
1972.0 2.501
1920.0 2.571
1804.0 2.73
1752.0 2.811
1696.0 2.907
1556.0 3.172
1500.0 3.29
1440.0 3.416
Could do a linear least squares fit (red line) or calibrate the VREF value at 1.205v and use V = 1.205*4095/ADCval (blue curve).
v33new.png
v33new.png (33.61 KiB) Viewed 10098 times
X axis is vref ADC value. Y axis is Vcc (volts).

So one can measure the supply voltage and track the drain of the supply battery.
Last edited by manitou on Sat May 02, 2015 4:08 pm, edited 2 times in total.

Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: Can you get the supply voltage?

Post by Gordon_Hardman » Thu Apr 30, 2015 4:56 pm

I reworked the above data to get an Est. of the supply, and allowed Vr to be a parameter. I then played with Vr to minimize the rms error. This is what I got with Vr=1.204V, which seemed to be about the best for this data set.


Vr= 1.204

Cts Vsup Est. error (%) e^2
1972 2.501 2.500 -0.03 0.00
1920 2.571 2.568 -0.12 0.01
1804 2.73 2.733 0.11 0.01
1752 2.811 2.814 0.11 0.01
1696 2.907 2.907 0.00 0.00
1556 3.172 3.169 -0.11 0.01
1500 3.29 3.287 -0.09 0.01
1440 3.416 3.424 0.23 0.05
rms= 0.12

So the error in the supply voltage seems to be around +/-3mV or so, and the rms error a little over 1 part in a thousand. Not bad, for battery "fuel gauge" purposes. And for a system with a reasonably fixed supply voltage, one calibration with a good DMM should suffice for normal ADC use.

On another note, what does the temperature reading mean? At room temperature I am getting numbers around 68 to 70. Could this really be in Fahrenheit?

Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: Can you get the supply voltage?

Post by Gordon_Hardman » Thu Apr 30, 2015 5:08 pm

On the other hand.... With a measured supply of 3.368V, my device is reporting a vbat of 3.085V, which is an error of 8.4%... I guess so long as it is stable, this can be calibrated out, but that seems a long way off.

Gordon_Hardman
Posts: 68
Joined: Sat May 03, 2014 11:31 pm

Re: Can you get the supply voltage?

Post by Gordon_Hardman » Thu Apr 30, 2015 5:22 pm

It just dawned on me- Vbat must be the backup battery voltage, on Pin 1... On another Pyboard with no battery I get:

Micro Python v1.4.2-48-g6f218d7 on 2015-04-30; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>>
>>> import pyb
>>> a = pyb.ADCAll(12)
>>> a.read_core_vbat()
0.4190476
>>>

Sorry for being so dense! So to get the supply voltage you must measure vref and ratio it out from the supply, not vbat. That's why there are the two of them....

Post Reply