|
Diferenciando
los agujeros y el borde de las pistas del circuito impreso:
El objetivo del
programa es interpretar una imagen en mapa de bits con el dibujo un circuito por
la cara de pistas. Debería reconocer el borde de todas las pistas y los
agujeros para ordenar a la fresadora que mecanice la placa. Esto no se puede
hacer de cualquier manera sino que cada punto de los bordes debe ser detectado
siguiendo un orden secuencial ya que en este mismo orden se desbastará el cobre
en la placa.
El algoritmo
que utilizo permite de un solo paso detectar todos los bordes correctamente y al
mismo tiempo diferenciar cuales son agujeros para que la maquina también pueda
taladrar automáticamente.
Hay que tener
en cuenta que la herramienta de la fresadora tiene un ancho y, por tanto, hay
que desbastar siguiendo el borde pero separado de él una distancia R para que
la maquina no destroce también la pista. R es el radio de la punta de desbaste.
Para conseguir esto ejecuto este mismo algoritmo N veces hasta que las pistas
engordan (virtualmente) lo suficiente como para compensar este efecto. Cada vez
que se ejecuta se añade el borde calculado a la imagen real para aumentar el
grosor de las pistas. (El reconocimiento de los agujeros se hace solo la 1º
vez).
Se puede
entender todo el código del programa dividiéndolo en 3 partes conceptuales
aunque realmente están demasiado entrelazadas como para separarlas. Hay una
parte general que controla todo el flujo del programa, otra que detecta todo el
borde de cada pista, y otra que diferencia los agujeros.
Se hace un barrido de toda la
imagen que mira uno a uno todos los píxeles de izquierda a derecha y de
arriba abajo. Se mira el color del píxel, que solo puede ser o blanco (no hay
pista) o negro (hay pista). Cuando se detecta un cambio de blanco a negro al
pasar de un píxel al que está a su derecha entonces se da cuenta de que ha
dado con una pista y se ejecuta el algoritmo de detección del borde. Cuando
se ha rodeado por completo esa pista se vuelve al punto anterior y se continúa
con el barrido buscando otra pista nueva. Para evitar que se repita la detección
de la misma pista varias veces he incluido una matriz en la que cada valor del
punto (x,y) tiene memorizado si pertenece a una pista ya encontrada o no.
Además tuve que hacer que el
programa considerara que los puntos fuera de la imagen son blancos así no
puede trabajar con placas cuyas pistas tocan el borde de la imagen sin dar
errores raros...
Como dije en la introducción se
debe tener en cuenta el grosor de la herramienta y por tanto hacer que
desbaste siguiendo un borde un poco alejado del borde real y así no destruir
las pistas que sean delgadas. La manera más fácil que se me ocurrió de
detectar un borde separado del real es hacer este proceso descrito
anteriormente varias veces y añadiendo cada borde hallado a la imagen real
engordando las pistas. El número de veces que se repita este proceso equivale
al número de píxeles que se separa la herramienta de la pista. Cuando se
conozca la relación entre píxel y distancia física sobre la placa se
modificará este parámetro automáticamente indicando cual es el diámetro de
la herramienta.
-
Reconocimiento de los agujeros
Esto se realiza al mismo tiempo
que la detección de los bordes. Cada vez que el control de flujo explicado
anteriormente encuentra una nueva pista pone a cero una variable llamada
HoleLong que medirá el número de puntos que tiene el borde de esa pista, es
decir su perímetro. A cada nuevo punto encontrado de este borde HoleLong se
incrementa en uno.
En el caso de que la pista que
se está rodeando sea un agujero entonces este perímetro es justamente la
longitud de la circunferencia de este agujero. Entonces para discriminar ya
con mucha precisión cuales son agujeros e determinado que, por ejemplo las
pistas con un perímetro HoleLong menor que 25 son razonablemente pequeñas y
por tanto pueden ser un agujero.
Ahora suponiendo que lo es se
procede a calcular su centro. Para ello teniendo el perímetro lo más fácil
que se me ocurrió fue ir almacenando en una lista todos los puntos (x,y) del
perímetro (esto se realiza mientras se haya el borde). Sabiendo qué puntos
son se puede trazar una recta atravesando la circunferencia y dividiendo su
longitud en dos se haya el centro. Para hacer esta recta necesito dos puntos.
Uno es el ultimo de la lista que tengo y el otro es aquel que está justo en
la mitad de la lista, es decir "longitud de circunferencia" / 2

Para el ejemplo de la imagen
HoleLong = 12 ya que el borde encontrado (puntos rojos) contiene 12 píxeles.
Aunque en el ejemplo puse el 1 en lugar equivocado (tenia que esta en el lugar
del 7), el efecto sería el mismo.
Si el ultimo píxel tiene las
coordenadas Xf, Yf, el que está en la mitad del perímetro es Xm, Ym y el
centro del agujero es Xc, Yc:
Xc = (Xf + Xm)/2
y Yc = (Yf + Ym)/2
Con esto ya llega para detectar
todos los agujeros de la placa pero así se detectarán también algunas cosas
que no son agujeros, como puntos negros y pequeños en la placa o algo
parecido a un agujero pero con forma no circular, que puede ser por ejemplo el
hueco de una letra para escribir en el cobre. Conociendo el centro ahora se
pueden discriminar estos con bastante facilidad:
Los puntos negros se diferencian
obviamente mirando el color del punto central, si este es negro es que no es
un agujero.
Pero para determinar que la
forma es aproximadamente circular hay que complicarse algo más la vida, como
hacer un barrido siguiendo una circunferencia de radio un poco mayor que el
real y ver que todos sus puntos son negros, así se entiende que los blancos
están contenidos y por tanto es un agujero. Pero este no es el método que he
usado porque al probarlo rechazaba algunos agujeros verdaderos. Esto es culpa
de la mala resolución y la imperfección de los agujeros.
Así que he probado otro método
menos preciso pero más rápido y más eficaz teniendo en cuanta las características
que suele tener una placa...
Consiste simplemente en medir el
diámetro en dirección del eje X pasando por el centro y hacer lo mismo
midiendo según la dirección del eje Y. Comprobar si son prácticamente
iguales (aplicando un margen de error ajustable por el usuario). Si lo son se
entiende que es un agujero por tener un diámetro constante. Aún así no
diferenciaría por ejemplo una elipse oblicua de un agujero pero esa es una
situación prácticamente imposible.
Por este método se detectan
absolutamente todos los agujeros de la placa independientemente de su diámetro
(hasta un máximo ajustable) y discrimina prácticamente todas las cosas
parecidas a un agujero que se podrían confundir. Aún así sigue siendo
imposible diferenciar por ejemplo el hueco de la letra "o" escrita
en la placa, aunque la letra sea cursiva. Hay algunos tipos de letra alta o
inclinada que son ideales para esto pues no los confunde. Aún así estoy ya
conforme pues si de 200 agujeros selecciona por error 3 de más estos se
pueden eliminar manualmente antes de grabar la placa con otra aplicación que
haré para quitar y poner agujeros nuevos.
Aunque no lo he hecho todavía,
no sería nada difícil hacer que diferencie los diámetros de los agujeros
para ordenar a la máquina pararse para cambiar de broca.
Para esto empleo un algoritmo
intuitivo aunque más difícil de implementar de lo que parece. Basándome en
que todas las pistas y agujeros de la placa son conjuntos acotados de puntos
(están limitados por las dimensiones de la placa) se puede considerar que
cada nudo del circuito eléctrico tiene una pista que está aislada de las demás
y por tanto se puede bordear por completo.
Una vez detectada una pista
nueva con el control de flujo, se entra en un bucle que explora uno a uno
todos los puntos de su borde hasta que llega al punto por el que había
empezado, entonces sale del bucle y vuelve al control general.
La pregunta es ¿Como hace un
programa para saber cual es el siguiente punto del borde?
Sencillamente hay que explorar
todos los puntos adyacentes al actual en sentido de las agujas del reloj hasta
que detecte de nuevo un cambio de color blanco a negro. En este momento
descubre un nuevo punto del borde y realiza lo mismo pero girando alrededor de
este nuevo punto.

Para entenderlo de manera más
precisa he hecho la imagen de arriba. Hay que leerla de izquierda a derecha y
de arriba abajo. Se presentan 14 situaciones que ocurren una detrás de la
otra para acabar rodeando por completo la hipotética pista eléctrica, que
son los píxeles negros.
Los puntos negros son puntos de
la pista que aun no han sido encontrados por el programa.
Los puntos azules son aquellos
que ya han sido detectados y que forman parte del borde.
El punto rojo se corresponde con
el pixel del borde que ha sido encontrado previamente y alrededor del cual se
busca otro nuevo punto girando en sentido CW.
Este giro de búsqueda lo indico
con la flecha roja, que acaba naturalmente donde encuentra un nuevo punto de
la pista y empieza desde una posición (ángulo) calculada previamente.
Las flechas azules indican el
giro de búsqueda que se realizo anteriormente y por el cual se encontró el
punto rojo (actual).
El cuadrado con contorno verde
es el que indica la posición desde la que se debe empezar a buscar. Observar
la relación que hay entre las flechas azules y los cuadrados verdes. El
cuadrado verde se coloca en aquella posición que resulte de prolongar el
radio de giro de la flecha verde en el momento en que acaba. Así que, por
ejemplo, en la fase numero 3 como la flecha azul llega por abajo al punto rojo
(con un ángulo de 270º), el cuadrado verde se pone en la posición 45º más
adelante, es decir, 315º. Hay que considerar el punto rojo como el centro de
estos ángulos.
En la fase numero 1 el punto
rojo ha sido encontrado por el programa de control de flujo mientras hacía el
barrido de izquierda a derecha, por eso la flecha azul es recta y no un arco.
Como se ve aunque un punto
determinado del borde ya haya sido explorado este se vuelve a detectar si el
programa vuelve a pasar por el (por causa de que la pista tiene anchura de 1 píxel
en ese punto). Esto no importa en absoluto.
Todos los puntos que va
detectando (azules) se almacenan en una lista indicando sus posiciones X,Y
para posteriormente enviar a la maquina y los trabaje secuencialmente. Se
almacenan seguidos incluso los puntos pertenecientes a pistas diferentes ya
que cuando cuando el programa de grabado detecte una distancia mayor que 1
entre el punto que se esta desbastando y el siguiente ordenará a la máquina
que se pare, levante el taladro de la placa, lo posicione en el nuevo punto,
encienda de nuevo, baje y continúe...
|