Internally estimating VDD with FVR by routing to ADC on PICs powered by LiPo

Started by trastikata, Aug 21, 2021, 08:54 PM

Previous topic - Next topic

trastikata

Just thought of measuring the VDD level internally on devices with FVR (Fixed Voltage Reference). This could be useful on devices directly powered by LiPo batteries to prevent over-discharge and/or give some warnings without the need of extra circuitry.

I am certainly not the first one to think of it, so if someone tried it, I'd appreciate sharing if it works. Here's what I'd do:

- Tie internally VREF to VDD
- Enable FVR at level, lower than VDD i.e. 1.024v
- Measure the FVR as referenced to VDD by selecting CHS<1111>
- Inversely calculate VDD as function of measured FVR, knowing that FVR is fixed to 1.024

Another question arising is, can I use ADin 15 command to select the FVR (CHS<1111>) channel?

ADC.jpg

trastikata


Giuseppe

You have enabled fvr and you have read the threshold fvr to the adc then you have used a second channel adc
to read the battery voltage right?

trastikata

Quote from: Giuseppe on Aug 22, 2021, 05:48 AMYou have enabled fvr and you have read the threshold fvr to the adc then you have used a second channel adc
to read the battery voltage right?

No, I am not using any of the PIC pins. I am simply measuring the FVR on channel 15.

FVR is fixed to 2.048v, but because the ADC output data is ratiometric to VDD, which is used internally as VREF source, the ADC output data will vary with changes in VDD. 

Here's the code and LiPo battery being discharged while the PIC is working and self measuring the voltage. (the steps are because I decimated the data to 8 bit):

Device = 18F14K50
Declare Xtal = 12

Declare Float_Display_Type = Large

Dim wADC As Word
Dim BatteryVoltage As Float
       
Main:
    ANSEL = 0 : ANSELH = 0  'All pins as digital
    ADCON1 = 0              'VREF tied to VDD and VSS
    ADCON2.7 = 1            'ADC data is right justified
    REFCON0 = %10100000     'FVR enabled at 2.048v, routed to CHS<1111>
   
    While 1 = 1
        Print At 1, 1, Dec VDD()
        DelayMS 500
    Wend
   
Proc VDD(), Float
    ADCON0.0 = 1            'ADC on
        wADC = ADIn 15      'Measure FVR channel as referenced to VDD
    ADCON0.0 = 0            'ADC off
   
    Result = 2097.152 / wADC    'Calculate VDD in function of FVR
EndProc

LiPo.jpg

John Drew

That is very innovative Trastikata.
How about putting it on the WIKI?
John

charliecoutas


top204

A nice mechanism, however, your code will not work correctly...

The VDD procedure is not passing back a value for the Print command to access. To return a value, it must be placed into the procedure's Result variable. The code is using Print VDD(), but VDD has nothing for Print to access, so it will simply print whatever is in the return variable.

trastikata

Quote from: top204 on Aug 22, 2021, 04:40 PMA nice mechanism, however, your code will not work correctly...

The VDD procedure is not passing back a value for the Print command to access. To return a value, it must be placed into the procedure's Result variable. The code is using Print VDD(), but VDD has nothing for Print to access, so it will simply print whatever is in the return variable.

Thank you Les, the original test code used Sub routine and I forgot to change BatteryVoltage to Result when I converted it to Proc. 

top204

You will also need the Dec modifier prior to the VDD procedure in the Print command, otherwise, it will print raw binary data that will not be displayed by an LCD. Also, a Print At, otherwise, the data will be displayed after each previous data text and not in the same position on the LCD.

Print At 1, 1, Dec VDD()