Head-Fi.org › Forums › Misc.-Category Forums › DIY (Do-It-Yourself) Discussions › A UV lightbox with exposure timer. A photo-PCB howto.
New Posts  All Forums:Forum Nav:

A UV lightbox with exposure timer. A photo-PCB howto.

post #1 of 19
Thread Starter 

Avro_Arrow suggested I post in the 'Rate My Etching Job' thread, but there's so much of this, I don't want to take over that thread.

 

I've seen a few posts about PCB fabrication. Many people use toner transfer, but I've always used photo-etch.

 

Here's how:-

 

This time I decided to go with LEDs. The previous lightbox I had used fluorescent tubes installed in some fittings taken from an old camper van, I used to run it off a 12V lead-acid battery. The whole thing was constructed out of scavenged bits; a box I picked up in the street that had slots for a sliding lid that neatly accommodated a sheet of glass that I cut to fit. I lost it. How do you lose a UV lightbox?. Don't ask me.

This time I bought 100 UV LEDs from a seller in Nanjing, China for $10 US shipped. I had some Veroboard which I cut into 3-conductor-wide strips, this gave me 10 strips, each of which accommodated 9 LEDs.

I decided to run the LEDs in strings of 3, without a ballast resistor. The forward voltage is quoted as 3.4~3.8 volts. When I ran up the 90 LEDs to 600mA (30 strings @ 20mA) I got ~11 volts on the lab power supply, so I figured 2 rectifier diodes in series with 12V regulated from a 7812 would be about right to drop the voltage to an appropriate level. It’s not recommended to run LEDs this way, usually there’s a ballast resistor in every string or a constant current supply, but I broke from these practices first when building torches, and it turns out LEDs are more robust used like this than theory and literature would suggest.

I built a 12V power supply with a 20VA RS toroidal transformer I had lying around. The other components for the bridge and the smoothing caps were just ‘lying around’ too. I used a 78S12 regulator in conjunction with the aforementioned dropper diodes in order that the UV array wouldn’t be overdriven.

 

Here's the LED array:-

 

UV_LED_array.jpg

 

Here it is lit.

 

UV_LEDs_lit.jpg

 

And here's the coverage pattern:-

 

UV_LEDs_illum_pattern.jpg

 

This is a sheet of printer paper lying on the picture frame blocked up about a foot over the array on some piles of books.

 

Arranging the LEDs was a problem. First they had to be seated firmly against the Veroboard to try and make the beams parallel. Then the Veroboard had to be held flat. I've got a piece of 3 mm fibreboard with 2 x 1/4 x 1/2in balsa strips adhered to it with doublesided sticky pads. Then the Veroboard is held to the balsa strips with thumbtacks, or drawing pins if that name is more familiar to you.

This has not resulted in as even illumination as I had hoped. The beams of the LEDs are quite narrow. This has the advantage that the overall beam does not spread too much, but I have had to keep the target sheet 12 inches away from the LEDs to ensure that the spots spread into one another. The beams mean that the collimation is not too bad, however, certainly better than the typical fluorescent setup. I’m looking for an LCD monitor to dismantle, they have some high-performance diffusion screens in them, which might improve things. 

 

It looks a bit blotchy, and I've tweaked the way the LEDs point since, but its surprisingly effective and even in its results. I've made a 7.5 inch square board without problem. The exposure time is 480 seconds. The box I had previously only required about 4 minutes. It was 12 watts, this is only ~6. This was cheap, however, given that I had the Veroboard, it works, and it’s low voltage.

 

w

post #2 of 19

Nice and neat setup! I agree about the LCD filter, that could have a great diffusal effect while staying efficient.

post #3 of 19
Thread Starter 

Hi, Ben. Yeah, I'm just waiting for a broken monitor.

 

When at work I used to make stencils on a laser printer. I used transparencies up to A4, and architectural drafting film up to A2. I made some pretty big PCBs, butting 3 sheets together to get up to 32 inches. Once I figured how, I made the big boards by isolation routing.

 
A big board, 32*9.5 inches:-
 

Click the image to open in full size.

 

You can see the SMPS mezzanine board in the middle. The board is an illuminated instrument panel with 7-segment display meters. The big cut-outs accommodate banks of circuit breakers. You can see the blue glow from the illumination reflected back from the bench underneath.

 

I was concerned that stencils made on an inkjet printer might not work. Transparency material for inkjet has a coating on one side to absorb the ink. This has tiny dots (imperfections) irregularly spaced presumably as a result of the coating drying. I thought these might show up on the PCB. I also didn't know if the contrast ratio between the inked areas and the clear would be sufficient to produce a good image in the photoresist. As it turns out, this is not a problem. Although the contrast could be better, it is still possible to produce adequate results down to 10 mil traces. This can be seen on the doublesided board shown later.
 

 

post #4 of 19
Thread Starter 

 

I made the board for the PSU using the new LED array driven from a lab PSU and did the timing with a stopwatch. It’s a conventional thru-hole job, single-sided.
 
Click the image to open in full size.

Click the image to open in full size.

 

 

I thought I might have to move the regulator off the board to get it on a heatsink, but it doesn't get too hot as it turns out.
 
w
post #5 of 19
Thread Starter 

This is the board for the timer.

 

I like surface mount components. The more surface mount you have, the less holes you have to drill. There are no problems with requiring thru-hole plating, although obviously, in the case of a double-sided board, vias are necessary. I generally use a larger head on the vias than I would for a commercially produced board. This is not ideal, but the real-estate taken up is generally not critical in DIY projects.

Click the image to open in full size.

Double-sided boards obviously require registration between the sides. This can be accomplished by peeling the protective plastic covering from one side and sticking one stencil to the unexposed board and drilling a few holes. You will have to remove some swarf from between the stencil and board before exposure. You can use reference marks included for the purpose, or simply drill at the board corners, or through a few vias. Then the protective film is peeled from the other side and the second stencil carefully matched to the holes. An alternative method matches the stencils against each other, taping them to prevent relative movement, and inserting a piece of scrap board with an edge coincident with one of the board edges on the stencil and then taping this in place. The unexposed board can then be inserted between the stencil sheets and butted up against the scrap piece and some tape added to obviate movement between exposures.

 

Here is the artwork as a 200dpi bitmap

 

lightbox_top.bmp

 

lightbox_bot.bmp


w

post #6 of 19

Wow, that's really impressive work! I'm a bit of a beginner with DIY electronics, is isolation routing literally using a routing machine to mechanically remove the metal on the circuit board?

 

Also, a probably very newbish question about the first post, how do the 'rectifier' diodes protect the LEDs? I've only ever really seen diodes used to stop current flowing in the wrong direction (or as LEDs tongue.gif).

post #7 of 19
Thread Starter 

Vias

 

Click the image to open in full size.

Click the image to open in full size.

Vias are all placed at the same time. Take about a metre of plated copper wire and grasp the ends in long-nose pliers, taking a couple of turns round each of the plier jaws. Hold the pliers firmly and pull them apart until the wire can be felt to give by a centimetre or so. This will put a 'set' on it, i.e. leave it straight and slightly work hardened.

Now cut sufficient 'needles' from the straightened wire to complete the board. Cut the needles with side-cutters held at a 45 degree or better angle so that a sharp pointed end is produced.

Place the board on a piece of sponge such as frequently found in kitchens or bathrooms. Place the needles to fill all the via holes, pushing them down securely into the sponge for about half their length. Once they are all placed, you can go round and solder them all. Detach the board from the sponge and trim the excess wire from the top surface. Now you can invert the board and solder the other side. Even if the board is subsequently reflowed in a toaster oven, the vias are unlikey to fall out due to surface tension, particularly if the wire is not a sloppy fit in the holes.

Click the image to open in full size.

w

post #8 of 19
Thread Starter 

OK, Ben, the large PCB carried about a hundred side-firing LEDs. They were arranged to fit into a perspex light-guide. (A sheet of perspex matching the PCB in size) The LEDs (dual) were about 2.5*12mm and each fitted into a corresponding laser-cut slot in the perspex. Now when the LEDs were powered you had a lot of light shooting around in the perspex sheet. By laser engraving a lot of dots on the (back of the) sheet the light could be made to reflect out of the plane of the sheet at rightangles. Put the dots in the right place and cover the light-guide with a second perspex painted black with legends cut in the paint with a laser and hey-presto, an evenly illuminated and unique panel into which to incorporate any meters, indicators and switches required to run your particular application, in this case a luxury yacht.

 

Yes, isolation routing involves engraving a line around every track or land to isolate it from the rest of the copper. You can completely remove the excess copper, but it's time consuming. Time's money so we only cut away sufficient to prevent shorts, and anyway there was quite a lot of heat evolved so the extra copper helped to spread any hotspots. There was so much heat, in fact, that the application was only made possible by the efficient use of the light via the lightguide.

 

Cool all round, a 32 inch PCB and 10 thou tolerance holes cut on different machines. The LEDs were thru-hole which permitted a certain amount of hand-fettling.

 

Here's a similar thing I made at home for a touch-sense relay-switched attenuator:-

 

attn.jpg

 

Left up-down, channel select, buffer on-off, both up-down, right up-down. You can just see the channel and buffer indicator LEDs, the camera doesn't see them well in this light and at this angle.

 

The rectifier diodes for the lightbox were simply used as voltage droppers. Every diode has a characteristic known as its 'forward voltage'. In the case of a silicon rectifier this voltage is about 0.6V, although this is approximate and varies with the current passed and the temperature. I needed ~10.8V. I used a 7812 regulator to get 12V, then I threw away 1.2V by including 2 otherwise unnecessary rectifier diodes forward biased (conducting) in the circuit. I could have achieved roughly the same result with a resistor and doing some calculation, but this way requires less thought and the voltage dropped is less dependent on the current.

 

w


Edited by wakibaki - 10/9/11 at 4:49pm
post #9 of 19
Thread Starter 

Click the image to open in full size.

Here's the timer for the lightbox. It employs a PIC 16F887 which was selected, amongst other things, for its internal oscillator.

Click the image to open in full size.

Click the image to open in full size.

The board provides a simple timer function with a relay to control the UV light. The circuit is shown here.

Click the image to open in full size.

When switched on the timer displays 000. There are 3 control button inputs, 2 for setting the period.. The first causes the display to count upwards. The count proceeds at second intervals when the button is held down until the count reaches 5, then the delay period is reduced and the count increases at a faster rate, this means that setting relatively long delays can be accomplished in a relatively short time.

The second button functions in a similar fashion to the first, but the count is down.

The third button turns on the UV light and starts the counter counting down at 1 second intervals. When the count reaches zero the UV is turned off and the display reverts to the number originally set. Subsequent exposures can be initiated by pressing the start button again.

A number of the components used are mounted unconventionally. The voltage regulator, electrolytic caps and diodes and relay are all conventional thru-hole types applied to one side of the board and ‘glued’ there with solder. In some cases I have used a custom foil pattern, and bent the component legs to mate. The 7-segment displays are common-anode types, each segment is ballasted with a 470R resistor. They are mounted in a 30-pin DIL socket which is surface-mounted to the PCB, this provides some stand-off and means that the components can be replaced or re-used if so desired. Since 30-pin sockets are not generally available, one can be made up from 2 smaller or cut down from a larger one (just cut off 2 pins leaving the plastic intact). Past experience with the MPU and displays (the LED forward voltage is >3V) have shown that the chip will easily support the dissipations encountered with 470R ballasts.

Where possible I like to use solder paste and reflow in a toaster over. A good source for solder paste is DealExtreme: Cool Gadgets at the Right Price - Site-Wide Free Shipping - DX, although there is a considerable delay in postage. Obviously solder paste can be obtained from sources closer at hand, but many suppliers like to ship fairly large quantities in an insulated package, to keep the temperature of the contents low. This can result in high prices and the quantities involved are greater than an amateur could reasonably use before it deteriorated. Solder paste is commonly used in commercial applications. If the paste fails to reflow suitably thousands of dollars worth of components can be affected in a production run. This can result in litigation in the worst cases. While this is understandable, the insistence on shipping large quantities in controlled circumstances is inconvenient to say the least, and the availability of small quantities from sites such as dealextreme is a way round this.

The MCU itself is a TQFP44. Soldering these by hand only requires the correct technique, which bears repeating here. Carefully apply solder to a corner pad of the PCB foil pattern. Slide the IC into place and secure the one pin. Adjust the positioning until you are completely happy with it. Now solder a single pin at the opposite corner. Starting with one of the unsecured edges, solder thickly and indiscriminately all the pins along that edge, pulling the solder bead from one end to another, making sure all pins on that edge are wetted. Now solder the remaining pins in the same manner. Remove the excess solder with a solder-sucker, working quickly to use as little heat as possible. If a string or sphere between 2 pins is difficult to remove, try re-applying some solder in that area and try again with the sucker.

w

post #10 of 19

When I do my vias, I set the board on a couple of popsicle sticks.

Then I stick my wire through, solder and snip; then repeat until

all the holes are filled. Then I flip the board over and solder the other side.

My way might be slower, but uses less wire. On the other hand, wire

is cheap...

post #11 of 19
Thread Starter 

In order to build this you need a PIC programmer. I have a PicKit2. It's a USB device. You can get a clone off ebay, but the saving over the genuine article isn't much.

 

Here's the BOM.

 

Resistors

24 R2-R25 470R 
1 R27 1k 
2 R28,R29,R30 10k 

Capacitors

3 C2-C4 100n 
2 C9,C10 2.2uF 

Integrated Circuits

1 U2 PIC16F887A-PT 
3 U3-U5 7SEGBLUE 
1 U7 78S05 

Transistors

1 Q1 BC108 

Diodes

3 D5-D7 DIODE 1N4001 
90 D8-D97 LED UV

Miscellaneous

1 TR1 TRANS-12V-20VA
1 J1 PIC_ICSP_HDR 
1 J2 CONN-H4 
1 J5 TBLOCK-I2 
1 RL1 G2R-14-DC12 
1 Large Veroboard

w

post #12 of 19
Thread Starter 

Software.

 

A couple of years ago I looked around for a BCD routine written under Mpasm, the free PIC assembler. I couldn’t find anything. I wanted to display the contents of the 10-bit PIC A/D register on 7-segment displays, effectively to build a digital meter. The routine here does this and can be used to build a meter with some analog circuitry added to process e.g. AC current to voltage or WHY.

The board is programmed with a Pickit2 USB programmer via an ISP header which is simply a 6-pin 0.1 pitch SMT pin-header, connected to the appropriate pins on the PIC. The Pickit2 is available for a comparatively low price from regular suppliers, and even cheaper as a clone from ebay. It is very simple to knock up a board with a socket and header which will permit the programming of a wide variety of conventional thru-hole PICs using the Pickit2. Although it is possible to build programmers running off the PC’s serial or parallel ports, the cost and effort mean that this is hardly worthwhile, and the Pickit2 is extremely versatile. There is now a Pickit3 available with (I believe) better debug facilities, but I have always found the PK2 to be adequate. Anyone who likes to be able to add a few digital features to a design should have one.

Since the display runs 000-999, a ten-bit buffer is required to contain the count. Arranging for this to overflow correctly is comparatively straightforward. The 3 input switches select amongst up- and down-counting routines while the program continuously cycles in one big loop. The loop processes the count in the buffer into 3 secondary Binary Corrected Decimal (hundreds, tens and units) buffers which are in turn processed into 7-segment display buffers. The process is comparatively straightforward, if tedious.

Each bit in the count buffer is examined and, if set, a corresponding number is added to the BCD registers, i.e. if BUF_HI, bit 1 is set, 5 is added to the hundreds count, 1 to the tens count and 2 to the units count, and so on, down to BUF_LO, bit 0, which is worth 1. When all the bits have been examined the BCD units buffer is reprocessed to move any accumulated tens to the BCD tens buffer by repeated subtraction of tens from the units buffer until a borrow occurs, when the units count is restored by adding ten. Similarly the BCD tens buffer is stripped of any accumulated hundreds. The size of the numbers involved is small enough that there is no risk of unintended overflows.

A simple delay routine at the end of the loop pads the time taken to execute to ~1 second. A second, shorter delay is switched in during the up and down setting routines after the buttons have been held down for a count of 5. This means that setting up a high count e.g. 600 does not become too tedious. The RC clock in the MPU is not guaranteed to keep accurate time, but the seconds delay can be trimmed to fair accuracy by timing the count over a minute or so and adding or subtracting a few cycles from the delay routine. On my board the accuracy is within 1 second per minute, which is plain lucky with such an uncomplicated delay routine.

The seconds delay means that, depending on where the routine is in the loop, there may be a brief wait for the system to respond to a button press, but I haven’t bothered to complicate the routine by eliminating that.

The relay can easily be used with a minor modification to the circuit to switch mains voltage if mains-driven fluorescents are used. In that case only a 5V supply would be required.

The accompanying circuit diagram shows the proper correspondence between the PIC port bits and the common-anode display pins. The displays used are 0.5in character height which are readily available at a reasonable price on ebay.

w

post #13 of 19
Thread Starter 

Hi, Avro_Arrow. Sounds not a lot different from my procedure.

 

Whatever floats your boat...

 

w

post #14 of 19

Thats a great light box and timer.

I use the set up in the tread here.

 

Maybe after my workshop gets build I'll be able to have

a better setup.

 

Great thread so far!

post #15 of 19
Thread Starter 
The CODE.​


Finally, the code. I hope the forum doesn't mangle the formatting...



#include <p16F887.inc>

__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

    cblock    0x20

BUF_LO
BUF_HI
BUF2HI
BUF2LO
BUF3HI
BUF3LO
THOUS
HUNS
TENS
UNITS
TH_DISP
HU_DISP
TE_DISP
UN_DISP
CTR
CTR2
CTR3
FLAGS
S_FLAG
C_FLAG
F_FLAG

    endc

ZERO        equ            B'10001000'
ONE         equ            B'11101011'
TWO         equ            B'01001100'
THREE       equ            B'01001001'
FOUR        equ            B'00101011'
FIVE        equ            B'00011001'
SIX         equ            B'00011000' 
SEVEN       equ            B'11001011'
EIGHT       equ            B'00001000'
NINE        equ            B'00001011'
DECIMAL     equ            B'00000011'

    org 0

start:
    banksel TRISE
    clrf    TRISE          ; Make PortE all output
    bcf     TRISE,0        ; Set RE0 to output
    bsf     TRISE,1        ; Set RE1 to input
    bsf     TRISE,2        ; Set RE2 to input

    bcf     STATUS,RP0     ; select Register Page 0
    bcf     STATUS,RP1     ; select Register Page 0
    clrf    PORTA
    bsf     STATUS,RP0     ; select Register Page 1
    clrf    TRISA          ; Make PortA all output
    clrf    TRISB          ; Make PortB all output
    clrf    TRISC          ; Make PortC all output
    clrf    TRISD          ; Make PortD all output
    movlw   0x80           ; right justify, Vdd and Vss as Vref
    movwf   ADCON1
    bsf     TRISA,0        ; Set RA0 to input
    bsf     STATUS,RP1     ; select Register Page 3
    clrf    ANSEL
    bcf     STATUS,RP1     ; select Register Page 1
    bcf     STATUS,RP0     ; select Register Page 0
    movlw   0xFF
    movwf   PORTB          ; turn off all outputs
    movwf   PORTC
    movwf   PORTD
    clrf    BUF_LO
    clrf    BUF_HI
    clrf    BUF2LO
    clrf    BUF2HI
    clrf    BUF3LO
    clrf    BUF3HI
    clrf    FLAGS
    clrf    S_FLAG

mainloop:    

    btfsc  C_FLAG,0        ; test the count flag
    goto   main2           ; execute count
    btfsc  PORTE,2         ; else test down bit
    goto   sw2
    btfsc  PORTE,1         ; test up bit
    goto   sw1
    btfsc  PORTA,0         ; test start bit
    goto   sw0
    clrf   FLAGS           ; if no button pressed
    clrf   S_FLAG          ; clear the short delay flag and counter
    goto   main2_done

sw2:

    btfsc  FLAGS,0         ; if short count flag set 
    goto   main1           ; else count down
    incf   S_FLAG          ; else count to 5
    btfss  S_FLAG,2        ; check for 4
    goto   main1           ; else count down
    btfss  S_FLAG,0        ; 4+1=5, so skip to set short count flag
    goto   main1           ; else count down
    bsf    FLAGS,0         ; set short count flag    
    goto   main1           ; and count down

sw1:

    btfsc  FLAGS,0         ; same as down count, but up
    goto   main0
    incf   S_FLAG
    btfss  S_FLAG,2
    goto   main0
    btfss  S_FLAG,0
    goto   main0
    bsf    FLAGS,0 
    goto   main0           ; and count up

sw0:

    bsf    C_FLAG,0        ; continuous count
    bsf    PORTE,0         ; turn on relay
    movfw  BUF2HI          ; store count for future reference
    movwf  BUF3HI
    movfw  BUF2LO
    movwf  BUF3LO
    goto   main2            ; start count

main0:

    movlw  0x01             ; upcount under button control
    addwf  BUF2LO,1         ; increment buffer memoryy
    btfsc  STATUS,Z
    incf   BUF2HI,1
    btfss  BUF2HI,1         ; check for 1000
    goto   main2_done
    btfss  BUF2HI,0
    goto   main2_done
    btfss  BUF2LO,7
    goto   main2_done
    btfss  BUF2LO,6
    goto   main2_done
    btfss  BUF2LO,5
    goto   main2_done
    btfss  BUF2LO,3         ; not 1000, continue
    goto   main2_done
    clrf   BUF2LO           ; else set buffer to 0
    clrf   BUF2HI
    goto   main2_done

main1:

    movlw  0x01             ; downcount under button control without switching on relay
    subwf  BUF2LO,1         ; decrement buffer memory
    btfsc  STATUS,C         ; carry bit is UNSET on borrow when decrementing
    goto   main2_done
    subwf  BUF2HI,1
    btfsc  STATUS,C         ; check for 000
    goto   main2_done
    movlw  0x03
    movwf  BUF2HI
    movlw  0xE7
    movwf  BUF2LO
    goto   main2_done

main2:

    movlw  0x01             ; downcount continuously with relay turned on
    subwf  BUF2LO,1         ; decrement buffer memory
    btfsc  STATUS,C         ; carry bit is UNSET on borrow when decrementing
    goto   main2_done
    subwf  BUF2HI,1
    btfsc  STATUS,C         ; check for 000
    goto   main2_done
    movfw  BUF3HI
    movwf  BUF2HI
    movfw  BUF3LO
    movwf  BUF2LO
    clrf   C_FLAG           ; discontinue count
    bcf    PORTE,0          ; turn off relay

main2_done:

    movfw  BUF2HI           ; transfer counting buffer to main register
    movwf  BUF_HI
    movfw  BUF2LO
    movwf  BUF_LO
    
    clrf    TH_DISP         ; clear display registers
    clrf    HU_DISP
    clrf    TE_DISP
    clrf    UN_DISP
    clrf    THOUS           ; clear BCD registers
    clrf    HUNS
    clrf    TENS
    clrf    UNITS
    btfss   BUF_HI,1        ; test buffer bits and distribute values to BCD registers
    goto    bitnine
    movlw   5
    addwf   HUNS,f
    movlw   1
    addwf   TENS,f
    movlw   2
    addwf   UNITS,f

bitnine:

    btfss   BUF_HI,0
    goto    biteight
    movlw   2
    addwf   HUNS,f
    movlw   5
    addwf   TENS,f
    movlw   6
    addwf   UNITS,f

biteight:

    btfss   BUF_LO,7
    goto    bitseven
    movlw   1
    addwf   HUNS,f
    movlw   2
    addwf   TENS,f
    movlw   8
    addwf   UNITS,f

bitseven:

    btfss   BUF_LO,6
    goto    bitsix
    movlw   6
    addwf   TENS,f
    movlw   4
    addwf   UNITS,f

bitsix:

    btfss   BUF_LO,5
    goto    bitfive
    movlw   3
    addwf   TENS,f
    movlw   2
    addwf   UNITS,f

bitfive:

    btfss   BUF_LO,4
    goto    bitfour
    movlw   1
    addwf   TENS,f
    movlw   6
    addwf   UNITS,f

bitfour:

    btfss   BUF_LO,3
    goto    bitthree
    movlw   8
    addwf   UNITS,f

bitthree:

    btfss   BUF_LO,2
    goto    bittwo
    movlw   4
    addwf   UNITS,f

bittwo:

    btfss   BUF_LO,1
    goto    bitone
    movlw   2
    addwf   UNITS,f

bitone:

    btfss   BUF_LO,0
    goto    bitzero
    movlw   1
    addwf   UNITS,f

bitzero:

    movlw   D'10'           ; move any tens to tens register
    subwf   UNITS,f
    btfsc   STATUS,Z
    goto    units_zero
    btfss   STATUS,C
    goto    units_carry   
    incf    TENS,f
    goto    bitzero

units_carry:

    movlw   D'10'
    addwf   UNITS,f
    goto    units_done

units_zero:

    incf    TENS,f

units_done:

    movlw   D'10'           ; move any hundredss to hundreds register
    subwf   TENS,f
    btfsc   STATUS,Z
    goto    tens_zero
    btfss   STATUS,C
    goto    tens_carry   
    incf    HUNS,f
    goto    units_done

tens_carry:

    movlw   D'10'
    addwf   TENS,f
    goto    tens_done

tens_zero:

    incf    HUNS,f

tens_done:

    movlw   D'10'
    subwf   HUNS,f
    btfsc   STATUS,Z
    goto    huns_zero
    btfss   STATUS,C
    goto    huns_carry   
    incf    THOUS,f
    goto    tens_done

huns_carry:

    movlw   D'10'           ; move any thous to thous register
    addwf   HUNS,f
    goto    huns_done

huns_zero:

    incf    THOUS,f

huns_done:
    
    movlw   1              ; test value in BCD units and set display registers 
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_1
    movlw   ZERO           ; move '0' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_1:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_2
    movlw   ONE            ; move '1' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_2:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_3
    movlw   TWO            ; move '2' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_3:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_4
    movlw   THREE          ; move '3' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_4:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_5
    movlw   FOUR           ; move '4' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_5:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_6
    movlw   FIVE           ; move '5' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_6:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_7
    movlw   SIX            ; move '6' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_7:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_8
    movlw   SEVEN          ; move '7' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_8:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    units_9
    movlw   EIGHT          ; move '8' to UN_DISP
    movwf   UN_DISP
    goto    tens_0

units_9:

    movlw   1
    subwf   UNITS,f
    btfsc   STATUS,C
    goto    tens_0
    movlw   NINE           ; move '9' to UN_DISP
    movwf   UN_DISP

tens_0:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_1
    movlw   ZERO           ; move '0' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_1:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_2
    movlw   ONE            ; move '1' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_2:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_3
    movlw   TWO            ; move '2' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_3:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_4
    movlw   THREE          ; move '3' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_4:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_5
    movlw   FOUR           ; move 4 to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_5:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_6
    movlw   FIVE           ; move '5' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_6:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_7
    movlw   SIX            ; move 6 to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_7:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_8
    movlw   SEVEN          ; move '7' to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_8:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    tens_9
    movlw   EIGHT          ; move 8 to TE_DISP
    movwf   TE_DISP
    goto    huns_0

tens_9:

    movlw   1
    subwf   TENS,f
    btfsc   STATUS,C
    goto    huns_0
    movlw   NINE           ; move '9' to TE_DISP
    movwf   TE_DISP

huns_0:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_1
    movlw   ZERO           ; move '0' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_1:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_2
    movlw   ONE           ; move '1' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_2:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_3
    movlw   TWO            ; move '2' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_3:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_4
    movlw   THREE          ; move '3' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_4:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_5
    movlw   FOUR           ; move '4' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_5:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_6
    movlw   FIVE           ; move '5' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_6:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_7
    movlw   SIX            ; move '6' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_7:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_8
    movlw   SEVEN          ; move '7' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_8:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    huns_9
    movlw   EIGHT          ; move '8' to HU_DISP
    movwf   HU_DISP
    goto    thous_0

huns_9:

    movlw   1
    subwf   HUNS,f
    btfsc   STATUS,C
    goto    thous_0
    movlw   NINE           ; move '9' to HU_DISP
    movwf   HU_DISP

thous_0:

    movlw   1
    subwf   THOUS,f
    btfsc   STATUS,C
    goto    thous_1
    movlw   ZERO           ; move '0' to TH_DISP
    movwf   TH_DISP
    goto    thous_2

thous_1:

    movlw   1
    subwf   THOUS,f
    btfsc   STATUS,C
    goto    thous_2
    movlw   ONE            ; move '1' to TH_DISP
    movwf   TH_DISP

thous_2:

    movf    UN_DISP,0      ; paint display registers onto 7-segment displays
    movwf   PORTC
    movf    TE_DISP,0
    movwf   PORTD
    movf    HU_DISP,0
    movwf   PORTB
    btfsc   FLAGS,0        ; fast/slow count switch
    goto    short2delay
    call    secdelay
    goto    mainloop

short2delay:

    call    shortdelay
    goto    mainloop

secdelay:

    movlw   0x05
    movwf   CTR3
    decfsz  CTR,1
    goto    $-1
    decfsz  CTR2,1
    goto    $-3
    decfsz  CTR3,1
    goto    $-5
    return     

shortdelay:

    movlw   0x3F
    movwf   CTR2
    decfsz  CTR,1
    goto    $-1
    decfsz  CTR2,1
    goto    $-3
    return     
    end

 

New Posts  All Forums:Forum Nav:
  Return Home
Head-Fi.org › Forums › Misc.-Category Forums › DIY (Do-It-Yourself) Discussions › A UV lightbox with exposure timer. A photo-PCB howto.