Introducción

Todo empezó con el desarme del posnet A910, en el cual venía una impresora térmica. La idea era poder reutilizar el conjunto completo para imprimir imágenes al estilo cámara Polaroid. Luego de varios intentos fallidos, hice lo que toda persona haría… hacer ingeniería inversa de la impresora térmica y utilizarla por separado.

Desarme e ingeniería inversa

La impresora térmica es un conjunto de 3 partes:

  1. Cabezal térmico
  2. Sensor de papel
  3. Motor paso a paso

alt text

Inicialmente había empezado a identificar cada señal en cada pin de la impresora, soldando unos cables a una placa de pruebas. Más adelante en el proyecto, Agustin Palla consiguió el datasheet!(webarchive pdf) y terminé verificando cada pin.

alt text alt text

La impresora tiene una interfaz serie, es un shift register, donde cada pixel ingresado se se carga en un buffer. Luego, para cargar los datos se envía un pulso de LATCH y mediante la señal de STROBE se imprimen los datos.

alt text

La matriz de la impresora es de 384 puntos, donde cada pixel está separado por 0.125mm (1/8 de mm). Son 8 puntos por mm, lo que hace un total de 48mm de ancho imprimible, unos 203 dpi.

Programación

Las primeras pruebas fueron para identificar y probar el protocolo serie. Se utilizó una placa ESP32 para enviar los datos a la impresora mediante el puerto SPI.

El programa es básicamente:

  1. Inicializar los pines de LATCH(HIGH) y STROBE(LOW).
  2. Enviar 384 bits de datos (48 bytes de 0x0F) a la impresora para generar un patrón
  3. Enviar el pulso de LATCH en bajo y luego en alto. Almacena los datos en el buffer
  4. Enviar el pulso de STROBE en alto. Con esto se imprime el buffer en la impresora
  5. Avanzar el papel
delayMicroseconds(10);
digitalWrite(latch_pin, LOW);
delayMicroseconds(10);
digitalWrite(latch_pin, HIGH);
delayMicroseconds(30);
digitalWrite(dst_pin, HIGH);
delayMicroseconds(100);
digitalWrite(dst_pin, LOW);

alt text

El siguiente paso fué implementar una función para imprimir una imagen. El concepto es basícamente lo mismo, pero en lugar de enviar un patrón, se envía una imagen en paquetes de 1 byte. El problema es de donde conseguir una imagen codificada en 1 bit por pixel, y que fuera fácil de adaptar al código C++… Ahí es donde viene la página image2cpp de Jasper Van Loenen. En esta página se puede cargar una imagen y seleccionar la cantidad de bits por pixel, y luego se genera un código C++ con la imagen codificada. Es importante que la imagen sea en blanco y negro (podemos convertirla en la página) y también que tenga un ancho de 384px, valor que coincide con el máximo imprimible.

En caso de una imagen en escala de grises, podemos utilizar Dither para mejorar la representación en pixels.

Prueba dither

Las líneas horizontales más claras (como falta de toner) son debido a que los cables que estoy utilizando para alimentar la impresora no son lo suficientemente gruesos. Esto causa una caída de voltaje y afecta la calidad de la impresión. Recomiendo utilizar cables de mayor calibre para evitar este problema.

Aquí pueden apreciar un ejemplo de impresión de texto e imagen juntos.

Qué como genero el texto? ahí es donde entran las fuentes GLCD. Hay varias en internet dando vueltas, hay que buscar una y adaptar el código. Es básicamente una imagen, pero de 8 bits de alto y 384 bits de ancho (máximo imprimible). En el caso del video son fuentes de 8x8, por lo que se pueden imprimir hasta 48 caracteres por línea.

Conclusión

La impresora térmica es un dispositivo muy interesante y fácil de utilizar. Con un poco de ingeniería inversa y programación se pueden hacer cosas muy interesantes.

En el caso de querer imprimir imágenes, recomiendo utilizar una fuente de alimentación de 7.8V y cables de mayor calibre para evitar problemas de calidad de impresión. El problema es imprimir varios pixels al mismo tiempo, ya que esto implica un mayor consumo de corriente.

En el caso de querer imprimir texto, recomiendo utilizar fuentes de 8x8 para poder imprimir hasta 48 caracteres por línea.

Próximos pasos

El código eventualmente lo voy a subir a mi perfil de github para que puedan utilizarlo. Inicialmente empezó como un proyecto personal, pero me parece interesante compartirlo como una biblioteca para que otros puedan utilizarlo.