Darrell, first of all thanks so much for your input. I really like your algorithm much better than the Microchip AN869 approach to a PLVD because it is simpler and also doesn't require an additional Resistor and Capictor.
I have implemented your algorithm into the code attached below and tried to test it using the 16F690 in a PICKIT2 LPDV board. It compiles and programs the board/16F690 with no problem, but the testing shows there must be a problem in the code, which I will explain.
To ensure accurate testing I calibrated my PICKIT2 per their instructions with a voltmeter and made sure it puts out exactly 4.8 volts to the target ch when 4.8 volts is selected in the PICKIT2 Voltage selector. I have attached a picture of the PICKIT2 screen during the test for reference.
Notice that I have inserted some WRITE statements in the code to enable me to READ the different variables at certain points in the code execution.
These read values are shown in HEX in the EEPROM memory locations at the bottom of the PICKIT2 screen:
Address 11 is ADINPUT = hex A0 = decimal 160
Address 13/14 is VDD = hex 0027 = decimal 38; which is equivalent to the code calculation 6138/ADINPUT = 6138/160 = 38.36 => 3.84 volts.
Address 17 is Vthr = hex 2F = decimal 47; which is as it should be based on the constant value being set as 47 in the variable declarations.
However, this testing shows the calculated VDD to be 3.84 volts when the voltmeter on the calibrated PICKIT2 input to the VDD on the chip is showing exactly 4.80 volts. This then causes the IF-THEN statement to incorrectly trigger the Low Voltage warning subroutine that blinks the LED. I have double checked my code and can't find why the A/D is measuring the wrong value. In fact, to equal the calibrated 4.8 volt input the ADINPUT reading by the A/D would have to be decimal 127 instead of the measured 160. Can you see any mistakes in my code that would cause this measurement error? If you have a PICKIT2 with the LPDV board you should be able to use this code to replicate my testing.
One thing in your algorithm I didn't quite understand was where the value 6138 comes from in the calculation 6138/ADINPUT that converts the A/D measurement to voltage. Can you please explain?
Code:'**************************************************************** '* Name : DT_VoltageMonitor.BAS * '* Author : [select VIEW...EDITOR OPTIONS] * '* Notice : Copyright (c) 2009 * '* : All Rights Reserved LodeStar Assoc. Inc. * '* Date : 7/21/2009 * '* Version : 1.0 * '* Size : 226 words * '* Notes : Adapted from Darrell Taylor's code in order to * '* : monitor a battery pack input from 4ea NiMH AA * '* : batteries that is normall fully charged at 4.8vdc.* '**************************************************************** ' ---------[ Device Declaration & CONFIG settings]----------------------------- ASM ; 16F690 ifdef PM_USED ; For PM assembler device INTRC_OSC_NOCLKOUT ; Oscillator Selection device FCMEN_OFF ; Fail-Safe Clock Monitor device IESO_OFF ; Internal External Switchover device BOD_OFF ; Brown-out Detect device CPD_OFF ; Data Code Protection device PROTECT_OFF ; Code Protection device MCLR_OFF ; Master Clear Reset device PWRT_ON ; Power-up Timer device WDT_OFF ; Watchdog Timer else ; For MPASM assembler cfg= _INTRC_OSC_NOCLKOUT ; Oscillator Selection cfg=cfg& _FCMEN_OFF ; Fail-Safe Clock Monitor cfg=cfg& _IESO_OFF ; Internal External Switchover cfg=cfg& _BOR_OFF ; Brown-out Reset cfg=cfg& _CPD_OFF ; Data Code Protection cfg=cfg& _CP_OFF ; Code Protection cfg=cfg& _MCLRE_OFF ; Master Clear Reset cfg=cfg& _PWRTE_ON ; Power-up Timer cfg=cfg& _WDT_OFF ; Watchdog Timer __CONFIG cfg endif ENDASM ' The above config is inteded to set CONFIG = %0000000000000000 for hex 00C4 or ' FCMEN off(0), IESO off(0), BOR off(00), CPD off(1), CP off(1), /MCLR is ' digital input(0), /PWRTE on(0), WDTE off(0), FOSC<2:0> (100). ' -----------------------[ Set Registers & Ports ]----------------------------- ' Set ADCON registers for A/D converter ADCON0 = %10110101 ' ADCON0.7 = ADFM = 1 ' 10-bit result is right justified ' ADCON0.6 = VCFG = 0 ' Set VREF+ to VDD ' CHS<3:0> = 1101 ' Select 0.6V Ref channel ADCON1 = %00110000 ' Select FRC as A/D conversion clock source ' Set FOSC=1MHz to stay inside recommended TAD range when not in SLEEP mode OSCCON = %01000001 ' Set ANSEL register to make RA1 analog input ANSEL= %11110011 ' Set PortA to Analog I/O to save power during Sleep but ' leave Bits 2 & 3 as digital for RA2 and RA3 interrupts ANSELH= %11111111 ' Analog module enabled to save power during Sleep DEFine ADC_BITS 10 ' -----------------[ Declare Variables & Aliases ]----------------------------- led2 VAR PORTC.1 ' Set RC1 as LED indicator of low battery condition ADINPUT VAR WORD ' Stores VP6 value as sampled by ADC VDD VAR WORD ' Stores VDD value as converted from ADINPUT Vthr CON 47 ' Set threshold (4.7v) to trigger low voltage warning b0 VAr vdd.byte1 ' LSB of VDD when right justified b1 var VDD.Byte0 ' MSB of VDD when right justified Main: VRCON.4 = 1 ' Turn 0.6V reference ON PAUSEUS 100 ' Allow VP6 to settle ADCIN 15,ADINPUT ' Get VP6 analog reading (10-bit) VRCON.4 = 0 ' Turn 0.6V reference OFF WRITE 11,ADINPUT VDD = 6138/ADINPUT ' convert input reading to VDD voltage ' VDD now holds the measured VDD voltage * 10 (i.e., 3.4V = 34) ' The formula is the same for any VDD voltage. ' Assume normal VDD = +4.8vdc direct from fully charged battery pack input WRITE 13,b0 ' Remove comments on Write statements for test only WRITE 14,b1 Write 17,Vthr IF VDD < Vthr THEN GOSUB LowVoltage ' if VDD less than 4.7v EndIF GOTO Main '------------------------------Subroutines------------------------------------- LowVoltage: ' If Battery is low..flash low battery monitor light HIGH led2 PAUSE 125 Low led2 Pause 500 RETURN END




Bookmarks