Tabla de contenido:

Reloj del mapa del metro de Londres: 9 pasos (con imágenes)
Reloj del mapa del metro de Londres: 9 pasos (con imágenes)

Video: Reloj del mapa del metro de Londres: 9 pasos (con imágenes)

Video: Reloj del mapa del metro de Londres: 9 pasos (con imágenes)
Video: Cómo ir del Aeropuerto de Heathrow al centro de Londres 2024, Mes de julio
Anonim
Reloj Mapa del metro de Londres
Reloj Mapa del metro de Londres
Reloj Mapa del metro de Londres
Reloj Mapa del metro de Londres

En 2014, después de una pasantía en una consultoría de impresión 3D en Londres y un experimento con litofanos en color usando su máquina Stratasys, diseño mi propio regalo de despedida, una impresión en 3D en color de líneas de tubos local a sus oficinas. Estaba decidido a hacer algo con eso. Dos años después, en 2016, tenía mi propia impresora 3D y me puse a trabajar para convertirla en un reloj.

Cuando era niño, pensé que los relojes digitales Tokyo Flash eran las mejores cosas de la historia, y pensé que ese sería el punto de inspiración para el diseño.

¡Y ahora solo ha sido un pequeño descanso de 4 años hasta que comencé a escribirlo!

Si bien las instrucciones exactas serán difíciles de replicar, y la reducción del costo en la fabricación de PCB para aficionados en los últimos dos años podría hacer que mi método exacto para la colocación de LED sea obsoleto. ¡Espero que las ideas compartidas puedan llevar a otros a hacer relojes raros con objetos delgados!

Paso 1: capa frontal

Capa frontal
Capa frontal
Capa frontal
Capa frontal
Capa frontal
Capa frontal

Como se mencionó en la introducción, se trataba de una impresión 3D en color, creo que una máquina Stratasys que usaba una cama de polvo y un cartucho de tinta modificado para aglutinante y pigmento.

El archivo se pierde en la historia, pero esta capa podría ser cualquier cosa, una foto o un litofano de un solo color funcionaría de maravilla.

Esta pieza se hizo en 3DS max en 2014, pero hoy en día existen herramientas en línea para convertir una imagen en un SLT según el brillo.

Paso 2: diseño de la capa guía

Diseño de la capa guía
Diseño de la capa guía
Diseñar la capa guía
Diseñar la capa guía
Diseño de la capa guía
Diseño de la capa guía
Diseño de la capa guía
Diseño de la capa guía

Aquí es donde decidimos la complejidad del proyecto y el método para leer el tiempo. Las imágenes muestran las 2 ideas con las que estaba jugando.

Estos se hicieron escaneando el diseño y dibujando líneas a través de él en inkscape.

Este no es un reloj muy legible, pero preferí la idea de que las líneas se llenasen a lo largo del día, así que ese se convirtió en el objetivo del diseño.

El conteo binario es un método viable para reducir el conteo de LED, y mejoraría la legibilidad si el binario es su problema, pero eso socavó mi idea de 'líneas de llenado', por lo que no era una opción para este proyecto.

Es común en los Tokyo Flash Watches minimizar el recuento de LED, pero teniendo una sección que cuenta en 3 o 5 y luego otro relleno para cada vez que se llena esa sección, utilicé esta técnica para los minutos, para reducirlos de 60 a 20 más 2. I No estaba tan preocupado por la precisión por unos segundos.

Paso 3: creación de la capa de guía

Construyendo la capa de guía
Construyendo la capa de guía
Construyendo la capa de guía
Construyendo la capa de guía
Construyendo la capa de guía
Construyendo la capa de guía

Esta capa de guía para los LED tiene 2 propósitos, mantiene los LED en su lugar y evita que se derramen entre ellos.

Se dibujó como una capa en Inkscape directamente en la parte superior del escaneo que estaba usando para el diseño del diseño. Se agregó 1 mm de grosor en la licuadora antes de enviarlo a mi impresora.

Esta fue una de las impresiones más difíciles que tuve que hacer en mi escasa Makibox A6, la pieza se imprimió en abs, por lo que se usó una tonelada de lechada de acetona para mantenerla unida a la plataforma de construcción con una deformación mínima. Afortunadamente, esta parte no se ve en el producto final.

La imagen final muestra que se sostiene frente a una lámpara para verificar el espacio.

En retrospectiva, el derrame entre luces a lo largo de una línea podría ser preferible para las imágenes, no es más difícil de leer, esto podría lograrse agregando un chaflán a la guía en los lados cortos de cada luz.

Paso 4: cableado de los LED

Cableado de los LED
Cableado de los LED
Cableado de los LED
Cableado de los LED
Cableado de los LED
Cableado de los LED

La primera imagen muestra la impresión de prueba que hice para verificar el tamaño del orificio, estaba apuntando a que el LED encajara perfectamente en el encaje con un poco de fuerza, luego se colocó la forma correcta a mano al colocar la capa guía.

Debido a la baja tolerancia de mi impresora 3D, algunas estaban sueltas y requerían un poco de pegamento para permanecer en su lugar, mientras que otras estaban demasiado apretadas, pero se animó a colocarlas en su lugar presionando el LED mientras soldaba, esto fue en realidad un mejor ajuste que el agujero del tamaño correcto, que tenía un arrendamiento para sacar una vez conectado.

Para reducir la cantidad de cables, los LED se soldaron en una matriz de 7 por 8, lo que significa que los 55 LED se podían controlar con solo 13 pines. Tenía un mapa dibujado a mano de cada una de estas conexiones que, lamentablemente, se ha perdido.

Se usó alambre de esmalte para que las secciones pudieran exponerse en su lugar calentando una sección con la plancha y estañándola antes de hacer la conexión.

Este proceso llevó mucho tiempo, recomiendo encarecidamente diseñar una PCB

Paso 5: diseño de la electrónica

Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica
Diseñando la Electrónica

Mi plan inicial era usar un microcontrolador Arduino con un RTC, pero opté por un ESP8266 en la placa Node MCU D1, ya que permitía el horario de verano automático y el potencial de control sobre WIFI.

Para reducir aún más el recuento de pines, tenía la cantidad perfecta de LED para poder usar un MAX7219 (que puede manejar hasta 64 LED).

Este IC se usa comúnmente para controlar pantallas LED de 7 segmentos, pero tenía un caso de uso muy similar al mío, iluminando una cantidad arbitraria de LED con un parpadeo mínimo, incluso tiene un brillo controlable.

Decidí usar protoboard para el cableado, pero eagle fue útil para la ubicación de las piezas y la comprensión del cableado.

Adjunté los archivos de mi tablero, pero esta fue la primera vez que usé eagle (y una versión desactualizada por ahora), por lo que son solo para referencia

Paso 6: cableado de la electrónica

Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica
Cableado de la electrónica

Este fue un paso simple y repetitivo, siguiendo el esquema de Eagle, el uso de encabezados para el ESP y la matriz de LED ayudó enormemente en el ensamblaje.

El pin 1 en los encabezados LED de ánodo y cátodo estaba marcado con un marcador plateado, se podían diferenciar entre el 7 y el otro 8.

Paso 7: programación

Programación
Programación

Como nuestra pantalla no es una matriz tradicional, tuve que encontrar un método para visualizar qué bits encender y cuáles enviar al MAX IC en HEX. Afortunadamente, sé lo suficiente de Excel para meterme en problemas e hice un 'mago hexadecimal' para guiarme a través del patrón que quería que se mostrara, casillas de verificación colocadas a mano y todo.

Esto vino con la revalorización de que el hexadecimal para mi hora, minuto y segundos podría combinarse usando un bit a bit OR para producir el comando hexadecimal final para enviar al max7219, incluida una pequeña animación que agregué a los segundos para poder asegurarme de que el tablero no había; t congelado.

Entonces, casi al final. y tiempo para otra decisión que no ha envejecido demasiado.

El código para ESP está en LUA, hoy recomendaría usar el IDE de arduino por su mejor documentación y una biblioteca de paquetes robusta, en ese momento la comunidad ESP aún estaba madurando y elegí LUA como el lenguaje para este proyecto.

Tomé la cuestionable decisión de hacer ping regularmente a los servidores de Google para leer la hora. Esto solucionó la necesidad de un RTC para minimizar la deriva, esto funciona, pero sería mejor que utilizara una API de tiempo real.

halfSec = 0 hora = 0 minuto = 0 segundo = 0

lowIntensity = 0

highIntensity = 9

SSID local = "Wifi"

local SSID_PASSWORD = "Contraseña"

function time (): conéctese a Internet para obtener la hora y fecha actuales

si wifi.sta.getip () entonces local conn = net.createConnection (net. TCP, 0) conn: connect (80, "google.com")

conn: on ("conexión", function (conn, payload) conn: send ("HEAD / HTTP / 1.1 / r / n".. "Host: time.is / r / n".. "Aceptar: * / * / r / n".. " Usuario-Agente: Mozilla / 4.0 (compatible; esp8266 Lua;) ".." / r / n / r / n ") end)

conn: on ("recibir", function (conn, payload) --print (payload) conn: close () local p = string.find (payload, "GMT") - encuentra la cadena de fecha y hora en la carga útil de Internet, cambia por zona horaria si p ~ = cero entonces - extraer números correspondientes a la hora, minuto, segundo, día, mes hora = tonumber (string.sub (payload, p-9, p-8)) minuto = tonumber (string.sub (payload, p- 6, p-5)) segundo = tonumber (string.sub (payload, p-3, p-2)) addHour () - codificado en hardware BST (horario de verano británico) impresión de ahorro de luz diurna (hora, minuto, segundo) halfSec = (segundo% 6) * 2 --print (halfSec) else print ("¡falló la actualización web!") end end --function) - fin del controlador de eventos "recibir"

conn: on ("desconexión", function (conn, payload) conn = nil payload = nil end) end print ("todavía no hay wifi") end

function borTable (a, b,…) - tablas OR bit a bit juntas

si arg [1] entonces b = borTable (b, unpack (arg)) end local z = {} for i, v in ipairs (a) do table.insert (z, bit.bor (v, b )) fin volver z fin

función bxorTable (a, b,…) - tablas OR bit a bit juntas

si arg [1] entonces b = bxorTable (b, unpack (arg)) end local z = {} for i, v in ipairs (a) do table.insert (z, bit.bxor (v, b )) fin volver z fin

función addSecond ()

segundo = segundo + 1 si segundo> = 60 luego segundo = 0 minuto = minuto + 1 si minuto> = 60 luego minuto = 0 addHour () end end end

función addHour ()

hora = hora + 1 si hora> = 24 luego hora = 0 finaliza si hora == 2 o hora == 16 luego max7219.setIntensity (lowIntensity) finaliza si hora == 8 u hora == 18 luego max7219.setIntensity (highIntensity) end end function update () local secGap = 6 local minGap = 3 local horGap = 1 local sec = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x03}, {0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x03}, {0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x03}, {, 0x00, 0x00, 0x01, 0x01, 0x03, 0x01, 0x03}, {0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x01, 0x03}, {0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01 }, {0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x03}}; local mínimo = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00}, {0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x00}, {0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00}, {02x00, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00}, {0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00}, {0x02, 0x02, 0x02, 0x02, 0x02, 0x02x, 0x02x, 0x02, 0x02, 0x02, 0x02, 0x00, 0x12, 0x10}, {0x02, 0x02, 0x02, 0x02, 0x02, 0x10, 0x12, 0x10}, {0x02, 0x02, 0x02, 0x02, 0x12, 0x10, 0x12, }, {0x02, 0x02, 0x02, 0x12, 0x12, 0x10, 0x12, 0x10}, {0x02, 0x02, 0x12, 0x12, 0x12, 0x10, 0x12, 0x10}, {0x02, 0x12, 0x12, 0x12, 0x12, 0x10, 0x12, 0x10}, {0x12, 0x12, 0x12, 0x12, 0x12, 0x10, 0x12, 0x10}, {0x12, 0x12, 0x12, 0x12, 0x12, 0x30, 0x12, 0x10}, {0x12, 0x12, 0x12, 0x12, 0x32, 0x30, 0x12, 0x10}, {0x12, 0x12, 0x12, 0x32, 0x32, 0x30, 0x12, 0x10}, {0x12, 0x12, 0x32, 0x32, 0x32, 0x30, 0x12, 0x10}, {0x12, 0x32, 0x32, 0x32, 0x32, 0x30, 0x12, 0x10}, {0x32, 0x32, 0x32, 0x32, 0x32, 0x30, 0x12, 0x10}}; hor local = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x00}, {0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00}, {0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, {0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00}, {0x04, 0x04, 0x04, 0x04, 0x0x04, 0x04, {0x04, 0x04, 0x04, {0x04, 0x0x04, 0x04,, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08}, {0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0C, 0x08}, {0x04, 0x04, 0x0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, }, {0x04, 0x04, 0x04, 0x04, 0x0C, 0x0C, 0x0C, 0x08}, {0x04, 0x04, 0x04, 0x0C, 0x0C, 0x0C, 0x0C, 0x08}, {0x04, 0xC, 0x04, 0x0C, 0x08}, {0x04, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08}, {0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC, {, 0x0C, 0x0C, 0x0C, 0x48}, {0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x4C, 0x48}, {0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x4C, 0x4C, 0x0C, 0x4C, 0x4C, 0x0C, 0x0C, 0x0C, 0x4C, 0x4C, 0x4C, 0x48}, {0x0C, 0x0C, 0x0C, 0x4C, 0x4C, 0x4C, 0x4C, 0x48}, {0x0C, 0x0C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x048}, {0x0C} 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x48}, {0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x48}}; --impresión (hora, minuto, segundo)

- la tabla comienza en 0, por lo que en 1 como actualmente sec [0] = nil)

max7219.write ({animate (borTable (sec [1+ (segundo / secGap)], min [1+ (minuto / minGap)], hor [1+ (hora / horGap)]))})

fin - función

wifi.setmode (wifi. STATION)

wifi.sta.config (SSID, SSID_PASSWORD) wifi.sta.autoconnect (1)

--configurar max7219

max7219 = require ("max7219") max7219.setup ({numberOfModules = 1, slaveSelectPin = 8, Intensity = highIntensity})

--Programa principal

checkOnline = tmr.create ()

tmr.alarm (0, 180000, 1, hora)

tmr.alarm (1, 1000, 1, addSecond)

tmr.alarm (2, 500, 1, actualización)

función animada (todavía)

marcos locales = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; halfSec = halfSec + 1 si halfSec> = 12 entonces halfSec = 0 end --print (halfSec) return bxorTable (frames [halfSec + 1], todavía) end

Paso 8: la vivienda

La vivienda
La vivienda
La vivienda
La vivienda
La vivienda
La vivienda

Ahora es el momento de mostrar su increíble destreza y albergar el proyecto.

O eso, o saca un paquete de Amazon del reciclaje y crea una carcasa temporal que todavía está en uso en la actualidad.

La ventaja de utilizar este enfoque fue que cada capa del proyecto coincidía casi a la perfección con el grosor del cartón, por lo que se podía apilar y pegar un sándwich. Una versión premium similar podría usar acrílico.

Paso 9: Observaciones finales

Gracias por leer. Como muchos de ustedes saben, documentar un proyecto puede ser tan difícil como hacerlo. Hay fragmentos de video conmigo hablando que eventualmente pueden ver la luz del día.

En los años transcurridos entre la realización de este proyecto y su redacción, esperaba ver más ejemplos de pantallas LED arbitrarias que utilizan la impresión 3D, pero la reducción de las tiras RGB ha eliminado en gran medida la necesidad de una alternativa.

Espero que esto haya sido informativo y, por favor, haga preguntas, ya que intentaré dar más detalles sobre las secciones que no satisfacen completamente.

Salud

Recomendado: