|
|
|
|
|
|
Home PageContact MeMAC OS XLinuxLinux Servers Fedora Core 4Linux Servers - CentOSLinux Servers Fedora Core 5Linux Servers Fedora Core 7Linux Servers Fedora 8OpenWRTNSLU2LinuxClusterHardware Hacking ProjectsSpeaker Building ProjectsElectronics ProjectsOther Sites |
![]() Status
IntroductionThis is my attempt at building an accurate L/C meter. This design is based on other designs found on the internet. It was just my luck that the other designs didn't work as expected. By that I mean: I have my own PICs on hand, I wanted other features, I fine tuned the LM311 oscillator. This project is for my ham bench. The features are as follows: The SchematicBelow is the schematic for the meter. The image has been sized to fit the browser window. Right click to save or view the full size image. ![]() The Parts ListHere's the list of parts you get to spend money on.
The Main PlayersThe circuit is composed of 3 functions. Power SupplyThe power supply uses a LM7805 voltage regulator. Nothing more than the standard textbook design. The BrainsA PIC16F628 is the brains of the circuit. It handles all the calculations and displaying the results LC OscillatorThe LC oscillator is based on a LM311. And I bet you're saying that there is a mistake in the schematic. There isn't. The oscillator can be improved by feeding the output of the LM311 back to the L/C tank. The SoftwareThe software was written in basic. I don't use floating point math. This is a great example showing how to use integers to do floating point math. This program is far from done. Here is the hex file for the program below. The file will download as a text file. Just change the .txt extension to .hex and you're good to go.
'*****
'* PROJECT: CAMP L/C Meter
'* SOFTWARE VERSION: 0.7
'* TARGET PIC: PIC16F628
'* TARGET PCB: ?
'* CREATED:
'* LAST UPDATED:
'* WRITTEN BY: Richard Camp
'*
'* OVERVIEW
'* --------
'*
'* INPUTS/OUTPUTS
'* --------------
' A0 OUT -
' A1 OUT -
' A2 OUT - LCD enable
' A3 OUT - LCD reg select
' A4 OUT -
' A5 INP -
' A6 XTAL OSC
' A7 XTAL OSC
'
' B0 OUT - LCD data 0
' B1 OUT - LCD data 1
' B2 OUT - LCD data 2
' B3 OUT - LCD data 3
' B4 OUT - cal cap relay
' B5 OUT - mode select relay
' B6 IN - freq count
' B7 OUT -
' DEVICE PROGRAMMING OPTIONS
' --------------------------
@ DEVICE pic16F628, XT_OSC
@ DEVICE pic16F628, WDT_ON
@ DEVICE pic16F628, PWRT_ON
@ DEVICE pic16F628, BOD_ON
@ DEVICE pic16F628, MCLR_OFF
@ DEVICE pic16F628, LVP_OFF
@ DEVICE pic16F628, CPD_OFF
@ DEVICE pic16F628, PROTECT_OFF
' picbasic defines
' ================
DEFINE LCD_DREG PORTB ' LCD RA to LCD data port
DEFINE LCD_DBIT 0 ' Starting data bit on b0 & last on b3
DEFINE LCD_BITS 4 ' Set 4-bit data bus width
DEFINE LCD_RSREG PORTA ' Set LCD register select port to A
DEFINE LCD_RSBIT 3 ' Set A3 to register select pin
DEFINE LCD_EREG PORTA ' Set LCD enable to port A
DEFINE LCD_EBIT 2 ' Set A2 to LCD enable pin
DEFINE LCD_LINES 1 ' LCD is a 1 line display
DEFINE LCD_COMMANDUS 2000 ' Set LCD command delay time in uS
DEFINE LCD_DATAUS 100 ' Set LCD data delay time in uS
' HARDWARE ASSIGNMENTS
' --------------------
freqin var portb.6 ' input - freq in
calRelay var portb.4 ' relay pin for calibration 0=calibrate
modeRelay var portb.5 ' relay pin mode select
' 0=measure cap
' 1=measure ind
' RAM ASSIGNMENTS AND VARIABLES
' -----------------------------
tmpvar var word ' temp storage
tmpvar2 var word ' temp storage
units var byte ' units to display
freq1 var word ' F1 frequency
freq2 var word ' F2 frequency
fratio var word ' F1/F2 ratio
FRdecMv var byte ' num of dec places to move fratio
' ex:
' fratio=1.032
' prdecmove=1
' fratio=10.32 recalculated
valmult var word ' (fratio -1)
fcount var word ' raw count from osc
ovf var bit ' overflow flag for fcount
OscC1 var word ' C of osc in pf
OscL1 var word ' L of osc in uH
meterMode var bit ' 0=measure capacitance
' 1=measure inductance
decmult var word ' number of digs after dec point
' ex: 10, 100, 1000, 10000
LCval var word ' L or C value
LCvalR var word ' remainder of L or C value
' PROGRAM CONSTANTS
' -----------------
ctime con 100 ' fcount sample time in ms
rtime con 3000 ' relay and osc settling time ms
Ccal con 1100 ' 1.1 nf
Ccap con 750 ' 750pf
Cind con 82 ' 82uh calibration inductor
' -------------
' PROGRAM START
' -------------
' START OF PROGRAM INITIALIZATION
' ===============================
Disable
progstart:
' initialize hardware
CMCON=%00000111 'disable comparators
TRISA=%00101111 'setup port A
TRISB=%11110000 'setup port B
OPTION_REG.7 = 0 'enable port b pullups
VRCON.7 = 0
VRCON.6 = 0
RCSTA.7 = 0
Pause 1000 'timeout to let the hardware settle
high calrelay 'turn the cal relay off
low moderelay 'turn off the relay
' setup lcd and display title
LCDOUT $FE,1,$FE,$0C,$FE,2,"CAMP L/C Meter V0.7b"
pause 4000
' set program vars
metermode=0 ' set meter mode to measure capactance
OscL1=cind ' set to default value
OscC1=ccap ' set to default value
'calibrate the device
gosub calibrate
OscL1=cind ' set to default value
OscC1=ccap ' set to default value
' START OF MAIN PROGRAM LOOP
' ==========================
mainloop:
'measure the freq and store in F2
gosub readfreq ' load fcount with Osc frequency
freq2=fcount ' store fcount in F2
' Do range checking and mode switching
if (freq2>(freq1+75) or ovf=1 or freq2<30) and meterMode=1 then
metermode=0 ' set mode to measure cap
low moderelay ' turn off mode relay
pause rtime ' pause to let things settle
goto mainloop
endif
if (freq2>(freq1+75) or ovf=1) and meterMode=0 then
meterMode=1 ' set mode to measure inductance
high moderelay ' turn on mode relay
pause rtime ' pause to let things settle
goto mainloop
endif
' Do the calculations
' There is no floating point here
'
' F1^2
' Cx= [------- -1]*Cref
' F2^2
'
' F1^2
' Lx= [------- -1]*Lref
' F2^2
'
' Auto scaling is also done. This provides the best
' accuracy for the part we are measuring.
'
decmult=1 ' set the mult to 1
scalecalc:
gosub freqratio ' calc F1/F2
gosub valuemult ' get the num to mult L or C by
' fratio^2-1
' the section below checks to see if we have a large
' enough integer. If the answer is below what we are
' looking for then change the multiplication factor and
' redue the calcs.
if valmult<=1000 and decmult<10000 then
decmult=decmult*10
goto scalecalc
endif
gosub calcLc ' calc Lx or Cx
' this section displays the result
lcdout $fe,1,$fe,$c0,$fe,2,"Auto "
if metermode = 0 then
lcdout "C"
else
lcdout "L"
endif
lcdout "=",#LCval,".",#LCvalr
if metermode = 0 then
select case units
case 1
lcdout "pF"
case 2
lcdout "nF"
case 3
LCDout "uF"
end select
else
select case units
case 1
lcdout "uH"
case 2
lcdout "mH"
case 3
LCDout "H"
end select
endif
pause 200 ' pause between readings
GoTo mainloop ' repeat the main loop forever
' END MAIN PROGRAM LOOP
' =====================
' read freq on a pin
' use hardware timer1 to count the pulses from the
' LM311.
readfreq:
fcount=0 ' zero fcount
ovf=0 ' clear the overflow flag var
t1con = 7 'set timer 1 on, external clock, non sync = bit0 =1, bit1 =1, bit2 =1
tmr1h = 0 'clear timer 1 high byte
tmr1l = 0 'clear timer 1 low byte
pir1 = 0 'clear overflow flag
pause ctime 'wait for the sample period
t1con = 0 'stop timer 1 , bit0 =0
fcount.byte0 = tmr1l 'get the timer low byte
fcount.byte1 = tmr1h 'get the timer high byte
ovf = pir1 'get the overflow flag
fcount=fcount/2 'divide fcount by 2
Return
' calibration routine
' we need to know the actual L1 and C1 values
' calibration is done using a high accuracy calibration
' capacitor
calibrate:
lcdout $fe,1,$fe,$c0,$fe,2,"Calibrating"
decmult=10000 'set the dec multiplier to 10000
' get F1 then enable cal cap and get F2
pause rtime 'pause to let the osc settle
gosub readfreq 'get the osc freq
freq1=fcount 'store in F1
low calrelay 'turn on the calibration relay
pause rtime 'pause to let the osc settle
gosub readfreq 'get the osc freq
freq2=fcount 'store in F2
high calrelay 'turn off the calibration relay
'lcdout $fe,1,$fe,$c0,$fe,2,"F1=",#freq1," F2=",#freq2
'pause 3000
' calculate C1
' F2^2 F2^2
' C1 = ----------- * Ccal = ----------------- * Ccal
' F1^2-F2^2 (F1+F2)*(F1-F2)
tmpvar=freq1*freq1 ' square F1
tmpvar=div32 10000
tmpvar2=freq2*freq2 ' square F2
tmpvar2=div32 10000
tmpvar=tmpvar-tmpvar2 ' F1^2-F2^2
tmpvar2=tmpvar2*1000
tmpvar2=div32 tmpvar
tmpvar=tmpvar2*Ccal
OscC1=div32 1000
' Calculate L1
' 1
' L1 = -----------------
' 39478*F1^2*C1^2
tmpvar=freq1*freq1
tmpvar=div32 1000
tmpvar2=OscC1*OscC1
tmpvar2=div32 1000
tmpvar2=tmpvar2*39478
tmpvar2=div32 1000
tmpvar=tmpvar2*tmpvar
tmpvar=div32 1000
tmpvar2=1000*1000
tmpvar2=div32 tmpvar
lcdout $fe,1,$fe,$c0,$fe,2,"Cal C1=",#OscC1,"pF"
pause 5000
lcdout $fe,1,$fe,$c0,$fe,2,"Cal L1=",#tmpvar2,"uH"
pause 5000
return
' calc F1/F2
freqratio:
tmpvar=freq1*decmult
fratio=div32 freq2
return
' calc fratio^2-1
valuemult:
tmpvar=fratio*fratio
valmult=div32 decmult
valmult=valmult-decmult
return
' calc L or C
' load tmpvar2 with L1 or C1 value
' tmpvar2 returns unit scaling for display
' 1 = pf or uh
' 2 = nf or mh
' 3 = uf or h
calcLC:
if metermode = 0 then
tmpvar2=OscC1
else
tmpvar2=OscL1
endif
units=1
rescale:
tmpvar=valmult*tmpvar2
LCval=div32 decmult
LCvalR=R2
if LCval>50000 then
tmpvar2=tmpvar2/10
decmult=decmult*100
units=3
goto rescale
endif
if LCval>1000 then
tmpvar=LCval*1
LCval=div32 1000
LCvalR=R2
units=2
endif
tmpvar=lcvalr*100
lcvalr=div32 100
return
' END OF PROGRAM
' ==============
The Theory(the last part to be done) ConclusionEnjoy. Below is a photo of my version. ![]() Comments |