Designing a UV LED PCB Developer Box

Employing Python for minimum design parameters

Posted by Angel G. Miranda on January 15, 2018

If you want to design a homemade UltraViolet LED exposure box, you have come to the right place.

The following plot was generated with Python. On the right is the 2D projection that the LEDs will illuminate on the perpendicular surface. The idea is to modify the number of LEDs to cover as much area as possible to properly “cure” the photoresistive layer of the PCB.

With this code, you could calculate the minimum height from the UV LEDs to the perpendicular surface of the photoresistive film of the PCB to fully expose the surface. The only parameters you need to change are the box’s height, length and width, the aperture angle of the LEDs (theta) and the number of LEDs (x) parallel to the length. The number of LEDs parallel to the width are automatically calculated and stored in y. The second output is the minimum height where you have to place the LEDs.

The Code

##===================================================================================
##  Simple LED UV Box design
##  Written By: AG Miranda
##  Date: 2016/01/13 yyyy/mm/dd
##===================================================================================
import math as math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib import cm

##Givens
H = 8   #Box's height
L = 18  #Box's Length
W = 13  #Box's Width
theta = 25
x = 9

##Calculations
d = L/(2 * x)
x_center = (L - x * 2 * d)/2

y = W /(2*d)
y = int(y)
y_center = (W - y * 2 * d)/2

theta = math.radians(theta)
h = d * math.cos(theta) / math.sin(theta)

if h > H:
    print('Error: The minimum height is higher than the box''s height: ' + repr(h) + ' > ' + repr(H))
else:
    print('The minimum height is: ' + repr(h))

## Design Re-adjustment
h = h * 1.4 # works pretty well
proj_d = h * math.sin(theta) / math.cos(theta)
if h > H:
    print('Error: The minimum height is higher than the box''s height: ' + repr(h) + ' > ' + repr(H))
else:
    print('The Rule-of-Thumb height is: ' + repr(h))

##Plot related
points = 7  # number of sides = points - 1
fig = plt.figure()
ax = fig.add_subplot(121, projection='3d')
ax2 = fig.add_subplot(122)
plt.hold(True)

##>For the 3D plot
##>> Polar Coordinates
r = np.linspace(0, proj_d, points)
phi = np.linspace(0, 2*np.pi, points)
R, P = np.meshgrid(r, phi)
##>>Cartesian system transformation
X, Y = R*np.cos(P), R*np.sin(P)
Z = np.linspace(h, 0, points)

##>For the 2D plot
##>>Create a circle
points_2d = 36
r_2d = np.linspace(proj_d, proj_d, points_2d)
phi_2d = np.linspace(0, 2*np.pi, points_2d)
R_2d, P_2d = np.meshgrid(r_2d, phi_2d)
X_2d, Y_2d = R_2d*np.cos(P_2d), R_2d*np.sin(P_2d)

## Graphing ALL plots
for i in range(x):
    for j in range(y):
        ax.plot_surface(X+d*(i*2+1), Y+d*(j*2+1)+y_center, Z, rstride=1, cstride=1, cmap=cm.YlGnBu_r)
        ax2.plot(X_2d+d*(i*2+1), Y_2d+d*(j*2+1)+y_center)
        
ax.set_xlim3d(0, L)
ax.set_ylim3d(0, W)
ax.set_zlim3d(0, H)
ax.set_xlabel('Length')
ax.set_ylabel('Width')
ax.set_zlabel('Height')

ax2.set_xlim(0, L)
ax2.set_ylim(0, W)
ax2.set_xlabel('Length')
ax2.set_ylabel('Width')

plt.show()