Medir una pared con huincha es trivial. Medir el volumen de una bodega, la altura de un techo al que no llegas, o el desnivel de una repisa antes de atornillarla, ya no lo es: ahí empiezan los cálculos a mano, los apuntes en el celular y los errores de medio metro. Un telémetro láser resuelve las tres cosas al mismo tiempo, y por dentro es un proyecto de electrónica mucho más abordable de lo que parece.

Este artículo desarma el SmartTape, un medidor láser de bolsillo con batería construido sobre un STM32, y lo usa como excusa para entender cómo se mide distancia con luz: qué hace un sensor Time of Flight, por qué la lectura cruda no sirve tal cual, cómo se combina distancia con ángulo para calcular una altura indirecta, y qué parte de todo esto puedes replicar en una protoboard sin diseñar una PCB.

Al final vas a saber elegir entre un sensor ToF y un ultrasónico, entender el filtro de dos etapas que estabiliza la medición, y tener una ruta concreta para armar tu propia versión con un ESP32.

Diagrama general del SmartTape: el camino del sensor láser de distancia y el del inclinómetro

Dos sensores, no uno

La idea central del proyecto es que un medidor útil necesita dos magnitudes distintas: cuán lejos está el objetivo y en qué ángulo estás apuntando.

La distancia la entrega un VL53L4CX de ST, un sensor Time of Flight que emite luz infrarroja y calcula la distancia a partir del tiempo que tarda el reflejo en volver. En modo LONG alcanza unos 6 metros, suficiente para interiores y taller. Un detalle que confunde a mucha gente: el punto rojo que ves proyectado no es el que mide. Ese es un diodo láser visible independiente, puesto ahí solo para que sepas hacia dónde estás apuntando. El sensor mide en infrarrojo, invisible.

El ángulo lo entrega un inclinómetro Murata SCL3300, de tres ejes y con una resolución cercana a 0,0055°. Con esas dos cifras. distancia inclinada y ángulo. el firmware calcula alturas a las que no puedes llegar con la huincha.

Todo lo coordina un STM32G491CEU6, un ARM Cortex-M4F a 170 MHz que se hace cargo del sensor de rango, el inclinómetro, la pantalla OLED, la perilla de entrada, el monitoreo de batería, el control del láser y la máquina de estados de la aplicación.

ToF contra ultrasónico: cuándo conviene cada uno

El original no entra en esta comparación, y es la primera pregunta que aparece cuando armas algo así con presupuesto acotado. Si vienes del mundo Arduino, tu reflejo va a ser el HC SR04. Las diferencias importan:

  • Ángulo del haz: el ultrasónico "ve" un cono de unos 15°, así que si mides al fondo de un pasillo estrecho te devuelve la pared lateral. El ToF tiene un campo de visión mucho más angosto, y mide donde apuntas.
  • Superficie del objetivo: el ultrasónico rebota mal en telas, espuma y cortinas. El ToF falla en el caso opuesto: superficies negras mate (absorben el infrarrojo) y vidrios o espejos (el reflejo se va para otro lado). Si tu lectura salta o devuelve error apuntando a un vidrio, no es el sensor: es física.
  • Precisión: milímetros contra centímetros. Para un medidor de distancia de verdad, el ultrasónico no da el ancho.
  • Luz ambiente: el ToF pierde alcance al sol directo, porque el infrarrojo del ambiente se le suma como ruido. Es la razón por la que este tipo de instrumento rinde mucho mejor en interiores.

El filtro: por qué la lectura cruda no sirve

Esta es, técnicamente, la parte más interesante del proyecto, y la que más se puede reutilizar en cualquier otro montaje con sensores.

Una lectura ToF cruda trae dos problemas distintos. Primero, aparecen outliers: una muestra suelta completamente fuera de rango, producto de un reflejo raro o de ruido en el fotodetector. Segundo, a mayor distancia la medición se vuelve más ruidosa de forma sostenida, porque vuelve menos luz.

Filtrar los dos problemas con el mismo promedio no funciona. Si suavizas fuerte, medir 30 cm se siente lento y la pantalla arrastra. Si suavizas poco, a 4 metros los números bailan. Por eso el firmware aplica dos etapas encadenadas:

1. Mediana móvil. Mantiene las últimas siete lecturas en un buffer circular, las ordena y se queda con el valor del medio. La mediana es inmune a valores extremos: una muestra absurda queda al borde del arreglo y nunca llega a la salida. Un promedio simple, en cambio, se la comería entera y movería el resultado.

2. Promedio móvil exponencial adaptativo. El resultado de la mediana entra a un EMA cuyo factor de suavizado depende de la distancia medida:

α = 1 / (1 + 0,0008 × distancia_mm)

acotado entre 0,08 y 0,60. A unos 500 mm el alfa queda cerca de 0,60 y la respuesta es rápida; a unos 4000 mm cae a ~0,23 y suaviza mucho más. El filtro se endurece solo, justo donde el ruido crece.

El orden no es intercambiable. Primero mediana, después EMA. Si inviertes las etapas, el outlier ya contaminó el promedio antes de que la mediana pudiera descartarlo, y te queda un escalón en la salida que tarda varias muestras en disolverse. Es un patrón que sirve igual para una celda de carga, un sensor de corriente o un ADC ruidoso.

Circuito del sensor Time of Flight VL53L4CX montado en la placa óptica

En el montaje del proyecto el VL53L4CX no va sobre la placa principal, sino en una placa hija óptica unida por siete contactos castellados. Eso permite alinear el sensor y el láser con la ventana de la carcasa sin depender de dónde quedó la placa principal, y mantiene el área de detección lejos de las señales digitales rápidas. El sensor habla por I2C a 400 kHz en la dirección 0x29, más dos GPIO: XSHUT para apagarlo por hardware e INT para avisar que hay una medición lista.

Altura indirecta: distancia más ángulo

Esquema del inclinómetro SCL3300 usado para la medición de altura indirecta

El modo HEIGHT es donde los dos sensores se juntan. En vez de apuntar el láser a la parte alta de un muro y tratar de dejar el aparato perfectamente vertical, mides la distancia inclinada al objetivo y el inclinómetro aporta el ángulo. La componente vertical sale de trigonometría básica:

raw_h = D × sen(θ)

Después vienen dos correcciones que rara vez se mencionan en los tutoriales y explican por qué un instrumento casero mide "casi bien". La primera es geométrica: el sensor no está en el piso, está unos 2,4 cm más arriba, así que hay que descontar esa altura proyectada sobre el ángulo:

uncal_h = raw_h, 2,4 cm × cos(θ)

La segunda es una calibración empírica de dos puntos, con ganancia y offset obtenidos midiendo objetivos de altura conocida:

altura = (uncal_h × 1,0989) + 2,242 cm

Si armas tu propia versión, esos números no te sirven: son de ese hardware, con ese lente y esa posición de sensor. El procedimiento sí te sirve. Mide dos alturas conocidas, ajusta una recta y guarda los coeficientes.

El SCL3300 conversa por SPI a unos 5,3 MHz, con tramas fijas de 32 bits y verificación CRC-8. También entrega temperatura, que la interfaz muestra en el modo nivel.

El láser visible y su driver

Circuito driver de corriente constante CAT4002A para el diodo láser

El puntero es un diodo láser rojo ROHM RLD65NZN5 de 650 nm, y no está conectado directo a un GPIO: pasa por un driver de corriente constante CAT4002A. Esto no es lujo de diseño. Un diodo láser tiene coeficiente térmico negativo: al calentarse conduce más, y si lo alimentas por tensión entra en un ciclo de realimentación que termina destruyéndolo en segundos. Por eso se maneja siempre por corriente. Acá la corriente se fija con una resistencia de 3,74 kΩ:

I_LASER = (1,2 V / 3740 Ω) × 100 ≈ 32 mA

La entrada EN/DIM va al STM32, así el firmware enciende y apaga el puntero según el modo. Dos precauciones si replicas esta parte: nunca mires el haz de frente ni lo apuntes a los ojos de nadie, y apaga el láser cuando congeles una medición, que es exactamente lo que hace este firmware.

Alimentación: USB-C, carga de litio y 3,3 V

Circuito cargador de batería con LTC4057 del medidor láser

La entrada es USB-C configurado como sink puro: dos resistencias de 5,1 kΩ en CC1 y CC2 le dicen al cargador que entregue 5 V, sin necesidad de un controlador Power Delivery. Es el truco mínimo para usar USB-C como conector de alimentación, y omitir esas resistencias es el error más común: el equipo simplemente no carga con fuentes modernas.

VBUS pasa por un diodo Schottky (protección contra corriente inversa cuando el equipo funciona con batería y además hay cable conectado) y llega al LTC4057ES5-4.2, que maneja la carga de la celda de litio. Su pin PROG con una resistencia de 1,65 kΩ fija la corriente de carga:

I_CHG = (1000 × 1,0 V) / 1650 Ω ≈ 0,606 A

El encendido se hace con un MOSFET canal P AO3401A: el switch deslizante no conduce la corriente del sistema, solo controla la compuerta. Una resistencia de 100 kΩ mantiene el MOSFET apagado con el switch abierto. Después, un LDO LD39200PU33R regula a 3,3 V con caída baja, lo que permite seguir funcionando mientras la celda se descarga.

La batería se monitorea con un divisor 100 kΩ/100 kΩ hacia el ADC, reconstruyendo la tensión como V_BAT = 2 × (ADC_RAW / 4095) × 3,30 V. El detalle fino: en vez de promediar las 32 muestras, el firmware las ordena, descarta el cuartil superior e inferior y promedia las 16 del medio. Esa media recortada rechaza los peaks de ruido que mete el driver del láser al conmutar, y después pasa por un IIR lento con alfa 0,08 más 1% de histéresis, para que el porcentaje en pantalla no oscile entre dos valores.

Interfaz: una sola perilla y un framebuffer

Menú carrusel del SmartTape mostrando los ocho modos de medición en la pantalla OLED

Todo el equipo se opera con un solo control: una perilla rotatoria con retorno por resorte, tipo Bourns PEC11R. No gira de forma continua como un encoder normal; la mueves en un sentido, genera un evento de navegación y vuelve sola al centro. El pulsador integrado aporta el resto de los gestos: pulsación corta, larga, doble y "presionar y girar". Con eso alcanza para navegar los ocho modos sin llenar la carcasa de botones. Cada fase del encoder entra por un GPIO con pull up de 10 kΩ y una red RC de antirrebote con 0,1 µF.

Los ocho modos son: distancia continua (DIST), nivel digital (LEVEL), altura indirecta (HEIGHT), área (AREA), volumen (VOLUME), volumen cilíndrico para estanques y tuberías (CYLINDER), seguimiento de máximo y mínimo (MAXMIN) y registro de las últimas diez mediciones (MEMORY). Las unidades. cm, mm, m o pulgadas. se guardan en la Flash interna del STM32, en la última página de 2 KB, junto a un valor mágico que permite distinguir una configuración válida de Flash vacía. La escritura ocurre solo cuando confirmas el cambio, no de forma continua: la Flash del STM32 aguanta del orden de 10.000 ciclos de borrado y escritura, y gastarlos en autoguardados es una forma lenta de matar el equipo.

La pantalla es una OLED SH1106 de 1,3" (128 × 64) por I2C en la dirección 0x3C. El firmware no la trata como display de texto: mantiene un framebuffer completo de 1024 bytes en RAM, dibuja ahí las líneas, íconos y números, y recién después vuelca la imagen entera. Eso permite animaciones sin parpadeo, y un renderizador de dígitos de siete segmentos paramétrico: en vez de guardar bitmaps para cada tamaño de fuente, genera los segmentos según el alto, ancho y grosor pedidos.

De la PCB al taller

Diseño de PCB de dos capas del medidor láser en Altium Designer

La placa es de dos capas, diseñada en Altium, y varias decisiones de layout valen como guía general: el pad térmico del QFN-48 conectado a un plano sólido de tierra en la capa inferior; el cristal de 24 MHz con sus capacitores de 8 pF pegados a los pines del oscilador; los condensadores de desacoplo de 0,1 µF junto a cada pin de alimentación; D+ y D, del USB ruteados como par diferencial de largo igualado con protección TVS junto al conector; y la pista del ADC de batería alejada de las líneas SPI e I2C para que el ruido digital no se acople a la medición analógica.

Placa PCB del medidor láser ya ensamblada con sus componentes soldados

En el ensamblaje, el orden importa: primero los pasivos chicos, después los SOT-23 y los encapsulados difíciles, y al final el cristal, el encoder, la OLED y los conectores, que estorban si los pones antes. El LDO en DFN-6 necesita que su pad inferior haga buen contacto térmico y eléctrico. Antes de aplicar energía conviene revisar la placa con lupa y verificar que no haya cortos entre VBAT, VDD, VBUS y tierra; luego probar la interfaz SWD con un ST Link antes de conectar la batería.

Diseño de carcasa impresa en 3D de dos piezas para el medidor láser

La carcasa es de dos mitades tipo almeja, con abertura para la OLED, un rebaje alrededor del encoder y una perforación circular alineada con el láser. El proyecto entrega tres modelos STEP (dos revisiones de la tapa superior y una de la inferior), pensados para imprimir en PLA o PETG con capa de 0,2 mm y relleno cercano al 20%.

El firmware está escrito en C con STM32CubeIDE, el HAL de STM32G4 y el driver Ultra Lite de ST para el VL53L4CX. No usa RTOS: corre un lazo principal cada ~30 ms (unas 33 veces por segundo) que revisa el encoder, consulta el sensor ToF sin bloquear, lee el inclinómetro por SPI, resuelve la máquina de estados, actualiza el framebuffer y saca telemetría por USB CDC.

Uso del medidor láser midiendo distancia en modo DIST

Variantes y mejoras

Versión en protoboard, sin PCB custom. Es la ruta realista si quieres el proyecto funcionando esta semana. Reemplaza el STM32G491 por un ESP32 DevKit, el VL53L4CX por un módulo VL53L1X (mismo principio ToF, hasta ~4 m, librería de Pololu o de STM muy documentada, I2C igual) y el SCL3300 por un MPU6050. Pierdes resolución angular. el MPU6050 anda en décimas de grado contra las milésimas del SCL3300. así que el modo nivel queda más "nervioso" y la altura indirecta acumula más error a distancia larga; para medir una pieza o un techo estándar sigue siendo perfectamente utilizable. Mantén la OLED SH1106 o SSD1306 por I2C y un encoder KY-040 en vez de la perilla con retorno.

Registro y telemetría inalámbrica. El ESP32 ya trae WiFi y BLE: en vez de guardar diez mediciones en Flash, publica cada medición por MQTT o levanta un servidor web mínimo y descarga el listado en CSV. Para una toma de medidas en terreno es la diferencia entre anotar a mano y tener la planilla lista.

Modo obra: acumulador de metros lineales. Ninguno de los ocho modos originales suma mediciones sucesivas. Agregar un modo que acumule tramos. útil para cotizar cornisas, guardapolvos o metros de cable. son unas pocas líneas sobre la máquina de estados existente y es de las mejoras que más se agradecen en uso real.

Apagado por inactividad agresivo. El firmware ya tiene temporizador de inactividad. Si además llevas el ESP32 a deep sleep y cortas la alimentación del ToF por su pin XSHUT, el consumo en reposo baja al orden de decenas de microamperes y una celda chica dura meses.

Personalización para Chile

El proyecto original está pensado para fabricar una PCB y comprar componentes SMD por DigiKey, algo poco práctico si estás partiendo. La versión en protoboard descrita arriba se arma con componentes que MechatronicStore mantiene en catálogo:

  • Placa ESP32 DevKit. reemplaza al STM32G491CEU6 como controlador. Tiene de sobra para el lazo de 30 ms, el filtro y el renderizado de pantalla, y te ahorra el ST Link (programa por USB).
  • Sensor ToF VL53L1X. equivalente funcional del VL53L4CX para este uso. Mismo bus I2C, misma lógica de XSHUT e interrupción, menor alcance máximo.
  • Módulo acelerómetro/giroscopio MPU6050. cubre el rol del inclinómetro SCL3300 para los modos nivel y altura.
  • Pantalla OLED 1,3" SH1106 I2C. es exactamente la misma pantalla del proyecto original.
  • Encoder rotativo KY-040. la perilla con retorno por resorte del original no se consigue suelta; el KY-040 con su pulsador integrado cumple la navegación y la selección.
  • Batería LiPo 3,7 V y módulo cargador TP4056 USB-C. juntos reemplazan toda la sección de alimentación custom (cargador LTC4057 + LDO + MOSFET). El TP4056 con protección ya trae la carga CC/CV y el corte por sobredescarga.
  • Protoboard 830 puntos y jumpers macho hembra. para el montaje sin soldar.

Dos componentes del original no tienen equivalente razonable en catálogo y conviene saberlo antes de empezar: el inclinómetro Murata SCL3300 (sensor industrial, se compra solo por distribuidores de componentes) y el diodo láser RLD65NZN5 con su driver CAT4002A. Para el puntero, cualquier módulo láser rojo de 5 V con su resistencia limitadora sirve como reemplazo funcional, aunque sin la regulación de corriente del diseño original.

Los precios y códigos exactos conviene confirmarlos en el catálogo al momento de comprar. Como referencia de magnitud: una versión en protoboard como la descrita queda muy por debajo del costo de un telémetro láser comercial de marca, y te deja el firmware en tus manos.

Recursos

Artículo inspirado en el proyecto SmartTape de Circuit Digest, con análisis técnico propio y una ruta de armado alternativa con componentes en stock local en MechatronicStore.