Kaynak Kodu :
; software: ver.6 ;***************** Dec. 3rd. 2002 ************************** ; Written by Flemming Jensen ; Zeroing on pwr-up ; Low battery indicator ; ; No diode in series with "nF" range resistor ; (instead the Pic pin connected to the nF resistor ; is programmed as input when not used, i.e. made Hi-Z) ; ; pF/nF/uF and up to >1F ; rolls over from 999pF to 1.00nF and 9.99nF to 10nF etc. ; pF procedure is run twice, mean value is used. This way ; hum influence is reduced. ; (uF range selected via a pnp, and so 1=off, 0=on) ; In mF procedure, is "wait" signalled when measuring. ; "ready" is shown when mF procedure has been run 4 times. ; meter has to be reset by on/off when ready has been shown. ; p.g.a. for stor fejlvisning over 5000uF er der nu indlagt ; en "wait" på 1500mS i uF proceduren ; ;************************************************************* #compiler clock = 20000 ; 20 MHz clock #ASM list p=16C84 #fuse CP_OFF + PWRT_ON + WDT_OFF + XT_OSC var charout : byte ; character output to lcd var flags : byte ; boolean byte var lcdData : bit 0 of flags ; T = data or F = command var lcdbusy : bit 1 of flags ; lcd busy flag var talx : word ; contains the cap. value var talx1 : word var talx2 : word var a : byte ; holds number of 1000's var nb : byte ; holds number of 100's var c : byte ; holds number of 10's var d : byte ; holds number of 1's var p : byte ; prefix ( p n u m ) var y : byte ; insert dec.point ? var z : word ; open lead cap. var zz : word ; open lead cap. var tempcount : byte ; for delay uF range var delaycount : byte var q : byte ; holds batt. condition var rdy : byte ; holds how many F proc. var proc : byte alias(RB4,lcdportD4) ; rename port RBx to lcdportDx alias(RB5,lcdportD5) alias(RB6,lcdportD6) alias(RB7,lcdportD7) alias(RA0,lcd_rs) ; lcd register select alias(RA1,lcd_en) ; lcd enable alias(RA2,lcd_rw) ; lcd read/write alias(RB0,bat) ; RB0 lo bat alias(RB1,range_uF) ; range select alias(RB2,range_nF) alias(RB3,reset) ; reset 555 alias(RA3,trig) ;trigger for 555 alias(RA4,out_555) ;output pulse from 555 procedure(MAIN) InitPort ; set up ports InitLCD ; initialise lcd display reset = 1 ; reset 555 high trig = 1 clr(z) ; reset zeroing var clr(rdy) ; rdy reset pFzero ; open leads cap is stored just after pwr-up while true clr(proc) pF ; pF procedure (000pF-9,99nF) if proc = 0 then begin talx1 = talx ; 2 times meas. (hum reduction) wait(10) pF talx2 = talx wait(10) talx = (talx1 + talx2)/2 end DoMessage loop procedure(pFzero) ; incr. talx, when 555 is high clr(y) ; no dec. point input(range_nF) ; nF is made Hi-z by converting pic pin as input ;range_nF = 0 ; nF,uF deselected,(uF=pnp=off) range_uF = 1 ; pF is hardwired high resettrig while (b'00010000' and PortA) ;RA4 is read,(555 output) inc(z) ;if high,increment talx if z >= 9999 then ;if >9999pF,shift to nF begin nF end loop ;the open zz = z ;leads caps need to be stored twice is stored in z ; (compiler peculiarities?) procedure(pF) ; incr. talx, when 555 is high z = zz ; Restoring open leads cap after having been in nF proc p = 'p' clr(y) ; no dec. point input(range_nF) ;range_nF = 0 ; nF,uF deselected,(uF=pnp=off) range_uF = 1 ; pF is hardwired high resettrig while (b'00010000' and PortA) ;RA4 is read,(555 output) inc(talx) ;if high,increment talx if talx >= 9999 then ;if >9999pF,shift to nF begin nF end loop talx = talx-z ;and subtracted from result while talx > 9999 ;ensures that talx-z doesn't talx = talx + 1 ;go below zero loop if talx >= 1000 then ;remove a decade and insert begin ;a dec.point talx = talx/10 p = 'n' ; n for (n)F y = 1 ; insert dec.point end ; 9999pF becomes 9,99nF if (b'00000001' and PortB) then begin q = 1 end else ;RB0 testing batt. begin q = 0 end if q = 0 then begin lo_mess end procedure(nF) ; procedure nF same as pF procedure p = 'n' ; except (n)F clr(y) clr(z) proc = 1 output(range_nF) range_nF = 1 ; nF range resistor selected range_uF = 1 ; uF=pnp=off resettrig while (b'00010000' and PortA) inc(talx) if talx >= 9999 then begin uF end loop if talx >= 1000 then begin talx = talx/10 p = 'u' y = 1 end procedure(uF) proc = 1 p = 'u' clr(y) clr(z) input(range_nF) ;range_nF = 0 range_uF = 0 ;uF(pnp=0=on) clr(talx) rst ; 555 reset procedure trig = 1 Wait(1500) trig = 0 delay trig = 1 while (b'00010000' and PortA) clr(tempcount) while tempcount <= 92 ; div. by 78, caused by the long inc(tempcount) ; timing pulse in uF range loop ; calibrated for proper reading inc(talx) if talx >= 9999 then begin mF ; goto mF routine if talx exceeds end ; 9999 loop if talx >= 1000 then ; same as in pF,nF begin talx = talx/10 p = 'm' y = 1 end procedure(mF) inc(rdy) proc = 1 p = 'm' clr(y) clr(z) ;range_nF = 0 ;range_uF = 0 ;uF range (pnp=0=on) clr(talx) rst ; 555 reset procedure waitmessage trig = 1 Wait(60000) ; due to the long timingpulse trig = 0 ; an extra long wait must be delay trig = 1 ; inserted while (b'00010000' and PortA) ;if high, increment talx wait(194) ;incr. has to be slowed down in mF inc(talx) loop if talx >= 1000 then ; same as in pF,nF begin talx = talx/10 p = ' ' y = 1 end while rdy = 4 ReadyMessage loop procedure(resettrig) clr(talx) rst ; 555 reset procedure trig = 1 Wait(100) trig = 0 delay trig = 1 procedure(rst) reset = 1 reset = 0 wait(1) reset = 1 procedure(delay) clr(delaycount) while delaycount <= 1 ; Delay for trig pulse inc(delaycount) ; loop Procedure(ReadyMessage) lcdData = false ; sending command charout = b'11000000' ; cursor to 2nd line position 1 LCDout lcdData = true charout = ' ' LCDout charout = ' ' ;move display 5 spaces LCDout ;to the left charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = 'R' LCDout charout = 'e' LCDout charout = 'a' LCDout charout = 'd' LCDout charout = 'y' LCDout Procedure(WaitMessage) lcdData = false ; sending command charout = b'11000000' ; cursor to 2nd line position 1 LCDout lcdData = true charout = ' ' ;move display 5 spaces LCDout ;to the left charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = 'W' LCDout charout = 'a' LCDout charout = 'i' LCDout charout = 't' LCDout Procedure(lo_mess) lcdData = false ; sending command charout = b'11000000' ; cursor to 2nd line position 1 LCDout lcdData = true charout = ' ' ;move display 2 spaces LCDout ;to the left charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout charout = 'B' LCDout charout = 'A' LCDout charout = 'T' LCDout procedure(doMessage) lcdData = false ; setup lcd for command receive charout = b'10000000' ; cursor to 'home' line 1 pos 1 LCDout ; send to lcd charout = b'00000001' ; clear display LCDout lcdData = true ; lcd,receive data clr(a) ; reset var clr(nb) clr(c) clr(d) charout = ' ' ;move display 4 spaces LCDout ;to the left charout = ' ' LCDout charout = ' ' LCDout charout = ' ' LCDout ;********** converts talx to decimals **************** ; by counting, how many 1000's,100's,10's and 1's ;***************************************************** while talx >= 1000 ;How many 1000's inc(a) ;is put in a talx = talx - 1000 loop if a = 0 then ;if no 1000's begin charout = ' ' ;write a 'space' end else begin charout = a + 48 ;convert to ascii end LCDout ; send to lcd while talx >= 100 ; how many 100's inc(nb) ; is put in b talx = talx - 100 loop if (nb=0) and (a=0) then ;if no 100's begin charout = ' ' ; write a 'space' end else begin charout = nb + 48 ; convert to ascii end LCDout if y = 1 then ;insert dec.point begin charout = '.' ;if y = 1 LCDout end while talx >= 10 ;how many 10's inc(c) ;is put in c talx = talx - 10 loop if (c=0) and (nb=0) and (a=0) then ;if no 10's begin charout = ' ' ;write a space end else begin charout = c + 48 ;convert to ascii end LCDout ;send to lcd d = talx ;d=how many 1's charout = d + 48 ;convert d to ascii LCDout ;send to lcd charout = ' ' ;space LCDout charout = p ;prefix var ( p n u m ) LCDout charout = 'F' ;F for farad LCDout procedure(InitPort) output(lcd_rs) ; lcd register select output output(lcd_en) ; lcd enable output output(lcd_rw) ; lcd read/write output output(lcdportD4) ; make port RB4 output output(lcdportD5) ; make port RB5 output output(lcdportD6) ; make port RB6 output output(lcdportD7) ; make port RB7 output output(range_uF) ; make port output output(range_nF) output(reset) output(trig) ;make RA3 output input(out_555) ;make RA4 input input(bat) ;make RB0 input procedure(InitLCD) wait(15) ; Ændring fra før. charout = b'00110000' ; 8 bit mode InitLCDout ; initialise LCD charout = b'00110000' InitLCDout charout = b'00110000' InitLCDout charout = b'00100000' ; Ændring fra før. InitLCDout lcdData = false ; sending command charout = b'00101000' ; 4 bit, 2 lines, 5x7 font LCDout ; 4 bit data transfer charout = b'00011000' ; cursor move, right shift LCDout charout = b'00001100' ; display on, cursor+blink off LCDout charout = b'00000100' ; entry mode LCDout charout = b'00000001' ; clear display LCDout procedure(LCDout) busywait ; is lcd busy if lcdData = false then begin lcd_rs = 0 ; 0 - instruction register lcd_rw = 0 ; 0 - writing to lcd end else begin lcd_rs = 1 ; 1 - data register lcd_rw = 0 ; 0 - writing to lcd end send4bits ; call routine to output 4 bits swap(charout) ; swap lower 4 bits send4bits ; call routine to output 4 bits procedure(send4bits) lcdportD4 = charout AND b'00010000' ; send 4 bits lcdportD5 = charout AND b'00100000' ; send 4 bits lcdportD6 = charout AND b'01000000' ; send 4 bits lcdportD7 = charout AND b'10000000' ; send 4 bits lcd_en = 1 ; Lcd enable high to low lcd_en = 0 ; data valid procedure(busywait) lcd_rw = 1 ; 1 - reading from lcd lcd_rs = 0 ; 0 - instruction register input(lcdportD4) ; make port input input(lcdportD5) ; make port input input(lcdportD6) ; make port input input(lcdportD7) ; make port input LCDwait output(lcdportD4) ; make port output output(lcdportD5) ; make port output output(lcdportD6) ; make port output output(lcdportD7) ; make port output procedure(LCDwait) lcdbusy = true while lcdbusy = true ; true = lcd busy, false = ready lcd_en = 1 ; read data lcdbusy = lcdportD7 ; receive upper 4 bits first lcd_en = 0 lcd_en = 1 ; not interested in lower 4 lcd_en = 0 ; bits of status byte loop procedure(InitLCDout) wait(10) ; wait 4 msec (no busy flag) lcd_rw = 0 ; 0 - writing to lcd lcd_rs = 0 ; 0 - instruction register send4bits ; call output 4 bits
Malzeme Listesi :
Resistors:
R1 = 120Ω
R2 = 5kΩ6
R3 = 5MΩ6
R4 = 1kΩ
R5 = 39kΩ
R6 = 10kΩ
R7 = 470Ω 1W (see text)
P1 = 1MΩ 10-turn multiturn preset,vertical mounting
P2 = 1kΩ 10-turn multiturn preset,vertical mounting
P3 = 100Ω 10-turn multiturn preset,vertical mounting
P4 = 22kΩ
Capacitors:
C1 = 47nF
C2,C7 = 100nF
C3,C4 = 4pF7
C5,C6 = 330nF
Capacitors:
C1 = 47nF
C2,C7 = 100nF
C3,C4 = 4pF7
C5,C6 = 330nF
IC2 = PIC16F84A-20/P, programmed,order code 020144-41
IC3 = 78L05
T1 = BC559B
Miscellaneous:
BT1 = 9V PP3 (6F22) battery with clip-on connector
JP1 = 2-way pinheader with jumper
K1 = two 7-way socket strips, lead pitch 0.1 inch
K2 = 16-way boxheader
K3 = PCB solder terminals
S1 = on/off switch
X1 = 20MHz quartz crystal
LCD display, 2×16 characters, e.g.,
Trimods 1536, Farnell # 142-554 Length of 16-way flat cable with IDC socket
Enclosure: e.g., Pactec HPS and HPLS series, type HPS-9VB (28x53x91x146 mm), Farnell # 736-351, see also www.pactecenclosures.com
PCB, order code 020144-1 (see Readers Services page) Disk, source code and hex files, order code 020144-11 or Free Download