Poner proyector láser de piezas disponibles

UPD: archivos se añaden a la placa DAC GitHub

Originalmente planeado para hacer Лазерную arpa , pero sin embargo para obtener el resultado intermedio - un dispositivo que puede ser utilizado como un proyector láser - láser para dibujar diferentes figuras grabadas en el formato de archivo de ILDA. Soy consciente de que muchos de los que ocupan el montaje del proyector de láser, como un dispositivo para controlar galvanómetro (y no entendía la mejor manera de traducir en mezcla de Rusia "galvo escáner & quot;), con un poco modificados tarjetas de sonido baratas para el PC. Fui una manera diferente, porque en última instancia lo que necesito para ser plenamente unidad autónoma que puede trabajar sin ordenador.



Vamos a ver lo que hay en mi proyector láser. El costo de todas las partes fue de alrededor de 8.000 rublos, de los cuales más de la mitad -. Un módulo láser 70mW
Гальванометры y controladores para ellos para desviar el rayo láser a lo largo de los ejes X / Y módulo láser 532nm 70mW alimentado por 5V Dragón Láseres SGLM70 Texas Instruments Stellaris Launchpad Una tarjeta hecha en casa con DAC AD7249BRZ Alimentación < /

Hardware h4> En mi sistema usando Stellaris Launchpad como el "cerebro" (porque es rápido y tiene soporte de hardware para USB) y de 12 bits de dos canales DAC con Analog Devices Interfaz Serial AD7249BRZ . Para controlar la deflexión de la viga en el controlador de entrada debe aplicar una señal analógica en el rango de -5 a 5 voltios. DAC AD7249BRZ apenas capaz de trabajar en este modo (y también de 0 a 5 voltios, y de 0 a 10 voltios). Para él, vomité en el Águila una tasa especial, que está conectado a la Stellaris Launchpad. La junta requiere una fuente de alimentación bipolar, que se obtiene por medio de chips ICL7660 . Para convertir una única tensión de salida suministrada al poder galvanómetro de alimentación (15V) si es necesario para mí, he usado un LM317 regulador lineal, que más tarde resultó ser la mejor solución, especialmente para la potencia del módulo láser - porque LM-ka con un gran disipador de calor (se ve en el video) después de 10 minutos el trabajo se calienta a 70 grados sin disipador de calor, que sólo muy rápidamente recalentado y desconectado de sobrecalentamiento (y con ello el módulo de láser, por lo que inicialmente decidí que quemó y casi pospuesto un par de ladrillos, porque cuando revitalizado no incluye -. como ya se vio después tanto tiempo hasta viruta fresca)

El módulo láser no está soportado nativamente TTL-modulación, así que cuando me cansé de sólo conducir con láser en diferentes direcciones, yo pensaba que cuando el tiempo se enciende y se apaga el haz. Esto implicó la modificación del hierro módulo de láser de soldadura. Afortunadamente, casi todos los módulos láser chinos son muy similares entre sí, simple, y se hacen en el amplificador operacional LM358. Soldadura a sus pies 3 y 4 (entrada no inversora y de la tierra, respectivamente) emisor y colector primero consiguió 2N4401 transistor bipolar, que por lo tanto tuve la oportunidad de modular el funcionamiento del láser, la alimentación de una señal de control a la base del transistor:



El módulo láser modificado con un archivo h6> AD7249BRZ Esquema y tabla presentan a continuación. Tal vez el lector atento encontrará en el esquema de error, ya que por razones desconocidas para mí, no parece funcionar con una parte de un amplificador operacional, que está diseñado para hacer que la salida del circuito балансным para una mayor protección contra la interferencia. Mi copia en lugar de las salidas de señales balanceadas desequilibrada, pero sin embargo, todo funciona bien.


Espero que no tiene miedo de las terribles imágenes de la tarjeta con unos pasadores de chip de contacto, que se formó después de limpiar con alcohol etílico. Por cierto, la razón por la cual lavada flujo recomienda alcohol isopropílico, ya que no deja dicho residuo. Por cierto, es interesante que este tipo de conectores con un pestillo en el tablero - que conecta Molex (22-23-2021 zócalo, enchufe 22-01-3027, 08-50-0114 Contacto Tenedor), ordenando a través de Digikey, ya los chinos, son de alguna manera obscenamente caro.

Soft h4> Esto parece las cosas más interesantes sobre el fin del hierro, por lo que van a las-partes blandas. Se compone de dos partes - una utilidad para el PC y el firmware de la Stellaris Launchpad, que implementa la mayor unidad USB con su propio formato de paquetes de 32 bits cada uno. El formato de la muestra se describe por la siguiente estructura:

 & lt; code class = & quot; cpp & quot; & gt; typedef struct {x sin firmar: 12; // Coordenadas X rx sin firmar: 4; // Bandera (on / off láser) y sin firma: 12; // Coordinar Y ry sin firmar: 4; // No se utiliza} SAMPLE_T; & Lt; / código de & gt;  pre> El dispositivo utiliza un USB-buffers de 512 bytes, en la que PC con cierto margen, y a una velocidad tal que no se produzca el desbordamiento o subdesbordamiento de la memoria intermedia escribe datos. Galvanómetros usados ​​diseñadas para mapear 20.000 puntos por segundo, que se requiere es la frecuencia de muestreo. Las funciones de los datos de la velocidad de procesamiento del USB está regulada por lo banal 
  SysCtlDelay  code>  pre>. Ajustando el valor del sistema se puede ajustar de manera que la imagen de prueba ILDA muestra correctamente: 


El LED verde en el video al comienzo de la Cuaresma parpadea después de procesar cada paquete de 20.000 muestras. Esto es, idealmente, debe parpadear exactamente 1 veces por segundo.

La parte del software de la PC se basa en la
  playilda.c  code>  pre> del paquete  OpenLase < / a>, pero cortar todos innecesaria y en lugar de comunicarse con el servidor JACK utiliza libusb para enviar paquetes de datos a la Stellaris Launchpad. 
El código fuente del programa para la PC
 & lt; code class = & quot; cpp & quot; & gt; #include & lt; stdlib.h & gt; #include & lt; sys / time.h & gt; #include & lt; time.h & gt; #include & lt; stdio.h & gt; #include & lt; string.h & gt; #include & lt; libusb-1.0 / libusb.h & gt; #include & lt; iostream & gt; #include & lt; cadena & gt; #include & lt; vectorial & gt; #define MAGIC 0x41444C49 línea estática uint16_t swapshort (uint16_t v) {return (v & gt; & gt; 8) | (v & lt; & lt; 8); } Escala flotador = 1,0; typedef struct {uint32_t magia; uint8_t Pad1 [3]; formato uint8_t; char nombre [8]; empresa char [8]; uint16_t contar; frameno uint16_t; frameCount uint16_t; escáner uint8_t; pad2 uint8_t; } ((Pic)) ilda_hdr __attribute __; #define #define 0x40 Vacia Ultima 0x80 typedef struct {int16_t x; int16_t y; z int16_t; Estado uint8_t; de color uint8_t; } ((Pic)) icoord3d __attribute __; typedef struct {coord3d int16_t x; int16_t y; z int16_t; Estado uint8_t; coord3d (int16_t x, int16_t y, int16_t z, estado uint8_t): x (x), y (y), z (z), estado (estado) {}} coord3d; typedef struct {std :: vector & lt; coord3d & gt; puntos; posición int; } Marco; rframe marco; subpos int; int divisor = 1; int loadildahdr (FILE * ild, ilda_hdr & amp; hdr) {if (fread (& amp; hdr, sizeof (HDR), 1, ILD) = 1!) {std :: cerr & lt; & lt; & Quot; Error al leer encabezado & quot; & Lt; & lt; std :: endl; devuelve -1; } Si (hdr.magic = MAGIA!) {Std :: cerr & lt; & lt; & Quot; la magia no válida & quot; & Lt; & lt; std :: endl; devuelve -1; } Si (hdr.format = 0!) {Fprintf (stderr, & quot; tipo de sección no admitida% d n \ & quot;, hdr.format); devuelve -1; Hdr.count} = swapshort (hdr.count); hdr.frameno = swapshort (hdr.frameno); hdr.framecount = swapshort (hdr.framecount); } Int loadild (std const :: string & amp; archivo, marco & amp; fotograma) {int i; ARCHIVO * ild = fopen (file.c_str (), & quot; rb & quot;); si (ILD!) {std :: cerr & lt; & lt; & Quot; No se puede abrir & quot; & Lt; & lt; archivo & lt; & lt; std :: endl; devuelve -1; } Hdr Ilda_hdr; loadildahdr (ILD, hdr); for (int f = 0; f & lt; hdr.framecount; f ++) {std :: cout & lt; & lt; & Quot; Frame & quot; & Lt; & lt; hdr.frameno & lt; & lt; & Quot; de & quot; & Lt; & lt; hdr.framecount & lt; & lt; & Quot; & Quot; & Lt; & lt; hdr.count & lt; & lt; & Quot; puntos & quot; & Lt; & lt; std :: endl; icoord3d * tmp = (icoord3d *) calloc (hdr.count, sizeof (icoord3d)); si (fread (tmp, sizeof (icoord3d), hdr.count, ILD) = hdr.count!) {std :: cerr & lt; & lt; & Quot; Error al marco de lectura & quot; & Lt; & lt; std :: endl; devuelve -1; } For (i = 0; i & lt; hdr.count; i ++) {punto coord3d (swapshort (tmp [i] .x), swapshort (tmp [i] .y), swapshort (tmp [i] .z), tmp [i] .state); frame.points.push_back (punto); } Gratuito (tmp); loadildahdr (ILD, hdr); } Fclose (ILD); return 0; } Breve outBuffer [128]; proceso de int () {frame * frame = & amp; rframe; corta * sx = & amp; outBuffer [0]; corta * sy = & amp; outBuffer [1]; for (int frm = 0; frm & lt; 64; frm ++) {struct coord3d * c = & amp; marco & gt; puntos [marco & gt; posición]; * Sx = 4095 - (2047 + (2,048 * c- & gt; x / 32768)) * escala; * Sy = (2.047 + (2,048 * c- & gt; a / 32768)) * escala; si (c- & gt; & amp Estado; BLANCO) {* sx | = 1 & lt; & lt; 15; } Else {* sx & amp; = ~ (1 & lt; & lt; 15); } + Sx = 2; sy + = 2; subpos ++; if (subpos == divisor) {subpos = 0; si (c- & gt; & amp Estado; APELLIDO) marco & gt; posición = 0; otro marco & gt; posición = (marco & gt; la posición + 1)% marco & gt; points.size (); }} Return 0; } Int main (int argc, char ** argv) {libusb_device_handle * dev; libusb_context * ctx = NULL; int ret, real; ret = libusb_init (& amp; CTX); si (r & lt; 0) {fprintf (stderr, & quot; No se pudo inicializar libusb \ n & quot;); volver EXIT_FAILURE; } Libusb_set_debug (ctx, 3); dev = libusb_open_device_with_vid_pid (CTX, 0x1cbe, 0x0003); si (dev == NULL) {fprintf (stderr, & quot; No se puede abrir el dispositivo \ n & quot;); volver EXIT_FAILURE; } Printf demás (& quot; Dispositivo abrieron \ n & quot;); si (libusb_kernel_driver_active (dev, 0) == 1) {fprintf (stderr, & quot; controlador Kernel \ n & quot activa;); libusb_detach_kernel_driver (dev, 0); } Ret = libusb_claim_interface (dev, 0); si (r & lt; 0) {fprintf (stderr, & quot; no podía reclamar interfaz \ n & quot;); volver EXIT_FAILURE; } // Para mantener nuestros ts timespec struct frecuencia de muestreo; ts.tv_sec = 0; ts.tv_nsec = 2000000; memset (& amp; rframe, 0, sizeof (marco)); si (loadild (argv [1], rframe) & lt; 0) {fprintf (stderr, & quot; No se ha podido cargar ILDA \ n & quot;); volver EXIT_FAILURE; } While (1) {process (); if (nanosleep (& amp; ts, NULL) = 0!) fprintf (stderr, & quot; nanosleep falló & quot;); ret = libusb_bulk_transfer (dev, (1 | LIBUSB_ENDPOINT_OUT), (unsigned char *) & amp; outBuffer, 256, & amp; real, 0); si (RET = 0 || real = 256!) fprintf (stderr, & quot; Error de escritura \ n & quot;); } Libusb_release_interface (dev, 0); libusb_close (dev); libusb_exit (CTX); return 0; } & Lt; / Código & gt;  pre> 
Las funciones de la
  main ()  code>  pre> usando nanosleep también gobernado por la frecuencia con la que los nuevos datos se envía al microcontrolador. 
El código fuente completo del firmware del controlador están disponibles .

Planes para el futuro h4> Está previsto terminar estas cosas todavía a un estado similar al arpa láser pensado originalmente. Para este propósito único en lugar de dos espejos, ya que el haz láser mueve a lo largo un solo eje. El principio de funcionamiento del arpa es que el controlador se enciende y se apaga rayo láser en determinados momentos se crean con láser "Teclado" en el aire. Artista, el bloqueo de la mano en el guante de reflexión rayo láser brillante activa el elemento fotosensible en la base del "arpa". Desde el microcontrolador sabe en qué momento qué parte del teclado, se "pintó" que puede determinar cuál de las vigas ha sido bloqueada. Luego le toca a la formación del mensaje MIDI correspondiente y enviarla a un ordenador o conectados para formar un sonido de sintetizador hardware.

Fuente: