PDA

View Full Version : Battery monitoring - ever tried AN1072?



flotulopex
- 19th September 2015, 08:02
Hi,

As some other threads around the forum about battery monitoring, I want to setup a battery monitoring system based on MICROCHIP's AN1072 "Measuring VDD Using the 0.6V Reference" (https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CBwQFjAAahUKEwjK_vr6voLIAhVC2BoKHWFaDa8&url=http%3A%2F%2Fww1.microchip.com%2Fdownloads%2Fe n%2FAppNotes%2F01072A.pdf&usg=AFQjCNEm6imq69_7Mg4jnVlHrZpyS9_OWw&bvm=bv.103073922,d.d2s).

In short, it says:
"To measure VDD, VDD should be selected as the reference to the ADC via VCFG, and the 0.6V reference selected as the input using the channel select bits, CHS<3:0>. A measurement of the 0.6V input is taken with the ADC, and the result represents 0.6 Volts as a percentage of VDD. As VDD increases, the resulting number will decrease and vice versa. This yields a direct “1/x” relationship between V DD and the produced digital value as seen in Equation 1. In short, given a specific VDD, the digital value is always the same. Working backwards, if the digital value is known, VDD may be calculated."

8039

It tells you what you have to do and even how. Now guess: I can't make it work :o

I have a circuit using a 16F690 (great! same one as used in the AN!). For the test, the circuit is connected to my variable power-supply so I can simulate a low battery condition (i.e. from 6VDC, I go down to 5,5VDC*).

According to the AN1072, the ADCON0 register has been set to %10110101.

Now when I vary the voltage on the power-supply, I get always the same ADC reading (no value change at all).

What am I doing wrong?

NB*: Yes, I'm using a LDO voltage regulator so I could use another way to check the battery's condition (i.e. comparator or resistor-divider)...but I want to have a go with the AN1072 ;)

flotulopex
- 19th September 2015, 09:21
That's the ADCON0 register:
8040

richard
- 19th September 2015, 09:29
I might have the wrong end of the stick here , but if you have a ldo reg suppling vdd won't you always read the regulated voltage. to read the battery voltage that way requires the battery be connected to vdd directly.

flotulopex
- 19th September 2015, 11:43
Sorry Richard, I don't get what you mean.

Charlie
- 19th September 2015, 12:44
You need to make sure you measure on the input side of the LDO, not the output side. It's job it to keep the voltage constant. You will need a resistor divider to reduce the battery sense voltage to within the range of the PIC. Post the schematic of how you connected the PIC.

towlerg
- 19th September 2015, 13:27
The point is that the AN1072 method measures Vdd as supplied to the 16F690 - it is purely internal. If you want to measure some other voltage, like the battery side of the LDO you need to use a potential divider (for example) and an ADC inputs that accepts an external input.

George

flotulopex
- 19th September 2015, 13:43
So I'll have to go for this one?

8041

flotulopex
- 19th September 2015, 14:16
Thank you George.

I did unfortunately not understand the AN the way you explain.

Let's go for a divider then ;)

towlerg
- 20th September 2015, 12:24
Is the 6V cast in amber? One of the may great features of the 690 is that it will run at 8Hz (convenient for internal clock) from 5.5V down to 2.0V.

George

flotulopex
- 21st September 2015, 08:10
Thanks George,

The aim of the thread I started is to find a good solution to check the battery's condition regardless with what PIC it is used.

In my case, I'm building a cooking timer and I have a sounder that needs at least 5VDC. So I'll better know when the batteries get low or my eggs will be like stones ;)

Ioannis
- 21st September 2015, 10:31
Hi Roger.

I like my egg like stones, but thats just me...!

About your circuit, you put a transistor I suppose to conserve energy while not measuring the battery, right?

But when the transistor is OFF, you drive a PIC input at 6 volts, higher than the specs, and also higher than the Vdd supply. So, the protection diodes of the input will forward the current to the PIC Vdd pin and you fry your PIC than your eggs!

Ioannis

longpole001
- 21st September 2015, 12:43
better off using higher value resistors to reduce the over all current draw of the voltage divider , but if you have too higher values the current will not be enough for accruate reading but after you do testing you will find the avg voltage range with the resistors used and you can apply that offset to the reading.

also use the inbuild voltage ref for the ad readings so that when you transfer between various input voltage on differnat pics , the same code and voltage tables can be used for either 10 bit or 12 bit ad cpus

towlerg
- 21st September 2015, 13:16
the same code and voltage tables....

Just in case anyone should be put of by mention of tables, the math is real simple - VDD = 6144/Ad_Result (0.6 * 1024 = 614.4 - 10bit - result in 0.1V).

It will come as no surprise to here that Daryl posted this info.

George

flotulopex
- 22nd September 2015, 22:13
This is how I made it for now ;)

Vbatt is 6VDC (4x AAA batteries) and VREG is 5VDC (hence, VREG is the reference voltage).

To measure the batteries, I draw 10mA; this seems to be okay to me - if not okay, please suggest another current I should have.

8046

Ioannis
- 23rd September 2015, 08:50
Roger, as I stated earlier, when the FET is OFF you supply +6 to the PIC pin. This is dangerous!

Ioannis

flotulopex
- 23rd September 2015, 17:34
Wow! I missed that!

What's the solution then? Shall I go with P-channel MOSFET?

towlerg
- 23rd September 2015, 17:49
How about move the MOSFET above the junction of ADC_IN. Voltage drop across the MOSFET?

George

Ioannis
- 23rd September 2015, 18:30
George's idea maybe feasible but FET's specs should be examined in detail.

A P-channel I thing is best with the aid of second NPN transistor that will be driven from the PIC enable output.

If you need more help with the circuit, please ask.

Ioannis

flotulopex
- 23rd September 2015, 18:38
Is this an "acceptable" solution?

6V is battery voltage
5V is from PIC

Battery check is OFF:
8050

Battery check is ON:
8049

Ioannis
- 23rd September 2015, 19:34
Yes it is. In fact exactly what I was thinking to suggest you!

Only objection the values of the voltage divider. These are low and you will have much current drain. Since PIC ADC has a nominal input impedance of 10K you can increase by a factor of 10 the values. Say at 1k8 and 5k6.

Ioannis

flotulopex
- 23rd September 2015, 20:13
Thanks Ioannis.

By choosing the 180 and 560 values, I was thinking about drawing "enough" current out the batteries to get an as accurate as possible voltage reading (load = +/- 10mA).

10mA is "only" 1% of the batterie's capacity added to the few mA from the circuit, I think this is already low - but I'm not a battery expert, just knowing for sure that three minutes are okay for eggs :D

What do you think?

amgen
- 23rd September 2015, 23:07
for low battery draw, use high value r's and wait 5RC , that's 5 time constants between readings which allows 1 micro farad cap to charge to full divider value. That's 180K times 1X10to minus 6 which is about .2 seconds. The 1 micro farad is many times the cap value in the pic so it is an accurate reflection of the voltage and high r's draw micro amps from battery...... no switching on/off stuff8051

Charlie
- 24th September 2015, 00:26
exactly what I was about to say, except cap should be 0.1 uf. This reduces your current to 8 uA.

flotulopex
- 24th September 2015, 05:20
... and wait 5RC , that's 5 time constants between readings (about .2 seconds)

So, if I get you right, no transistors at all, just two resistors, one cap. And then, launch the ADCIN command a few times with at least 0.2 seconds interval.

Correct?

Ioannis
- 24th September 2015, 10:01
That was an example with the cap.

You SHOULD add the transistor!. Just use cap for more stable reading when R's are higher and have more time waitng for sampling. Also you do nothave to keep the divider active all the time, just for the few ms to read the AD valu. Then switch it off.

Ioannis

flotulopex
- 24th September 2015, 13:06
Thanks Ioannis but what about the load?

Ioannis
- 24th September 2015, 13:18
What load? I did not understood that.

Ioannis

Charlie
- 24th September 2015, 14:30
Honestly, you are coming up against traditional design tradeoffs. To be able to measure the battery reserve, how much battery capacity are you willing to burn vs cost of the circuit? Using just 2 high value resistors without the transistor can be almost as efficient as having the transistor in there when you consider leakage currents if the values are high enough, and simplify the circuit, simplify the software, and cost a few pennies less. The problem is that the input impedance of the pin could load the resistor divider if the values get too high, and of course the high values add a susceptibility to electrical noise. The cap helps with removing noise, and prevents the load caused by sampling to impact the result if the reading is taken fairly quickly compared to the time constant of the RC product. If you don't care about cost and a relatively minor increase in complexity, then use lower value resistors to make the parasitics less of an issue, and use the transistor to switch on the circuit. If you are not comfortable with analog design, then the transistor simplifies the math.

Ioannis
- 24th September 2015, 15:08
Roger, do follow post #19 and just add a capacitor in parallel to the 560 resistor. A 1uF would be just fine. Or bigger if you have one.

This will give consistent AD values.

Thats all.

Ioannis

flotulopex
- 24th September 2015, 22:40
Received loud and clear ;)

longpole001
- 26th September 2015, 05:16
also consider that the voltage drop from a 6v incoming source to your LDR output at 5v /pic is going to give you much margin (.5v at best ) before your looking to have to replace the batteries, no cos they are that low just cos your voltage usage margin is small

consider running the app at 3.3v , take a closer look at thge items that require the 5v externally to the PIC to look at using devices at 3.3v as this will give a larger usage margin for the batteries and device

just a thought

flotulopex
- 26th September 2015, 17:14
After my first tests, I changed my circuit from 3,3VDC to 5VDC hence accepting the "margin" reduction.

The project I'm working on now is a cooking timer and I have a piezo-sounder that sounds best (= loudest) at pseudo* 10VAC (*I use a full bridge inverter for higher volume).

BTW, I use a LP2950ACZ5.0 and it's dropout voltage is around 0,2V @ 10mA. 0,8V leave me far enough accuracy to determine when it is time to change the batteries ;)

flotulopex
- 26th September 2015, 17:41
I still would like to know how to "read" the 0,6V (VP6) channel. This voltage reference is provided by the PIC itself.

If I set the ADSCON0 register to (i.e.) %10110100 (right just., VDD, 0,6V Reference, ADC is ON), what is the PICBASIC command to read that channel? If it is ADCIN, then ADCIN what?

8056

I tried with:

ADCIN 13, myvar
because I see channels from 0 to 11 in the DS, maybe "0,6 V ref" would be the 13th...and PBP accepts the compilation but the ADCIN result shows always 0 :(

Ioannis
- 26th September 2015, 17:56
ADCIN x, myvar

where x is the AD channel where you connected the voltage divider we were talking before.

If it is on pin 18, channel 1 then x=1 and so on.

Ioannis

flotulopex
- 26th September 2015, 20:33
I'm sorry, but I still don't understand :confused:

Looking at the ADC bloc diagram I've attached in post#1, I understand there is a "0,6V Reference" channel that I have to select to get an ADCIN result of 122 @ 5VDC or 186 @ 3,3VDC.

This channel doesn't seem to be linked to any pin of the PIC - this is confusing me at most.

Does this "0,6V Reference" channel really exist?

----

Hum...just found I have to ENABLE the 0,6Voltage Reference in VRCON register, bit 4 "VP6EN". I'll have a try in a moment...

flotulopex
- 26th September 2015, 20:48
...no, still getting 0.

Ioannis
- 26th September 2015, 21:25
Please post the program.

Ioannis

flotulopex
- 26th September 2015, 21:42
This is the code of which I removed the "cooking timer" specific code placed after the DEBUG part. If you think it can help, I'll post the full code.
'-------------------------------------------------------------------------------
' PIC 16F690 Fuses (MPASM)
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
'_INTRC_OSC_NOCLKOUT

'-------------------------------------------------------------------------------
' Registers 76543210
OPTION_REG = %10000110 'Pull-Ups OFF, Prescaler TMR0 1:128
ANSEL = %00010000 'Select analog inputs Channels 0 to 7
ANSELH = %00000000 'Select analog inputs Channels 8 to 11
WPUA = %00000000 'Select weak pull-ups
WPUB = %00000000 'Select weak pull-ups
ADCON0 = %10000001 'AD Module is ON, Channel 1
ADCON1 = %00000000 'AD control register
CM1CON0 = %00000000 'Comparator1 Module is OFF
CM2CON0 = %00000000 'Comparator2 Module is OFF
INTCON = %10100000 'INTerrupts CONtrol; GIE=1, T0IE=1
TRISA = %00000000 'Select Input/Output (0 to 5)
PORTA = %00000000 'Set High/Low (0 to 5)
TRISB = %00110000 'Select Input/Output (4 to 7)
PORTB = %00000000 'Set High/Low (4 to 7)
TRISC = %00000001 'Select Input/Output (0 to 7)
PORTC = %00000000 'Set High/Low (0 to 7)

'-------------------------------------------------------------------------------
' Defines
define OSC 8

DEFINE LCD_DREG PORTC 'LCD data port
DEFINE LCD_DBIT 4 'LCD data starting PORT.bit (0 or 4)
DEFINE LCD_RSREG PORTC 'LCD register select port
DEFINE LCD_RSBIT 3 'LCD register select bit
DEFINE LCD_EREG PORTC 'LCD enable port
DEFINE LCD_EBIT 2 'LCD enable bit
DEFINE LCD_BITS 4 'LCD bus size 4 or 8

DEFINE ADC_BITS 10 'Number of bits in ADCIN result

'-------------------------------------------------------------------------------
' Init display

' ELECTRONIC ASSEMBLY DOGM081 LCD display Mandatory settings
' See datasheet for circuitry changes by 5V or 3,3V operation
pause 1000 'Time to settle Vdd (THIS IS CRUCIAL!!!)
lcdout $FE, $29 'Function Set: 4 bits bus mode
lcdout $FE, $1C 'Bias set
lcdout $FE, $52 'Power control + Contrast (HiByte)(for 5V=$52 or 3,3V=55)
lcdout $FE, $69 'Follower control (5V=$69/3,3V=6D)
Lcdout $FE, $78 'Contrast (LowByte)

' Custom Characters
lcdout $FE,$28 'Function Set change - ONLY valid for ST7036 controller based LCDs
LCDOUT $FE,$40,$02,$06,$1A,$1A,$1A,$06,$02,$00 'Char 0 = Speaker
LCDOUT $FE,$48,$00,$0A,$0A,$00,$00,$11,$0E,$00 'Char 1 = Smile
LCDOUT $FE,$50,00,00,00,00,00,00,00,00 'Char 2
LCDOUT $FE,$58,14,27,17,17,17,17,31,00 'Char 3 = Battery 1/5 full
LCDOUT $FE,$60,14,27,17,17,17,31,31,00 'Char 4 = Battery 2/5 full
LCDOUT $FE,$68,14,27,17,17,31,31,31,00 'Char 5 = Battery 3/5 full
LCDOUT $FE,$70,14,27,17,31,31,31,31,00 'Char 6 = Battery 4/5 full
LCDOUT $FE,$78,14,31,31,31,31,31,31,00 'Char 7 = Battery 5/5 full
lcdout $FE,$29 'Function Set change

'-------------------------------------------------------------------------------
' Variables

CLEAR

SoftSwitch var PORTA.2
SoftSwitch = 1
Btn1xMinute var PORTB.4
Btn5xMinute var PORTB.5

'******* DEBUG ******
LED_Alarm var PORTB.6
LED_Alarm = 0
LED_RUN var PORTB.7
LED_RUN = 0
'******* DEBUG ******

Bat_Enable var PORTC.1
Bat_Enable = 0
Bat_Port var BYTE
Bat_Port = 4 'PORTC.0 - AN4
Bat_Level var byte 'for LCD character selection (3:7)
Bat_Level = 7
Bat_Value var word 'holds ADC value
Bat_Value = 0
Minutes var byte
minutes = 0
Seconds var byte
Seconds = 0
Ticks var byte
Ticks = 0
Dsp_Upd var bit 'Display Update Allowance
DSP_Upd = 1
Alarm var bit
Alarm = 0
Cnt_A var word
Cnt_a = 0
RUN var bit 'timer is running
RUN = 0
IdleCounter var byte 'counter that increments while timer is 00:00
IdleCounter = 0

'-------------------------------------------------------------------------------
' Start program


'******* DEBUG ******
TEST:
ADCIN 13, Bat_value
lcdout $FE,2,"B ",dec4 Bat_Value
GOTO TEST
'******* DEBUG ******

END



My question, in other words, is: how do I route the VP6 (0,6V Reference) to the ADCIN?

Ioannis
- 27th September 2015, 13:56
Hi Roger.

I am looking now the latest Data sheet (version F) of the chip and it seems that this chip supports 0,6 Volt reference only for the comparator. The ADC can be referenced internally byt the VCC or externaly on pin 18.

Sorry for the late detailed reply. It is my fault I did not check the data sheet earlier.

So in your case you have to use the internal reference to Vcc (that is 5V in your case), with ADCON0 set as it is now and read the input on your pin, which I suppose is PortC.0 with the

ADCIN 4,Bat_Value (Not 13 as in your program).

The other option you may have, is to use the comparator, and when the voltage of the divider trips under the reference, to have an interrupt, or just look for the comparator out if it is set. But you cannot have the exact battery value.

Ioannis

towlerg
- 27th September 2015, 15:21
this chip supports 0,6 Volt reference only for the comparator

Sorry, I don't think that is correct, or maybe I missed your point.

I have used 0.6v internal reference on several projects using the 690. And don't forget the original post was re. app note AN1072 which provides code for the 690.

George

Ioannis
- 27th September 2015, 17:13
OK, now I see how this works. Sorry I did not gave the proper attention to the AN1072.

It works in reverse. It does supply a 0,6 volts to the ADC input and the refererence is read from the Vdd supply.

Unfortunately this is NOT what Roger wants. He has a stable Vdd from his LDO regulator so his ADRES result will always be the same, no matter the battery condition.

Clever technique but not the one needed here...

Ioannis

flotulopex
- 27th September 2015, 17:17
I'll need to download the latest DS, mine is from 2007 :frown:

George, would you have a little piece of PICBASIC code about how to use the 0,6V reference please?

As a matter of fact, my AN1072 is from 2006 and there is no code example in there. And even if there would be some, it wouldn't be in PICBASIC anyway.

flotulopex
- 27th September 2015, 17:36
Thanks Ioannis. I just replied while you were sending your reply.

The first lines of the AN1072 say:

INTRODUCTION
This application note describes how to measure the voltage supplied to a PIC ® microcontroller, VDD . The device used in preparation of this application note was the PIC16F690. The ability to measure VDD lends itself to battery applications where VDD is likely to fall over time. In this application note, an example program is provided with routines to measure VDD.

THEORY OF OPERATION
Select Microchip PIC microcontrollers contain a 0.6V or 1.2V internal reference that is selectable as an input to
the ADC module. This provides a fixed reference to allow measurement of VDD . The PIC16F690 was chosen for this feature.


A:- I can't still find a code example in this AN.
B:- Can this AN be wrong?

Right; on MICROCHIP's website, I could find two ASM code examples....but I don't know machine language or I wouldn't probably be on this forum :wink:

But here they are (ZIPfile) so if somebody want's to have a look and "translate" the essential stuff in PICBASIC, it would be great.

In case I can't really use the 0,6 reference voltage, I plan to make my circuit looking like this:
8059



8058

Ioannis
- 27th September 2015, 17:40
Roger, for this to work you need to get rid of the LDO and feed a 4,5Volt battery pack to the PIC. That way you will measure the Vdd voltage in respect with the VP6 input to the ADC. There is no other way to do it.

Your configuration would be:



ADCON0=%10110101 ' Here we drive the 0,6 volts to the ADC
ADCON1=%00110000 ' I prefer to be sure to have FRC for the beginning at least
VRCON= %00010000 ' Enable the VP6 reference


Now if you want to measure the Vdd, just do this:



ADCON0.1=1
while ADCON0.1: wend
Bat_Value.Byte1=ADRESH:Bat_Value.Byte0=ADRESL


But remember, you have to drop the LDO and supply your circuit from the battery directly.

Ioannis

flotulopex
- 27th September 2015, 17:48
...you need to get rid of the LDO and feed a 4,5Volt battery pack to the PIC. That way you will measure the Vdd voltage in respect with the VP6 input to the ADC.

Thanks Ioannis; I now understand what you mean.

This morning, I tried to manually setup the ADC but it was always "failing" (= giving same value all time); you just explained why it didn't work ;)

I found an example on which I based my test code here (http://edeca.net/wp/electronics/measuring-pic-vdd-with-no-external-components-using-the-fvr/).

I'll give your example a try :)

flotulopex
- 28th September 2015, 06:52
...and here are the two code example files I was talking about in my post#43 ;-)

8060

towlerg
- 28th September 2015, 16:30
There is a post by Darrel re this but I can't find it. I don't have any PICBasic code to hand but this in Proton might help -



ADCON1 = %00100000 ' ADCS=010 Fosc/32 4usec
Symbol Go_Done = ADCON0.1
Symbol ADON = ADCON0.0
Symbol VP6EN = VRCON.4 ' 0.6V Reference Enable Bit

Dim Ad_Result As ADRESL.Word ' Convert the ADRESL register into a WORD variable
Dim VDD As Word


VP6EN = 1 ' Turn 0.6V reference ON
ADCON0 = %10110101 ' right justify, Vdd, select 0.6v ref, ADC on
DelayUS 100 ' Wait for sample/hold capacitors to charge and VP6 to settle
Go_Done = 1 ' Start conversion
While Go_Done = 1 : Wend ' Poll the GO_DONE flag for completion of conversion
ADCON0 = %10110100 ' right justify, Vdd, Select 0.6v ref, ADC off
VP6EN = 0 ' Turn 0.6V reference OFF
VDD = 6144/Ad_Result ' convert input reading to VDD voltage *VDD must be a Word
' 0.6 * 1024 = 614.4 - 6144 To get 1/10th

George

flotulopex
- 28th September 2015, 21:42
Finally YOU made it!!! :)

I just changed my circuit to power it directly from my variable power-supply and simulate the batterie's weakening.

@5VDC, my display shows a value of 135 and @4,2VDC (can't go lower or my display won't work anymore) I read 147.

So, except the particular init sequence for the LCD I use, the code example here under is working fine and should be quite standard.


' PIC 16F690 Fuses
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF

'-------------------------------------------------------------------------------
' Registers 76543210
OPTION_REG = %10000000 'OPTION register
ANSEL = %00000000 'Select analog inputs Channels 0 to 7
ANSELH = %00000000 'Select analog inputs Channels 8 to 11
WPUA = %00000000 'Select weak pull-ups
WPUB = %00000000 'Select weak pull-ups
ADCON0 = %00000000 'AD Module
ADCON1 = %00000000 'AD control register
CM1CON0 = %00000000 'Comparator1 Module
CM2CON0 = %00000000 'Comparator2 Module
INTCON = %00000000 'INTerrupts CONtrol
TRISA = %00000000 'Select Input/Output (0 to 5)
PORTA = %00000000 'Set High/Low (0 to 5)
TRISB = %00000000 'Select Input/Output (4 to 7)
PORTB = %00000000 'Set High/Low (4 to 7)
TRISC = %00000000 'Select Input/Output (0 to 7)
PORTC = %00000000 'Set High/Low (0 to 7)

'-------------------------------------------------------------------------------
' Defines
DEFINE OSC 8

DEFINE LCD_DREG PORTC 'LCD data port
DEFINE LCD_DBIT 4 'LCD data starting PORT.bit (0 or 4)
DEFINE LCD_RSREG PORTC 'LCD register select port
DEFINE LCD_RSBIT 3 'LCD register select bit
DEFINE LCD_EREG PORTC 'LCD enable port
DEFINE LCD_EBIT 2 'LCD enable bit
DEFINE LCD_BITS 4 'LCD bus size 4 or 8

DEFINE ADC_BITS 10 'Number of bits in ADCIN result

'-------------------------------------------------------------------------------
' Init display

' ELECTRONIC ASSEMBLY DOGM081 LCD display Mandatory settings
' See datasheet for circuitry changes by 5V or 3,3V operation
PAUSE 1000 'Time to settle Vdd (THIS IS CRUCIAL FOR THIS DISPLAY!!!)
LCDOUT $FE, $29 'Function Set: 4 bits bus mode
LCDOUT $FE, $1C 'Bias set
LCDOUT $FE, $52 'Power control + Contrast (HiByte)(for 5V=$52 or 3,3V=55)
LCDOUT $FE, $69 'Follower control (5V=$69/3,3V=6D)
LCDOUT $FE, $78 'Contrast (LowByte)

'-------------------------------------------------------------------------------
' Variables
Bat_Value var word 'holds ADC value
Bat_Value = 0

'-------------------------------------------------------------------------------
' Start program

MAIN:
ADCON0=%10110101 ' Here we drive the 0,6 volts to the ADC
'ADCON1=%00110000 ' I prefer to be sure to have FRC for the beginning at least
VRCON= %00010000 ' Enable the VP6 reference
ADCON0.1=1
WHILE ADCON0.1 : WEND
Bat_Value.HIGHBYTE = ADRESH : Bat_Value.LOWBYTE = ADRESL
LCDOUT $FE,2,DEC4 Bat_Value
PAUSE 1000
GOTO MAIN

END

Using the internal 0,6V reference:
- 0,8Vbatt difference = 12 value change
+ no external components

Using an external voltage divider:
+ 0,8Vbatt difference = 84 value change
- external components


Thanks a lot for all your help ;)

flotulopex
- 28th September 2015, 22:34
...and while testing things, here is something I just tried based on the code in my previous post using the ADCIN command:

' Start program

MAIN:
ADCON1 = %00110000 ' I prefer to be sure to have FRC for the beginning at least
VRCON = %00010000 ' Enable the VP6 reference
ADCIN 13, Bat_Value ' ADCON0 = %10110100 where bits 5:2 are the 0,6V reference's channel address (1101 = 13)
LCDOUT $FE,2,DEC5 Bat_Value
PAUSE 1000
GOTO MAIN

END

The results are @5VDC I read 8640 and 9790 @4,2VDC (?!) but it looks to work somehow.

towlerg
- 29th September 2015, 00:32
The ADC is 10 bit, the largest value you can read is 1023 (10 1's). BTW check to table in the ADC section re. recommended ADC clock source, at 8 Mhz use Fosc/16 or Fosc/32. See note re using FRC as a clock source above 1Mhz.

You seem to have missed out the conversion to 0v1.

George

Ioannis
- 29th September 2015, 09:09
Are you sure that you still have right justification? Maybe you have accidentaly set the ADCON.7 to zero?

In general the bigger number for lower voltage is correct. Since you have the same 0,6 volts at the ADC input, lowering the Vref (through Vdd) will give bigger ADC result.

But not more than 1023 as George stated.

Ioannis

flotulopex
- 30th September 2015, 16:23
Thanks Ioannis and George,

Here is the corected and 100% working code example using ADCIN:
' PIC 16F690 Fuses
@ __config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_HS_OSC &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF

'-------------------------------------------------------------------------------
' Registers 76543210
OPTION_REG = %10000000 'OPTION register
ANSEL = %00000000 'Select analog inputs Channels 0 to 7
ANSELH = %00000000 'Select analog inputs Channels 8 to 11
WPUA = %00000000 'Select weak pull-ups
WPUB = %00000000 'Select weak pull-ups
ADCON0 = %00000000 'AD Module
ADCON1 = %00000000 'AD control register
CM1CON0 = %00000000 'Comparator1 Module
CM2CON0 = %00000000 'Comparator2 Module
INTCON = %00000000 'INTerrupts CONtrol
TRISA = %00000000 'Select Input/Output (0 to 5)
PORTA = %00000000 'Set High/Low (0 to 5)
TRISB = %00000000 'Select Input/Output (4 to 7)
PORTB = %00000000 'Set High/Low (4 to 7)
TRISC = %00000000 'Select Input/Output (0 to 7)
PORTC = %00000000 'Set High/Low (0 to 7)

'-------------------------------------------------------------------------------
' Defines
DEFINE OSC 8

DEFINE LCD_DREG PORTC 'LCD data port
DEFINE LCD_DBIT 4 'LCD data starting PORT.bit (0 or 4)
DEFINE LCD_RSREG PORTC 'LCD register select port
DEFINE LCD_RSBIT 3 'LCD register select bit
DEFINE LCD_EREG PORTC 'LCD enable port
DEFINE LCD_EBIT 2 'LCD enable bit
DEFINE LCD_BITS 4 'LCD bus size 4 or 8

DEFINE ADC_BITS 10 'Number of bits in ADCIN result

'-------------------------------------------------------------------------------
' Init display

' ELECTRONIC ASSEMBLY DOGM081 LCD display Mandatory settings
' See datasheet for circuitry changes by 5V or 3,3V operation
PAUSE 1000 'Time to settle Vdd (THIS IS CRUCIAL FOR THIS DISPLAY!!!)
LCDOUT $FE, $29 'Function Set: 4 bits bus mode
LCDOUT $FE, $1C 'Bias set
LCDOUT $FE, $52 'Power control + Contrast (HiByte)(for 5V=$52 or 3,3V=55)
LCDOUT $FE, $69 'Follower control (5V=$69/3,3V=6D)
LCDOUT $FE, $78 'Contrast (LowByte)

'-------------------------------------------------------------------------------
' Variables
Bat_Value var word 'holds ADC value
Bat_Value = 0

'-------------------------------------------------------------------------------
' Start program

MAIN:
ADCON0 = %10000000 ' Here we drive the 0,6 volts to the ADC
VRCON = %00010000 ' Enable the VP6 reference
ADCIN 13, Bat_Value ' Select the VP6 channel's address ADCON0 = %xx1101xx
Bat_Value.HIGHBYTE = ADRESH : Bat_Value.LOWBYTE = ADRESL
LCDOUT $FE,2,DEC4 Bat_Value
PAUSE 1000
GOTO MAIN

END

towlerg
- 30th September 2015, 17:10
Did you see how to convert he ADC count in Bat_Value to volts?

I see you are still not using a recommended value for ADCS in ADCON1.

George

flotulopex
- 30th September 2015, 21:15
Yes George,

For any reason, either ADCON1.ADCS setting will affect the results.

For those interested in the maths (where "2n" is 1024 because I use 10bits in ADC):
8065

Regarding my results and comparing them to the table A-1 (Appendix A: AC Result Table in AN1072), something must be wrong.

A 135 ADC result corresponds to 4,52V and 147 to 4,16V (?!).

Grrrrrr! I didn't notice I hadn't removed the voltage regulator on my breadboard. My PICkit2 programmer delivers 4,78VDC (even if it shows 5V in the "VDD PICkit2" field) so the "new" ADC values I get now seem to be much closer to what they are supposed to be "on the paper".

For 4,82V displayed on my FLUKE87, the ADC result is now 127 (exact as table A-1) and @4,31V I get 142 (exact as table A-1).

((1024 - 1) / 4,82) * 0,6 = 127 and ((1024 - 1) / 4,31) * 0,6 = 142

Ioannis
- 30th September 2015, 21:50
Glad you did it Roger! Bravo!

Ioannis

towlerg
- 30th September 2015, 23:13
For any reason, either ADCON1.ADCS setting will affect the results.

I don't know the internals of ADCIN, but unless it sets the ADCS bits to something else, you're ADC clock source will be Fosc/2 which at 8Mhz will give a Tad of 250ns. Fosc/16 or Fosc/32 are recommended.

George

Ioannis
- 1st October 2015, 09:52
George, If you do not want any headaches, just use the Frc. The internal 500Khz clock is good enough for most applications.

Plus, you do not worry for any timing violations.

Ioannis