Tutoriales de Electrónica Básica
TUTORIAL DE CNC:

Aquí comenzamos una nueva sección de la web, pensaba inaugurar otra dedicada exclusivamente a este tema, pero bueno, luego veremos si es necesario o no, por lo pronto aquí queda instalada.

CNC - PROGRAMACION (Parte VII)

Graficadora de Imágenes:

Para que nuestra máquina pueda Desplazarse sobre la superficie de trabajo y Trazar el gráfico necesitamos tener comunicación con ella, para lo cual es indispensable disponer de una interfaz que haga de intermediaria entre ambos, la que utilizamos con mis alumnos, se encuentra descrita en la sección de electrónica, pero la describiré aquí en pocas palabras...

El control de la Máquina, se hará utilizando todos los pines de salida del Puerto Paralelo, sip, sin microcontrolador ni nada de eso, no se incluyeron sensores en los circuitos, tampoco encenderemos el taladro de forma automática, ni tiene dispositivos de enfriamiento ni nada por el estilo, es así, bien a lo aprendiz, más adelante cuando ya avancemos más en el tema, le agregaremos todos esos chiches, está...?

Comencemos entonces, Quieres ver cuál es el programa...? Bueno, no te sorprendas demasiado, tiene una vista muy similar a otro que ya conocemos...

Y es que no me gasté demasiado en la cara del programa como verás, Oye...!!! no estarás pensando que esos gráficos espectaculares los hice yo...!!!, Nooooooo...!!!, nada que ver, esos los bajé de la web, y si mal no recuerdo, creo que son de la web de Luberth, lo único que hice fue retocar una que otra cosa en los códigos de la imagen (por lo visto Luberth también los retocó para leerlos, parece que tuvo los mismos problemas que yo al armar sus programas), y el resto, bueno, queda en manos del programa que es el encargado de leerlos y trazarlos.

Bien, ahora sí, comenzamos en serio...

Desplazarse sobre la superficie de trabajo y Hacer el gráfico, son dos cosas distintas, como te habrás dado cuenta, así que lo tomaremos con pinzas e iremos por partes.

Desplazarse sobre la superficie de trabajo

El desplazamiento sobre la superficie de trabajo es muy sencillo, ya que sólo debes controlar dos motores, el único inconveniente es que el movimiento de ambos debe estar coordinado para que sea uniforme, parejo, no pierdas pasos en el giro de los motores, y etc. etc. etc. La pregunta aquí es, Cómo se logra todo esto...?, y la respuesta está en la interfaz y el tipo de motores a utilizar, debes conocerlos bien para saber cómo manejarlos, es más , los motores deben ser iguales, (me refiero al ángulo de giro, que es equivalente a la cantidad de pasos).

Los motores que utilizamos nosotros, pertenecen a una vieja impresora HP, y son de tipo Unipolar, es decir, para controlar este motor, necesitamos 4 señales, que se irán secuenciando de alguna manera. La forma de secuenciar estas señales, define el ángulo de desplazamiento de cada paso del motor y el torque que se produce en su interior, si anduviste por el Tutorial de Motores PaP, sabrás que hay 3 formas de controlar estos motorcillos, a saber...

  • A pasos completos: se alimenta una Bobina por vez.
  • A pasos completos: igual que el anterior pero alimentando dos Bobinas por vez, para obtener mayor fuerza de giro.
  • A Medio Paso: Es una combinación de los dos anteriores.

No voy a hablar mucho de eso, es un tema que ya vimos antes y puedes verlo cuando quieras. El que yo utilizaré en este programa corresponde al tercer modo de control.

La cosa es que, el desplazamiento sobre la superficie es en 2 dimensiones, y no hay que preocuparse de si se está trazando o no, y como es en 2D, solo necesitamos 2 motores, y como cada motor tiene cuatro hilos por los cuales enviar señales, necesitamos 8 bits de control.

Por otro lado, la interfaz es tan sencilla que lo único que hace, es amplificar la señal enviada por la PC en cada uno de los bits de salida, Cómo lo hace...?? Bueno, Lo primero que tiene es un conector DB25, que transfiere la señal tal como viene a un Buffer 74LS245, que de alguna manera actúa como separador, manteniendo un cierto nivel reconocible de señal. Los mismos valores lógicos de cada bit, se envían a un Array de Transistores que también describimos en secciones anteriores, el ULN2803, usé este por que la cantidad de corriente que maneja es suficiente para estos Motores PaP, el único problema aquí es que el ULN invierte las señales de salida, o sea cuando envías un 1 Lógico, el ULN entregará un 0 Lógico.

Por suerte para nosotros, el hilo común de las bobinas de un Motor PaP, va unido al positivo de la fuente de alimentación, mientras que las señales requeridas para controlarlas deben ser de naturaleza negativas (0 Lógico), es decir, lo que parecía un problema no lo es, es más, está todo a favor de nosotros.

Ya está todo claro, necesito 8 bit, y con ellos controlo dos motores, uno unido al EjeX y otro al EjeY, la cuestión es, Cuáles de los 12 bit de salida voy a utilizar, y por alguna razón decidí tomar el registro de Datos del LPT, que tiene justamente 8 Bits.

Como ambos motores deben moverse en forma simultánea, hay que ver cómo hacemos, yo opté por utilizar matrices, donde cada elemento de la matriz tiene el valor que corresponde a la combinación de bits que activan un movimiento.

Lo que viene ahora es la definición de esos valores, siempre refiriéndome al Registro de Datos, aquí va...

ELEMENTO DE CADA MATRIZ Y
ASIGNACIÓN DE VALOR DECIMAL
VALOR BINARIO
BitEjeX(0) = 1' 0000  0001
BitEjeX(1) = 3' 0000  0011
BitEjeX(2) = 2' 0000  0010
BitEjeX(3) = 6' 0000  0110
BitEjeX(4) = 4' 0000  0100
BitEjeX(5) = 12' 0000  1100
BitEjeX(6) = 8' 0000  1000
BitEjeX(7) = 9' 0000  1001
 
BitEjeY(0) = 16' 0001  0000
BitEjeY(1) = 48' 0011  0000
BitEjeY(2) = 32' 0010  0000
BitEjeY(3) = 96' 0110  0000
BitEjeY(4) = 64' 0100  0000
BitEjeY(5) = 192' 1100  0000
BitEjeY(6) = 128' 1000  0000
BitEjeY(7) = 144' 1001  0000

Como se puede ver, son dos matrices distintas, una para cada motor, al Motor del EjeX los 4 bits Menos significativos, y al del EjeY los Más significativos. Ahora, si se desea mover los dos motores a la vez, lo que debes hacer es sumar los valores de los elementos correspondientes al paso que deseas dar, que dicho en código de programación sería algo así...

nBitx = Int(nPrevx) Mod 8
nBity = Int(nPrevy) Mod 8
Call PortOut(888, BitEjeX(nBitx) + BitEjeY(nBity))

Hay cosas aquí que también nos resultan muy familiares, por ejemplo, nPrevX y nPrevY son los valores actuales de la ubicación en donde se está pintando un píxel, ahora describamos el resto...

Int(nPrevx) es una función que devuelve el entero del valor que se pasa como parámetro.

Mod Es un operador matemático, lo que hace es devolver el resto de dividir el primer número en el segundo, en nuestro ejemplo, divide nPrevx por 8, tantas veces como sea necesario y finalmente devuelve el resto de esa división, que pueden ser 8 valores, que van de 0 a 7, ese valor se almacena en una variable llamada nBitx, y nBity para cada caso.

nBitx y nBity son los índices que identifican a cada elemento de la matriz, matriz que se definió previamente, que como acabo de decir puede ser cualquier valor entre 0 y 7.

PortOut es un sub-procedimiento que debe estar definido en el encabezado del programa, este procedimiento se encuentra en un archivo IO.dll, tema que también ya hablamos en tutoriales anteriores, pero bueno, el procedimiento se llama de la siguiente forma...

Call PortOut(Número_Puerto, Dato)

En nuestro caso Número_Puerto es 888, que vendría a ser el Registro de Datos del Puerto Paralelo, y es con el que estamos controlando los dos motores.

Dato es un número de tipo Byte, que representa el dato a enviar, su máximo valor es 255, es decir, todos sus bits en 1 (11111111)

Veamos como obtenemos el valor de Dato.

Call PortOut(888, BitEjeX(nBitx) + BitEjeY(nBity))

Suponte que nBitx=3 y que nBity=4, entonces quedaría así...

Call PortOut(888, BitEjeX(3) + BitEjeY(4))

En este ejemplo, el elemento BitEjeX(3) de la matriz BitEjeX es 6, y el elemento BitEjeY(4) de la matriz BitEjeY es 64, y la suma de ambos será 70, entonces, la llamada a PortOut quedaría...

Call PortOut(888, 70)

y ese sería el dato que se envía al puerto, pero no conforme con ello, lo veremos en forma binaria, y 70 en binario es 01000110...

Qué?..., Oh...!!! Casualidad, 64(decimal)=01000000(binario) y 6(decimal)=0110(binario)

Quedó claro, verdad...?, bueno, con esto ya hemos logrado controlar los motores PaP que están unidos al Puerto Paralelo en el Registro de Datos, pero nos queda uno más que es el que controla si se grafica o no, entonces vamos por...

Trazar el gráfico

Esto es como en toda máquina, siempre debe haber un orden de prioridad de movimiento, en nuestro caso la prioridad la tendrá el eje que mueve la herramienta de trabajo, es decir, el tercer eje, el Eje Z. Imagínate que la instrucción fuese PU200,245, lo primero que deberé hacer será PU, y luego 200,245

PU es no trazar, o Pen-Up, o Subir la Herramienta, en nuestro caso, mover el Eje Z para levantar nuestro Mini-Taladro, y luego de eso recién desplazarme hacia el punto 200,245

No sé si quedó claro, bueno, espero que sí, lo que vamos a ver ahora es como controlar este Eje Z

El primer problema que se nos plantea es que los bits de este registro están invertidos, bueno, algunos de ellos, más específicamente el bit3, bit1 y bit0, así que nos la arreglaremos, y aquí vamos

Elemento de c/Matriz
Asignación Decimal
Binario no invertido
Enviado al Puerto
Binario Invertido
Saliendo del Puerto
BitEjeZ(0) = 10' 0000  1010' 0000  0001
BitEjeZ(1) = 8' 0000  1000' 0000  0011
BitEjeZ(2) = 9' 0000  1001' 0000  0010
BitEjeZ(3) = 13' 0000  1011' 0000  0110
BitEjeZ(4) = 15' 0000  1101' 0000  0100
BitEjeZ(5) = 7' 0000  0111' 0000  1100
BitEjeZ(6) = 3' 0000  0011' 0000  1000
BitEjeZ(7) = 2' 0000  0010' 0000  1001

El valor Binario no invertido es el valor tal como lo envías al puerto, pero como este invierte los bitS 3,1 y 0, pues el resultado de esa inversión es el que tendremos en la salida, podrías hacer la prueba de invertirlos para ver si es cierto, no crees...? Bueno, ahí queda...

Lo que toca hacer, es averiguar qué instrucción P es la que se va a ejecutar, según eso subimos o bajamos nuestra herramienta, y esa instrucción está almacenada en una variable llamada cCodigoP, si es "PU" giramos en un sentido para subir el taladro, y por supuesto utilizando nuestra función MOD, pero nos está faltando algo más...

Hasta dónde debemos subir, o bajar...??? Bueno, ese dato se leerá del cuadro de texto llamado txtProfundidad que será el punto máximo al que deberá bajar, y se cargará en una variable llamada nNewz, hay otra llamada nPrevz, que inicialmente arranca en cero, en realidad esta última almacena la posición actual de la herramienta. Vamos de nuevo...

Si la instrucción es "PU" significa que está abajo, por lo que deberá subir hasta la posición cero, y no saldrá de aquí hasta que alcance esa posición. y qué pasa si es que ya estuviera arriba...? Pues muy sencillo, no hará nada, y seguirá con el flujo del programa, pero veámoslo en código, cómo quedaría...

  1. '************************************************************
  2. 'Desplazamiento para el eje z
  3. '-----------si el taladro está abajo debe subir-------------
  4. If cCodigoP = "PU" Then
  5.     nBitz = 0
  6. Subir:
  7.     VelocPerf = (15 - hscPerforacion.Value) * 10  'veloc. para subir
  8.     If nPrevz > 0 Then                    'sube hasta la posición 0
  9.        nPrevz = nPrevz - 1
  10.         nBitz = Int(nPrevz) Mod 8
  11.         Call PortOut(890, BitEjeZ(nBitz))  'manda el dato al puerto
  12.         'Retardo
  13.         For TT = 1 To VelocPerf
  14.             For T = 1 To 10000: Next T
  15.         Next TT
  16.         GoTo Subir
  17.     End If
  18.     'de ahora en más el taladro permanece arriba
  19. End If

Lo que ves en azul es el salto que no nos deja salir de este bloque de código hasta que el taladro alcanza la posición indicada, otro detalle a tener en cuenta es que la llamada al puerto se hace por el registro 890 que es el registro de control, no lo olvides.

Como puedes ver, nPrevz va disminuyendo hasta hacerse cero, y el bucle For...Next es simplemente un retardo, hay por allí una variable llamada VelocPerf, que no es otra cosa que el valor de la posición dado por el Scroll de velocidad de Perforación, hay un cálculo innecesario que yo agregué para mis alumnos, y más que nada para que pudieran entender que a medida que va aumentando el valor del Scroll, la cantidad de repeticiones del bucle va disminuyendo, y bueno, que quieres, ellos lo comprendieron mejor así, y hay que adaptarse a ellos, así que así quedó, pero tú puedes arreglarlo para que quede mejor, está...???

Algo muy similar ocurre cuando la instrucción es "PD", sólo que en este caso el valor de nPrevz es cero, y se va incrementando hasta alcanzar la profundidad programada (nNewz), mira cómo quedaría...

  1. '-----------si el taladro está arriba debe bajar------------
  2. If cCodigoP = "PD" Then
  3.     nBitz = 0
  4. Bajar:
  5.     VelocPerf = (15 - hscPerforacion.Value) * 10  'veloc. para bajar
  6.     If nPrevz < nNewZ Then  'baja hasta la posicion indicada en nNewZ
  7.         nPrevz = nPrevz + 1
  8.         nBitz = Int(nPrevz) Mod 8
  9.         Call PortOut(890, BitEjeZ(nBitz))   'manda el dato al puerto
  10.         'Retardo
  11.         For TT = 1 To VelocPerf
  12.             For T = 1 To 10000: Next T
  13.         Next TT
  14.         GoTo Bajar
  15.     End If
  16. 'de ahora en más el taladro permanece abajo
  17. End If

Bueno, aquí es donde aparece nuestra variable llamada nNewz, que siempre será fija una vez comience a trazar, si prestas atención, esta vez la comparación no es con cero como en el caso anterior, sino con la variable nNewz, y el resto ya lo conoces.

Bien chicos, hemos llegado al final de esta sección, pero no sin antes dejarles el fuente para que jueguen un rato, pero aprendiendo ok..??? Esto es para practicar, ver cómo se puede optimizar el código y que otras posibilidades de control se pueden aplicar, por supuesto, no olviden contarme como les fue, y colaboren Che...!!! después de todo...!!! Ahora me voy a dormir, porque ya me dio sueñito, bye...

Aquí queda...

Cordiales Saludos...

R-Luis...