
Top of the box with a ruler for scale.
I just finished designing and building a (12.5″)x(12.5″)x(6″) ultraviolet light box with a pic16f54 microcontroller programmed as a timer for the exposure. It was made mostly to be a UV light source for exposing photosensitive film used as an etch-resist in the process of making printed circuit boards. It can also be used as a weapon against vampires.

Close-up of the controller board (upside down! Muahahah!).
The red LED indicates power is connected to the microcontroller (controlled by the small switch in the corner or just by unplugging the wall-wart). Pressing the round black button adds 30 seconds two minutes to the timer, which is indicated in binary on with the 8 orange LEDs; it is limited to 255 seconds (4 minutes, 15 seconds) and suffers overrun if you press the button enough times 16 minutes and doesn’t loop back to zero. Power is applied to the ultraviolet LEDS whenever the timer is greater than zero, which can be indicated by (a) the yellow LED indicating the UV lights are on, (b) the green led blinking once per second as the timer counts down, or (c) the bottom of the box emitting a faint blue glow. The assembly code I spent an afternoon writing can be found at the bottom of this post, if you are curious (My first real ASM program! It was actually kinda fun!).

Inside of the light box; still not sure what the cat likes about this place, but he sure likes trying to get in there.
Measurements indicated that the ultraviolet LEDs are using 29.1[mA] each, so the box should be outputting a total luminous intensity of at wavelengths between 350[nm]-420[nm] (peak @~380[nm]). The MG Chemicals photoresist film that I use has an exposure sensitivity between 315[nm]-400[nm], with a peak response at 355[nm]-380[nm] (good design, huh? ;D).
The UV LED array has a square spacing of 2.5″, meaning the center of four adjacent LEDs is away from any given led. Using the Radiation Diagram from the datasheet, the minimum surface distance from the tip of the LEDs at which the light cone would be at 25% intensity at these centers is then
. I interpret this as the minimum distance an object needs to be from the UV LEDs in order for the light to be relatively uniform across the whole surface. Beyond this distance, it should become even more uniform; fortunately, my two glass plates, a standard 1/16″ copper clad board, photoresist film, and artwork transparencies add up just under 3/8″, so all is well for my application. The largest copper clad board I ever plan to use is 8″x10″, so my 2.5″ spacing works to keep the UV light at a decent intensity on the edges. UPDATE: Unfortunately, this is not the case, as tests have shown that the board needs to be at least another 1/2 inch from the LEDs. This may have something to do with where you measure from, exactly, but there are visibly contrasting regions visible on a white sheet of paper. The solution I have in mind will be to simply extend the bottom of the box.
; Timer for UV Light Box Control ; Initially off. Waits for input to set length of ON time, waits for lack of input, then starts. PORTB acts as indicator of number of 2xminutes to set timer. ; PIC16F54 @ 3.579545 MHz ; Drew Jaworski 2012 #include <p16f5x.inc> __CONFIG _HS_OSC & _WDT_OFF & _CP_OFF UDATA ; delay counter vars dc1 res 1 dc2 res 1 dc3 res 1 ptm res 1 ; 120 second run timer PROG CODE init movlw b'11110010' ;RA0 is UV control output, RA1 is timer increment button input (active low), RA2 is clock indicator LED output, RA3 is UV on indicator tris PORTA movlw 0x00 ;RB7-RB0 are time display outputs tris PORTB start movlw 0x00 ;set all outputs OFF initially movwf PORTA movlw 0x00 ;initial time to display movwf PORTB movlw 0x78 ; initial 2xminute run timer setting (120) movwf ptm wait_start btfsc PORTA,b'001' ;check button status goto wait_start ;skip back if button was not pressed wait_input ;delay 0.25 seconds movlw 0xC7 movwf dc1 movlw 0xAF movwf dc2 Delay_2 decfsz dc1, f goto $+2 decfsz dc2, f goto Delay_2 ;end delay btfsc PORTA,b'001' ;check button status goto begin_run_timer;start if button was not pressed btfsc PORTB,b'000' goto $+3 bsf PORTB,b'000' goto wait_input btfsc PORTB,b'001' goto $+3 bsf PORTB,b'001' goto wait_input btfsc PORTB,b'010' goto $+3 bsf PORTB,b'010' goto wait_input btfsc PORTB,b'011' goto $+3 bsf PORTB,b'011' goto wait_input btfsc PORTB,b'100' goto $+3 bsf PORTB,b'100' goto wait_input btfsc PORTB,b'101' goto $+3 bsf PORTB,b'101' goto wait_input btfsc PORTB,b'110' goto $+3 bsf PORTB,b'110' goto wait_input btfsc PORTB,b'111' goto wait_input bsf PORTB,b'111' goto wait_input begin_run_timer bsf PORTA,b'000' bsf PORTA,b'011' run_timer ;delay 0.5 seconds movlw 0xAF movwf dc1 movlw 0xFA movwf dc2 movlw 0x01 movwf dc3 Delay_0 decfsz dc1, f goto $+2 decfsz dc2, f goto $+2 decfsz dc3, f goto Delay_0 goto $+1 goto $+1 nop ;end delay bsf PORTA,b'010' ;set led ;delay 0.5 seconds movlw 0xAF movwf dc1 movlw 0xFA movwf dc2 movlw 0x01 movwf dc3 Delay_1 decfsz dc1, f goto $+2 decfsz dc2, f goto $+2 decfsz dc3, f goto Delay_1 goto $+1 goto $+1 nop ;end delay bcf PORTA,b'010' ;clear led decfsz ptm,f ; decrement run_timer goto run_timer ;continue next cycle if iwt decrement result was not zero movlw 0x78 movwf ptm ;reset run timer if it hit zero ;also remove a minute from timer btfss PORTB,b'111' goto $+3 bcf PORTB,b'111' goto run_timer btfss PORTB,b'110' goto $+3 bcf PORTB,b'110' goto run_timer btfss PORTB,b'101' goto $+3 bcf PORTB,b'101' goto run_timer btfss PORTB,b'100' goto $+3 bcf PORTB,b'100' goto run_timer btfss PORTB,b'011' goto $+3 bcf PORTB,b'011' goto run_timer btfss PORTB,b'010' goto $+3 bcf PORTB,b'010' goto run_timer btfss PORTB,b'001' goto $+3 bcf PORTB,b'001' goto run_timer btfss PORTB,b'000' goto run_timer bcf PORTB,b'000' goto start ;reset everything if time has run out END
