RSS

My Custom made LC meter

25 Jun

An “improved” inductance / capacitance meter by Abhishek.Actually, it works much the same as the original.

It differs from the original in that:

  • A 16F628 PIC is used. This has internal comparator, which means the LM311 is no longer needed.
  • Software calibration is used. The finished meter can be calibrated against “any” accurate capacitor within the range 100pF to about 10000pF.
  • A PC Board layout is available (see below).

Special Components.

  • No particularly accurate components are required, except for one (or more) accurately known “external” capacitors used to calibrate the meter.
  • The two 1000pF capacitors should be fairly good quality. Polystyrene are preferred. MKT are fine. Greencaps tend to drift in value too much. Avoid ceramic capacitors. Some of these can have high losses (and it is hard to tell).
  • The two 10uF capacitors in the oscillator should be tantalum (for low series resistance/inductance).
  • The 4MHz crystal should be a genuine 4.000MHz one, not something approximate to 4MHz. Every 1% error in crystal frequency adds 2% error to the indicated inductance value.
  • The relay should be a low current one. The PIC can only provide about 30mA of drive current.
  • Don’t forget the “catch” diode across the relay coil!

 

Calibration:

  1. Check that you have put all the components in the right places.
  2. Check that you have soldered every lead.
  3. Double check the PIC orientation, the diode and the 7805.
  4. Don’t forget – the PIC (as purchased) isn’t programmed. You gotta load the LC Meter code into it before it will work.
  5. Apply power carefully. If possible, use a variable regulated supply for the first try. Measure the supply current while gradually increasing the voltage. The current should be below 20mA. The prototype drew just 8mA. If you see nothing on the display and everything else checks out OK, try adjusting the Contrast trimpot. If it is set too far off, you will see nothing. The display should briefly show the word Calibrating, then C=0.0pF (or some other capacitance up to +/- 10pF ).
  6. Allow several minutes “warm-up”, then press the “zero” button to force a re-calibration. The display should now show C=0.0pF.
  7. Connect your “standard” capacitor. The LC meter should read somewhere near its value (with up to +/- 10% error).
  8. To raise the indicated capacitance, join the links marked “4” on the diagram below. To lower the indicated capacitance, join the links marked “3” on the diagram below. When the indicated value is “close enough” to the standard, remove the link. The PIC will remember the calibration. You can repeat this as many times as you like (up to 10,000,000 times I think before you wear out the PIC).
  9. If the meter misbehaves, you can use the links “1” & “2” to check the oscillator frequency. Apply link “2” to check the free running frequency “F1” of the oscillator. This should be shown as 00050000 +/- 10%. If this reading is too high (near 00065535), the meter may go into “numerical overflow” and give you an error message. If the reading is too low (say below 00040000), you will lose some accuracy. Apply link “1” to check the “calibration” frequency “F2”. This should be near 71% +/- 5% of the “F1” reading that you get by applying link “2”.
  10. Experts may like to adjust the inductor value to raise F1 to near 00060000 to obtain maximum resolution from the meter. An “L” value of 82uH is preferred instead of the specified 100uH (but you can’t buy 82uH inductors in Bendigo).
  11. If the meter shows near 00000000 for F1 and or F2, then recheck the wiring around the L/C switch, ‘cos it sounds like your oscillator has stopped.
  12. The Inductance measuring function is automatically calibrated when you calibrate the capacitance function. All the testing required is to check that the meter can be “zeroed” with the terminals shorted together.

 

  1. The Code File:

;*******************************************************************
;
;    Inductance & Capacitance Meter with Software calibration
;
;*******************************************************************
;
;    First, let us choose our weapon – a 16F628
;
;*******************************************************************
;
; LC002    – THIS ONE WORKS FINE WITH A WELL BEHAVED DISPLAY
;
;    Deleted  CpyBin subroutine and one call to it
;
;    Modified B2_BCD to take its input directly from <AARGB0,1,2>
;
;    Modified “oscillator test” so it copies F3   to <AARGB0,1,2>
;
;    Fixed Get_Lcal so it gets the correct number
;
;    Minor adjustment to MS100 timing to correct frequency display
;
;    Check for oscillator too slow when measuring L or C.
;
;
;*******************************************************************
;
; LC003    – Optimised / Modified to handle “bad” displays
;
;    Removed duplicated code in DATS subroutine
;
;    Added code to fix crook display (select by jumper on B4 – 10)
;
;    Optimised L & C formatting code
;
;    Optimised “Display” subroutine
;
;    Cleaned up LCDINIT
;
;
;*******************************************************************
;
; LC004 – Deleted timer Interrupt Service Routine
;
;    Modified way oscillator “out of range” condition is detected
;
;
;*******************************************************************
;
; LC628 – LC004 code ported to 16F628 by Egbert Jarings PA0EJH.
;    Mem starts now at 0x20
;    InitIO modified , 628 PortA start’s up in Analog Mode
;    So changed to Digital Mode (CMCON)
;
;    Display’s “Calibrating” to fill up dead Display time
;    when first Powerd Up.
;
;    Changed pmsg Routine, EEADR  trick  wont work with 628,
;    PCL was always 0x00 so restart occurs. EEADR is now Etemp.
;
;    Also changed EEADR in FP routine to Etemp
;
;    Bad Display isn’t bad at all, its a Hitachi HD44780, as
;    80% of all Display’s are. Adress as 2 Lines x 8 Char.
;    So LCDINIT modified for 2 x 8 Display’s. (0x28 added)
;
;*******************************************************************
;
; LC005 – Cosmetic rewrite of RAM allocation from LC004
;
;    No change to address of anything – I hope
;    Identified unused RAM & marked for later removal.
;
;
;*******************************************************************
;
; LC006 – Merge LC005 and LC628
;
;    All “#ifdef” F628 parts by Egbert Jarings PA0EJH.
;    (or derived from his good work)
;
;    Cleaned up RAM allocation.
;
;    Added message re: processor type, just to verify selection
;
;    Included extra initialisation (2 line) command by PA0EJH
;
;*******************************************************************
;
; lc007    Changed strings to EEPROM (it’s not used for anything else)
;
;    Added “error collector” code to catch “all” FP errors
;
;       Addded macros
;
;
;*******************************************************************
;
; LC_swcal.000
;    Changed to use only F628 processor
;    Used internal comparator of F628 in place of LM311
;    Switched relay directly by digital I/O
;    Implemented software calibration via constant in EEPROM
;    Re-allocated most I/O pins
;    Added output munger for LCD connections (easy to re-allocate)
;
;
;*******************************************************************
;o—–o—–o—–o—–o—–o—–o—–o—–o—–o—–o—–o
;*******************************************************************
;
;    Some frequently used code fragments
;    Use macros to make mistreaks consistently.
;
;——————————————————————-
;    Select Register Bank 0

bank0    macro
    errorlevel    +302        ; Re-enable bank warning
    bcf        STATUS,RP0    ; Select Bank 0
    endm

;——————————————————————-
;    Select Register Bank 1

bank1    macro
    bsf        STATUS,RP0    ; Select Bank 1
    errorlevel    -302        ; disable warning
    endm

;——————————————————————-
;    Swap bytes in register file via W

swap    macro    this,that

    movf    this,w        ; get this
    xorwf    that,f        ; Swap using Microchip
    xorwf    that,w        ; Tips’n Tricks
    xorwf    that,f        ; #18
    movwf    this

    endm

;——————————————————————-
;    Copy bytes in register file via W

copy    macro    from,to

    MOVF    from,W
    MOVWF    to

    endm

;*******************************************************************
;
;    CPU configuration
;

    MESSG        “Processor = 16F628”
    processor    16f628
    include        <p16f628.inc>
    __CONFIG        _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC & _BODEN_ON & _LVP_OFF

;**********************************************************
;
;    I/O Assignments.
;

#define    LCD0    PORTB,3
#define    LCD1    PORTB,2
#define    LCD2    PORTB,1
#define    LCD3    PORTB,0
#define    ENA    PORTB,4        ; Display “E”
#define    RS    PORTB,5        ; Display “RS”
#define    functn    PORTB,6        ; 0 = “Inductor”
#define relay    PORTB,7        ; Switches Ccal

;*******************************************************************
;
;    file register declarations: uses only registers in bank0
;    bank 0 file registers begin at 0x0c in the 16F84
;    and at 0x20 in the 16F628
;
;*******************************************************************

    cblock    0x20
;
;       Floating Point Stack and other locations used by FP.TXT
;
;    FP Stack: TOS    A =     AEXP:AARGB0:AARGB1:AARGB3:AARGB4
;            B =     BEXP:BARGB0:BARGB1:BARGB2
;            C =     CEXP:CARGB0:CARGB1

    AARGB4
    AARGB3
    AARGB2
    AARGB1
    AARGB0
    AEXP            ; 8 bit biased exponent for argument A
    SIGN            ; save location for sign in MSB

    FPFLAGS            ; floating point library exception flags
    
    BARGB2
    BARGB1
    BARGB0
    BEXP            ; 8 bit biased exponent for argument B

    TEMPB3            ; 1 Unused byte
    TEMPB2            ; 1 Unused byte
    TEMPB1            ; Used
    TEMPB0            ; 1 Unused byte

    CARGB1
    CARGB0            ; most significant byte of argument C
    CEXP            ; 8 bit biased exponent for argument C

;
;    “Main” Program Storage
;
 
    COUNT            ; Bin to BCD convert (bit count)
    cnt            ;                    (BCD BYTES)

    CHR

    F1:2
    F2:2
    F3:2
    
    bcd:4            ; BCD, MSD first

    TabStop            ; Used to fix bad displays.
    TabTemp

    FPE            ; Collect FP errors in here
    
    R_sign            ; Holds “+” or ” ” (sign)

    EEflag:1        ; Cal adjust flag
    
    endc

    cblock    0x70        ; Common RAM

    cal_t:2            ; Ccal temporary value

    PB_data:1        ; LCD output munger temp
    
    links:1            ; User test links copy

    COUNT1            ; Used by delay routines
                ; and “prescaler flush”
    COUNT2            ; Timing (100ms)

    endc

EXP    equ    AEXP        ; Used by FP.TXT
TEMP    equ    TEMPB0
;AARG    equ    AARGB0        ; Unused
;BARG    equ    BARGB0        ; Unused
;CARG    equ    CARGB0        ; Unused

;*******************************************************************
;
;       GENERAL MATH LIBRARY DEFINITIONS
;
;
;    define assembler constants

B0        equ    0
B1        equ    1
B2        equ    2
B3        equ    3
B4        equ    4
B5        equ    5
B6        equ    6
B7        equ    7

MSB        equ    7
LSB        equ    0

;     STATUS bit definitions

#define    _C    STATUS,0
#define    _Z    STATUS,2

;*******************************************************************
;
;       FLOATING POINT literal constants
;

EXPBIAS         equ     D’127′

;
;       floating point library exception flags
;

IOV             equ     0       ; bit0 = integer overflow flag

FOV             equ     1       ; bit1 = floating point overflow flag

FUN             equ     2       ; bit2 = floating point underflow flag

FDZ             equ     3       ; bit3 = floating point divide by zero flag

NAN        equ    4    ; bit4 = not-a-number exception flag

DOM        equ    5    ; bit5 = domain error exception flag

RND             equ     6       ; bit6 = floating point rounding flag, 0 = truncation
                                ; 1 = unbiased rounding to nearest LSB

SAT             equ     7       ; bit7 = floating point saturate flag, 0 = terminate on
                                ; exception without saturation, 1 = terminate on
                                ; exception with saturation to appropriate value

;**********************************************************
;
;    Motorola syntax branches
;

#define    beq    bz
#define    BEQ    bz
#define    BNE    bnz
#define    bne    bnz

#define    BCC    bnc
#define    bcc    bnc
#define    BCS    bc
#define    bcs    bc

#define    BRA    goto
#define    bra    goto

;**********************************************************
;
;    Begin Executable Stuff(tm)
;

    org    0

GO    clrwdt            ; 0 << Reset
    call    InitIO
    bcf    relay        ; Remove Ccal

;**********************************************************
;
;    Main Program
;

START    CALL    LCDINIT         ; INITIALIZE LCD MODULE    
    call    EE_RD        ; Retrieve CCal integer value

cmdloop    call    HOME

;
;    “Zero” the meter.
;

Chk4Z    MOVLW   Calibr-0x2100    ; Display’s ” Calibrating ”
    call    pmsg        ; to entertain the punters

    call    Measure        ; Dummy Run to stabilise oscillator.
    call    MS200

    call    Measure        ; Get freq in F3

    copy    F3+0,F1+0    ; Copy F3 to F1
    copy    F3+1,F1+1

    bsf    relay        ; Add standard capacitor
    call    MS200

    call    Measure        ; Get freq in F3

    copy    F3+0,F2+0    ; Copy F3 to F2
    copy    F3+1,F2+1
    
    bcf    relay        ; Remove standard capacitor
    call    MS200

    call    Measure        ; Dummy Run to stabilise oscillator.

;
;    Now we resume our regular pogrom
;    Read state of user test links on LCD bus
;

M_F3    bank1            ; PORTB:-
    movlw    b’01001111′    ; LCD data bits to read
    movwf    TRISB        ; 1 = input
    bank0            ; 0 = output

    call    MS2        ; Settling time
    copy    PORTB,links

    bank1
    movlw    b’01000000′    ; restore data direction
    movwf    TRISB        ; 1 = input
    bank0            ; 0 = output

;—————————————————————
;
;    Take a break from regular duties to do something interesting
;
    btfss    links,0        ; Raise Ccal value
    goto    cal_up

    btfss    links,1        ; Lower Ccal value
    goto    cal_dn

    btfss    links,2        ; Test osc without Ccal
    goto    osc1

    btfss    links,3        ; Test osc with Ccal
    goto    osc2

;
;    None of the above
;

    bcf    relay        ; In case of osc test
    btfss    EEflag,0    ; Time to save Ccal value?
    goto    cont        ; No. Back to work
    
    bcf    EEflag,0    ; To say we have done it
    call    EE_WR        ; So, we better save it
    goto    cont        ; Hi Ho, its off to work I go

;
;    Add +10 to cal_t:2
;

cal_up    bsf    EEflag,0    ; Say “we’re adjusting”
    movlw    0x0a        ; +10
    addwf    cal_t+1,f
    bcc    cont
    
    incf    cal_t+0,f
    goto cont

;
;    Add -10 to cal_t:2
;

cal_dn    bsf    EEflag,0    ; Say “we’re adjusting”
    movlw    0xf6        ; -10
    addwf    cal_t+1,f
    bcc    hi_byte
    
    incf    cal_t+0,f

hi_byte    movlw    0xff
    addwf    cal_t+0,f
    goto    cont        

;
;    Measure & display osc freq for initial setup
;

osc2    bsf    relay        ; Add Ccal
    
osc1    call    HOME
    call    Measure        ; Measure Local Osc Freq.
    call    CLEAR

    btfss    INTCON,T0IF    ; Set = Counter overflow?
    goto    Do_Disp

    MOVLW    ovr-0x2100    ; Over-range message
    call    pmsg
    goto    M_F3
    
Do_Disp    clrf    AARGB0        ; Copy to 24 bit number
    movf    F3,W        ; in AARGB0, 1, 2
    movwf    AARGB1        ; for display
    movf    F3+1,W
    movwf    AARGB2

    call    Display
    goto    M_F3

;—————————————————————

cont    call    HOME
    call    MS200
    call    Measure        ; Measure F3 & leave it there

    movf    F3,w        ; test for “too low” frequency
    beq    OORange        ; F < 2560Hz ?
    
    btfss    INTCON,T0IF    ; test for “too high” frequency
    goto    OK2GO        ; F > 655359Hz ?

OORange    MOVLW    ovr-0x2100    ; Over/Under range message
    call    pmsg
    
    goto    M_F3

;
;    Precompute major bracketed terms cos
;    we need ’em both for all calculations
;

OK2GO    clrf    FPE        ; Declare “error free”
    call    F1_F2
    call    F1_F3

;
;    See what mode we are in
;

    btfss    functn        ; 0=Inductor
    goto    Do_Ind

;
;    OK, we’ve been told it’s a capacitor
;

Do_Cap    call    C_calc
    movf    FPE,f        ; Any FP errors?
    bne    complain
    
    movlw    Cintro-0x2100    ; C =
    call    pmsg

    call    C_disp
    goto    M_F3

;
;    Now, they reckon it’s a @#$*! inductor
;

Do_Ind    call    L_calc
    movf    FPE,f        ; Any FP errors?
    bne    complain
    
    movlw    Lintro-0x2100    ; L =
    call    pmsg

    call    L_disp
    goto    M_F3

;
;    Got a Floating Point Error of some sort
;

complain    movlw    ovr-0x2100    ; Over Range
        call    pmsg
    
        goto    M_F3

;**********************************************************
;
;    Print String addressed by W
;    Note: Strings are in EEPROM
;    We do a lotta bank switching here.

pmsg    bank1
    movwf    EEADR        ; pointer

pm1    BSF     EECON1,RD       ; EE Read
        MOVF    EEDATA,W        ; W = EEDATA, affects Z bit
        bank0            ; Does not change Z bit
 
    btfsc    STATUS,Z    ; ZERO = All done
    return            ; so quit

    call    DATS        ; Byte -> display

    bank1
    INCF    EEADR,F         ; bump address
    goto    pm1

;**********************************************************
;
;    Delay for 2ms (untrimmed)
;

MS2    MOVLW    0xFD        ; DELAY 2ms
    MOVWF    COUNT1

    MOVLW    0x66
    MOVWF    COUNT2

    goto    L3        

;**********************************************************
;
;    Delay for about 200ms or 300ms (untrimmed)
;

MS300    call    MS100

MS200    call    MS100

;**********************************************************
;
;    Delay for about 100ms
;

MS100    MOVLW    0x7e        ; Count up
    MOVWF    COUNT1        ; to roll-over

    MOVLW    0x20        ; was 0x19, then 0x25, then 1f
    MOVWF    COUNT2            

L3    INCFSZ    COUNT2,F
    GOTO    L3

    INCFSZ    COUNT1,F
    GOTO    L3

    RETLW    0

;**********************************************************
;
;    Put a BCD nybble to display
;

PutNyb    ANDLW    0x0F        ; MASK OFF OTHER PACKED BCD DIGIT
    ADDLW    0x30        ; Convert BIN to ASCII

;**********************************************************
;
;    Put a byte to display
;

DATS    decf    TabStop,F    ; Time to tickle bad display?
    bne    DAT1        ; Not yet
    
    movwf    TabTemp        ; Save character
    
;    btfss    FIXIT        ; Check if we got a crook one.
;    CALL    LINE2        ; Skip this if good

    movf    TabTemp,W    ; Restore character

DAT1    BSF    RS        ; SELECT DATA REGISTER
CM    MOVWF    CHR        ; STORE CHAR TO DISPLAY
    SWAPF    CHR,W        ; SWAP UPPER AND LOWER NIBBLES (4 BIT MODE)

    call    PB_dly

    MOVF    CHR,W        ; GET CHAR AGAIN

;**********************************************************
;
;    Put 4 bits to LCD & wait (untrimmed)
;

PB_dly    movwf    PB_data        ; Save nybble

    btfss    PB_data,0    ; copy LSbit
    bcf    LCD0
    btfsc    PB_data,0
    bsf    LCD0
    
    btfss    PB_data,1
    bcf    LCD1
    btfsc    PB_data,1
    bsf    LCD1
    
    btfss    PB_data,2
    bcf    LCD2
    btfsc    PB_data,2
    bsf    LCD2
    
    btfss    PB_data,3    ; copy MSbit
    bcf    LCD3
    btfsc    PB_data,3
    bsf    LCD3
    
    BSF    ENA        ; ENA HIGH
    NOP            
    BCF    ENA        ; ENA LOW

;    goto    D200us        ; Fall into DELAY subroutine

;**********************************************************
;
;    Delay for 200us (untrimmed)
;

D200us    MOVLW    0x42        ; DELAY  200us
    MOVWF    COUNT1    
NXT5    DECFSZ    COUNT1,F
    GOTO    NXT5    
    RETLW    0

;******************************************************************
;
;    Convert 24-bit binary number at <AARGB0,1,2> into a bcd number
;    at <bcd>. Uses Mike Keitz’s procedure for handling bcd
;    adjust; Modified Microchip AN526 for 24-bits.
;

B2_BCD

b2bcd   movlw   .24        ; 24-bits
        movwf   COUNT        ; make cycle counter

        clrf    bcd+0        ; clear result area
        clrf    bcd+1
        clrf    bcd+2
        clrf    bcd+3
        
b2bcd2  movlw   bcd         ; make pointer
        movwf   FSR
        movlw   .4
        movwf   cnt

; Mike’s routine:

b2bcd3  movlw   0x33            
        addwf   INDF,f          ; add to both nybbles
        btfsc   INDF,3          ; test if low result > 7
        andlw   0xf0            ; low result >7 so take the 3 out
        btfsc   INDF,7          ; test if high result > 7
        andlw   0x0f            ; high result > 7 so ok
        subwf   INDF,f          ; any results <= 7, subtract back
        incf    FSR,f           ; point to next
        decfsz  cnt,f
        goto    b2bcd3
        
        rlf     AARGB2,f    ; get another bit
        rlf     AARGB1,f
        rlf     AARGB0,f

        rlf     bcd+3,f         ; put it into bcd
        rlf     bcd+2,f
        rlf     bcd+1,f
        rlf     bcd+0,f

        decfsz  COUNT,f         ; all done?
        goto    b2bcd2          ; no, loop
        return                  ; yes

;*********** INITIALISE LCD MODULE 4 BIT MODE ***********************

LCDINIT CALL    MS100        ; WAIT FOR LCD MODULE HARDWARE RESET
    BCF    RS        ; REGISTER SELECT LOW
    BCF    ENA        ; ENABLE LINE LOW
    
    MOVLW    0x03        ; 1
    call    PB_dly
    CALL    MS100        ; WAIT FOR DISPLAY TO CATCH UP

    MOVLW    0x03        ; 2
    call    PB_dly

    MOVLW    0x03        ; 3
    call    PB_dly

    MOVLW    0x02        ; Fn set 4 bits
    call    PB_dly
    
    MOVLW    0x0C        ; 0x0C DISPLAY ON
    CALL    ST200us

    MOVLW    0x28        ; DISPLAY 2 Line , 5×7 Dot’s
    CALL    ST200us        ; New in LC628/LC006 version
    
    MOVLW    0x06        ; 0x06 ENTRY MODE SET
    CALL    ST200us        ; Fall into CLEAR

;************ CLEAR DISPLAY ***************************

CLEAR    MOVLW    0x01        ; CLEAR DISPLAY
    goto    Home2        ; LONGER DELAY NEEDED WHEN CLEARING DISPLAY

;*********** MOVE TO HOME *****************************

HOME    movlw    0x09        ; Count characters
    movwf    TabStop        ; before tickling display.

    MOVLW    0x02        ; HOME DISPLAY
Home2    CALL    STROBE
    goto    MS2

;**********************************************************
;
;    SENDS DATA TO LCD DISPLAY MODULE (4 BIT MODE)    
;

STROBE    BCF    RS        ; SELECT COMMAND REGISTER
    GOTO    CM

;************ MOVE TO START OF LINE 2 *****************

LINE2    MOVLW    0xC0        ; ADDRESS FOR SECOND LINE OF DISPLAY

ST200us    CALL    STROBE
    goto    D200us

;********************************************************************
;       Initialise Input & Output devices
;********************************************************************

InitIO    movlw    b’00000110′
    movwf    CMCON            ; Select Comp mode

    bank1

    movlw    b’00000000′
    movwf    VRCON            ; Set Volt ref mode to OFF

    movlw    0x37        ; Option register
    movwf    OPTION_REG    ; Port B weak pull-up enabled
                ; INTDEG Don’t care
                ; Count RA4/T0CKI
                ; Count on falling edge
                ; Prescale Timer/counter
                ; divide Timer/counter by 256

                ; PORTA:-
    movlw    b’11110111′    ; initialise data direction
                ; 1 = input
                ; 0 = output
                                ;
    movwf    TRISA        ; PORTA<0>   = comp1 “-” in
                ; PORTA<1>   = comp2 “-” in
                ; PORTA<2>   = comp1&2 “+” in
                ; PORTA<3>   = comp1 out
                ; PORTA<4>   = comp2 out, T0CKI in
                ; PORTA<5:7> = unused
                ;
                ;
                ; PORTB:-
    movlw    b’01000000′    ; initialise data direction
                ; 1 = input
                ; 0 = output
                ;
    movwf    TRISB        ; PORTB<0>   = LCD out “DB4”
                ; PORTB<1>   =         “DB5”
                ; PORTB<2>   =         “DB6”
                ; PORTB<3>   =         “DB7”
                ; PORTB<4>   = E  out to LCD
                ; PORTB<5>   = RS out to LCD
                ; PORTB<6>   = function in
                ; PORTB<7>   = Ccal switch out

    bank0

    return    

;**********************************************************
;
;    Measure Frequency. Stash in “F3 and F3+1”
;

Measure    bcf    INTCON,T0IF    ; Declare “Not yet Over-range”
    CLRF    TMR0        ; RESET INTERNAL COUNT (INCLUDING PRESCALER)
                ; See page 27 Section 6.0

    CLRF    F3        ; Ready to receive 16 bit number
    CLRF    F3+1

    bank1
                ; OPEN GATE
    
    movlw    b’11100111′    ; Enable RA4 output to T0CKI
    movwf    TRISA        ; 1 = input
                ; 0 = output
    
    CALL    MS100        ; 100MS DELAY

                ; CLOSE GATE (COUNT COMPLETE)

    movlw    b’11110111′    ; Disable RA4 output to T0CKI
    movwf    TRISA        ; 1 = input
                ; 0 = output
    bank0

    MOVF    TMR0,W        ; GET HIGH BYTE        
    MOVWF    F3        ; Copy to Big end of 16 bit result

; The comparator is “outputting” a 1 ‘cos we’ve forced it high
; so T0CKI=1.

PSC1    bank1
    bsf    OPTION_REG,T0SE    ; Clock the prescaler
    nop
    bcf    OPTION_REG,T0SE
    bank0
    
    DECF    F3+1,F        ; Decrement the counter
    
    movf    TMR0,W        ; Has TMR0 changed?
    xorwf    F3,W        ; if unchanged, XOR -> 0

    beq    PSC1

    return            ; F3 : F3+1 now holds 16 bit result

;**********************************************************
;
;    Display contents of AARGB0,1,2 on LCD
;    First convert to BCD, Then ASCII (nybble at a time)
;

Display    CALL    B2_BCD        ; CONVERT COUNT TO BCD        

    call    Swap0        ; GET NEXT DIGIT
    call    Move0        ; GET OTHER BCD DIGIT
    call    Swap1
    call    Move1
    call    Swap2
    call    Move2
    call    Swap3
    goto    Move3        ; includes return

;**********************************************************
;
;    Formatted display of BCD work area for Capacitor
;

C_disp    movf    R_sign,w    ; Sign
    call    DATS

F_C1    MOVF    bcd+0,W
    ANDLW    0x0F
    beq    F_C2

    CALL    PutNyb
    call    Swap1
    call    Move1
    CALL    DoDP        ; Print DP
    call    Swap2
    goto    F_C3U

;————————————————–

F_C2    swapf    bcd+1,W
    ANDLW    0x0F
    beq    F_C3

    CALL    PutNyb
    call    Move1
    CALL    DoDP        ; Print DP
    call    Swap2
    call    Move2
    goto    F_C3U        ; print nF. includes RETURN

;————————————————–

F_C3    MOVF    bcd+1,W
    ANDLW    0x0F
    beq    F_C4

    CALL    PutNyb
    CALL    DoDP        ; Print DP
    call    Swap2
    call    Move2
    call    Swap3

F_C3U    movlw    Unit1-0x2100    ; nF
    goto    pmsg        ; includes RETURN

;————————————————–

F_C4    SWAPF    bcd+2,W        ; Digit1 == 0 ?
    ANDLW    0x0F
    bne    NoB1_C

    MOVLW    0x20        ; YES PRINT A SPACE
    call    DATS

    MOVF    bcd+2,W        ; Digit2 == 0 ?
    ANDLW    0x0F
    bne    NoB2_C

    MOVLW    0x20        ; YES PRINT A SPACE
    call    DATS
    bra    NoB3_C

NoB1_C    call    Swap2        ; 1
NoB2_C    call    Move2        ; 2
NoB3_C    call    Swap3        ; 3
    CALL    DoDP        ; Print DP
    call    Move3        ; 4

    movlw    Unit2-0x2100    ; pF
    goto    pmsg        ; includes RETURN

;**********************************************************
;
;    Formatted display of BCD work area for Inductor
;

L_disp    movf    R_sign,w    ; Sign
    call    DATS

F_L1    MOVF    bcd+0,W
    ANDLW    0x0F
    beq    F_L2

    CALL    PutNyb
    call    Swap1
    CALL    DoDP        ; Print DP
    call    Move1
    call    Swap2
    goto    F_L2U        ; Print mH. includes RETURN

;————————————————–

F_L2    swapf    bcd+1,W
    ANDLW    0x0F
    beq    F_L3

    CALL    PutNyb
    CALL    DoDP        ; Print DP
    call    Move1
    call    Swap2
    call    Move2
    
F_L2U    movlw    Unit3-0x2100    ; mH
    goto    pmsg        ; includes RETURN

;————————————————–

F_L3    MOVF    bcd+1,W
    ANDLW    0x0F
    beq    F_L4

    CALL    PutNyb
    call    Swap2
    call    Move2
    CALL    DoDP        ; Print DP
    call    Swap3
    goto    F_L4U        ; Print uH. includes RETURN

;————————————————–

F_L4    SWAPF    bcd+2,W        ; Digit1 == 0 ?
    ANDLW    0x0F
    bne    NoB1_L

    MOVLW    0x20        ; YES PRINT A SPACE
    call    DATS

    goto    NoB2_L

NoB1_L    call    Swap2        ; 1
NoB2_L    call    Move2        ; 2
    CALL    DoDP        ; Print DP
    call    Swap3        ; 3
    call    Move3        ; 4

F_L4U    movlw    Unit4-0x2100    ; uH
    goto    pmsg        ; includes RETURN

;————————————————–
;
;    Common subroutine for formatted output
;

DoDP    MOVLW    ‘.’        ; Print DP
    goto    DATS        ; Return from DATS

Swap0    SWAPF    bcd+0,W        ; GET NEXT DIGIT
    goto    PutNyb        ; DISPLAY IT

Move0    MOVF    bcd+0,W        ; GET OTHER BCD DIGIT
    goto    PutNyb

Swap1    SWAPF    bcd+1,W
    goto    PutNyb

Move1    MOVF    bcd+1,W
    goto    PutNyb

Swap2    SWAPF    bcd+2,W
    goto    PutNyb

Move2    MOVF    bcd+2,W
    goto    PutNyb

Swap3    SWAPF    bcd+3,W
    goto    PutNyb

Move3    MOVF    bcd+3,W
    goto    PutNyb

;********************************************************************
;
;    Stack operations
;
;********************************************************************    

;add        call    FPA24
;        goto    S_fix

subtract    call    FPS24
        goto    S_fix

divide        call    FPD24
        goto    S_fix

multiply    call    FPM24
;        goto    S_fix

;
;    Fix stack after add, subtract, divide & multiply
;    AND Collect ALL Floating Point Errors in FPE

S_fix    iorwf    FPE,f            ; W may hold Error (0xff)

    copy    CARGB1,BARGB1        ; C -> B
    copy    CARGB0,BARGB0
    copy    CEXP,BEXP
    return

;
;    Push stack (duplicates TOS)
;

S_push    copy    BARGB1,CARGB1        ; B -> C
    copy    BARGB0,CARGB0
    copy    BEXP,CEXP

    copy    AARGB1,BARGB1        ; A -> B
    copy    AARGB0,BARGB0
    copy    AEXP,BEXP
    return

;
;    Swap A and B

S_swap    swap    AARGB1,BARGB1        ; A <-> B
    swap    AARGB0,BARGB0
    swap    AEXP,BEXP
    return

;********************************************************************
;
;    Calculate Unknown Capacitance OR inductance
;    
;       Output: 24 bit positive integer (scaled)
;    right justified in AARGB0, AARGB1, AARGB2
;    also as BCD in bcd:bcd+1:bcd+2:bcd+3
;
;********************************************************************    

C_calc    call    divide
    call    Get_Ccal    ; Times 10,000 ( = 1000.0pF)
    call    multiply
    goto    PorM        ; includes return

;——————————————————————–

L_calc    call    multiply
    call    Get_Lscale    ; Precomputed Scale_factor/(4*PI*PI)
    call    multiply
    call    Get_Ccal
    call    S_swap
    call    divide

L_divF1    call    Get_F1        ; Divide by F1^2
    call    S_push
    call    multiply
    call    S_swap
    call    divide

;
;    Handle Space or Minus in front of FP number
;    

PorM    btfss    AARGB0,7    ; test sign
    goto    Pplus
    
Pminus    movlw    0x2d        ; minus
    goto    PMdisp

Pplus    movlw    0x20        ; plus

PMdisp    movwf    R_sign        ; save for later display
    bcf    AARGB0,7    ; make plus anyway

;
;    Format as raw BCD string in bcd:bcd+1:bcd+2:bcd+3
;

    call    INT2424        ; To INT in AARGB0 etc.
    iorwf    FPE,f        ; W may hold Error (0xff)
    goto    B2_BCD        ; includes return

;********************************************************************
;
;    Calculate (F1/F3)^2-1, leave result on stack
;
;********************************************************************    

F1_F3    call    Get_F3
    goto    F1_F1

;********************************************************************
;
;    Calculate (F1/F2)^2-1, leave result on stack
;
;********************************************************************    

F1_F2    call    Get_F2
F1_F1    call    Get_F1
    call    divide        ; F1/Fx
    call    S_push
    call    multiply    ; (F1/Fx)^2
    call    Get_One
    call    S_swap
    goto    subtract    ; (F1/Fx)^2-1
                ; includes return

;********************************************************************
;    Fetch assorted things used for the calculation
;    of Unknown L and C
;
;********************************************************************    

Get_Lscale    call    S_push        ; make room first
        movlw    0xB8        ; 2.53303e+17
        movwf    AEXP        ; Create FP version of
        movlw    0x60        ; Precomputed 1/(4*PI*PI)
        movwf    AARGB0        ; times any needed
        movlw    0xFA        ; fiddle factor (1/100)
        movwf    AARGB1
        return

Get_One        call    S_push        ; make room first
        clrf    AEXP        ; Create a binary 1
        clrf    AARGB0
        clrf    AARGB1
        movlw    0x01
        goto    LSB2stak
    

Get_Ccal    movlw    cal_t        ; Get integer value
        goto    W2stak        ; Includes stack push

Get_F1        movlw    F1        ; Includes stack push
        goto    W2stak

Get_F2        movlw    F2        ; Includes stack push
        goto    W2stak

Get_F3        movlw    F3        ; Includes stack push
;        goto    W2stak

;********************************************************************
;    Copy 16 bit number, pointed to by W, to stack
;    and convert to FP (positive value only)
;    via a 24 bit number in AARGB0,1,2
;********************************************************************    

W2stak        movwf    FSR
        call    S_push        ; make room first

        clrf    AEXP
        clrf    AARGB0

        movf    INDF,W        ; Big Byte first
        movwf    AARGB1

        incf    FSR,F        ; then little byte

        movf    INDF,W
LSB2stak    movwf    AARGB2
        
        CALL    FLO2424        ; 24 bit int -> 24 bit FP
        iorwf    FPE,f        ; W may hold Error (0xff)
        RETURN

;********************************************************************
;    Read EEPROM into “cal_t”
;********************************************************************    

EE_RD    bank1
    movlw    cal_p-0x2100    ; Address to read
    MOVWF    EEADR
    bank0

    CALL    EE_R
    MOVWF    cal_t+0

    CALL    EE_Rinc
    MOVWF    cal_t+1

    RETURN

EE_Rinc    bank1
    INCF    EEADR,F        ; bump address

EE_R    bank1
    BSF    EECON1,RD    ; EE Read
    MOVF    EEDATA,W    ; W = EEDATA
    bank0

    RETURN

;********************************************************************
;    Write EEPROM from “cal_t”
;********************************************************************    

EE_WR    bank1
    movlw    cal_p-0x2100
    MOVWF    EEADR        ; Address to write

    MOVF    cal_t+0,W    ; Data byte #0
    CALL    EE_W

    MOVF    cal_t+1,W    ; Data byte #1
    CALL    EE_Winc

    bank0
    RETURN

    errorlevel    -302    ; In Bank 2

EE_Winc    INCF    EEADR,F        ; bump address
    
EE_W    MOVWF    EEDATA
    BSF    EECON1,WREN    ; Enable Write
    MOVLW    0x55        ;
    MOVWF    EECON2        ; Write 0x55
    MOVLW    0xAA        ;
    MOVWF    EECON2        ; Write 0xAA
    BSF    EECON1,WR    ; Set WR bit (begin write)

EE_W2    BTFSC    EECON1,WR    ; Wait for write to finish
    GOTO    EE_W2

    bank0
    BCF    PIR1,EEIF    ; clear interrupts
    bank1
    RETURN    

    errorlevel    +302

;********************************************************************    

    INCLUDE <FP.TXT>

;********************************************************************
;
;    Text Strings (stored in data EEPROM)
;

        ORG 0x2100

ovr    de    ”   Over Range   “,0
Unit1    de    ” nF”,0
Unit2    de    ” pF”,0
Unit3    de    ” mH”,0
Unit4    de    ” uH”,0
Cintro    de    ” C = “,0
Lintro    de    ” L = “,0
Calibr  de    ”   Calibrating  “,0

cal_p    de    0x27,0x10        ; Initial value = 10000

     END

;********************************************************************

 

 

 

 

Advertisements
 
Leave a comment

Posted by on June 25, 2011 in Microcontrollers

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: