Saltar al contenido

Telemedición de agua: de la PCB al clúster

Por Lucas Rack

En el área metropolitana de Buenos Aires, el 40,6 % del agua potable que se entrega no se contabiliza. No es que se pierda toda: es que nadie sabe dónde va. Y solo el 19 % de las unidades funcionales tiene un medidor conectado, así que la mayoría de los usuarios paga una tarifa catastral, calculada por las características del inmueble y no por lo que consume. Sin medición no hay forma de detectar una fuga domiciliaria, ni de gestionar la demanda, ni de saber cuánto de ese 40 % es pérdida de red y cuánto es derroche.

Ese es el problema que tomamos para nuestro trabajo profesional de Ingeniería Electrónica en la FIUBA: diseñar, construir y validar un sistema de telemedición completo, desde el dispositivo que se instala en la caja del medidor hasta el servidor que recibe los datos. Lo defiendo el 7 de septiembre, y quería dejar escrito qué construimos y, sobre todo, qué se rompió en el camino.

El proyecto lo hicimos entre dos. Yo me ocupé del servidor central y del circuito impreso; Gonzalo Puy se ocupó del firmware, en el que también metí mano. El informe lo escribimos entre los dos.

Qué construimos

El sistema tiene cuatro piezas. Un dispositivo IoT alimentado a batería que se instala dentro de la caja domiciliaria del medidor y se conecta al emisor de pulsos del caudalímetro: cada pulso equivale a una cantidad fija de litros. Un firmware que cuenta esos pulsos y despierta una vez por día para reportar. Una PCB propia con el microcontrolador, el módulo celular y su antena. Y un servidor central, el HES, que recibe los datos, los persiste y los deja disponibles para la empresa proveedora.

Diagrama del contexto de instalación: el medidor de agua con salida de pulsos y el dispositivo IoT dentro de la caja domiciliaria, comunicándose por red celular con el servidor HES

La restricción que ordena todo el diseño es que la caja del medidor no tiene electricidad. El dispositivo funciona a batería y tiene que durar más de ocho años sin que nadie lo toque, porque mandar una cuadrilla a cambiar pilas casa por casa destruye la economía del proyecto. Todo lo demás —la elección del microcontrolador, la del módem, el diseño del protocolo— sale de ahí.

Ocho años con una batería

El dispositivo pasa casi toda su vida dormido. Un STM32L031K6, un Cortex-M0+ con 32 KB de flash, queda en modo Stop contando pulsos por interrupción, y el módulo celular Quectel BG95-M3 está completamente apagado. Una vez por día el reloj de tiempo real lo despierta, prende el módem, se adjunta a la red, manda el reporte y vuelve a apagar todo.

Caracterizamos el consumo con un Nordic Power Profiler Kit II, midiendo por separado el dominio del microcontrolador y el del módem. Los números del ciclo completo:

Traza de corriente del módem durante una sesión completa: 97,53 mA de promedio, 411,72 mA de pico y 1,43 C de carga en 14,70 segundos
  • Piso de reposo del micro: 2,94 µA de promedio, apenas por encima del STM32L031 desnudo.
  • Piso real del producto: ~15,9 µA, sumando la fuga del módem apagado. El piso lo domina el módulo celular, no el microcontrolador.
  • Una sesión: unos 15 segundos y 0,41 mAh. El módem se lleva casi todo: 97,5 mA de promedio con picos de 411,72 mA en la transmisión, contra 2,93 mA del micro.
  • Consumo anual: alrededor de 0,3 Ah, repartido casi por mitades entre las sesiones y la fuga del módem apagado.

Contra una batería de litio-cloruro de tionilo de 17 Ah, esos 0,3 Ah al año dejan el objetivo de ocho años cumplido con margen amplio. El resultado interesante es cuál pasa a ser el factor limitante: ya no es el consumo del dispositivo sino la autodescarga de la propia batería. Cuando el diseño llega a ese punto, seguir optimizando firmware deja de tener sentido.

Por qué un subconjunto de IEC 62056 y no DLMS completo

Los sistemas de medición inteligente estándar hablan DLMS/COSEM, la familia de normas IEC 62056. La pila completa es grande: para un dispositivo con 32 KB de flash y 8 KB de RAM, implementarla entera no entraba, y forzarla hubiera comido el presupuesto de memoria que necesitábamos para el resto.

La decisión fue quedarnos con la semántica de la norma y no con su pila: los objetos COSEM y el direccionamiento OBIS, sobre un protocolo binario propio y mínimo. Un dispositivo nuestro no interopera con un concentrador DLMS comercial, pero los datos que produce y la forma de pedirlos son conceptualmente los mismos, así que migrar a la pila completa más adelante es un cambio de transporte y no un rediseño. La sesión periódica son siete mensajes: HANDSHAKE, READ, WRITE y el ACK de cierre, con sus respuestas.

El servidor: por qué un clúster para un prototipo

El HES está escrito en Rust. La pregunta razonable es por qué un prototipo de tesis necesita un clúster, y la respuesta está en el párrafo anterior sobre la batería: si el servidor se cae o se satura, los dispositivos no completan la sesión, se quedan esperando y reintentan. Cada reintento prende la radio. Un problema de disponibilidad del servidor se paga en batería en todo el parque, y esa batería no se puede reponer sin mandar una cuadrilla.

Diagrama de la arquitectura del HES: el backdoor recibe los mensajes, asigna bucket al scheduler, ambos persisten en la capa de persistencia y reportan al sistema de monitoreo

Los nodos se descubren por gossip y se vigilan con detección de fallos SWIM; cuando un nodo cae, sus dispositivos se delegan a otro. El scheduler reparte el parque en 48 buckets horarios y asigna cada dispositivo nuevo al menos cargado, de modo que las sesiones se distribuyen en el día en lugar de amontonarse. La persistencia es PostgreSQL y todo el sistema publica métricas a Prometheus, con tableros de Grafana.

Para validarlo levantamos tres nodos —uno en el servidor de desarrollo y dos en una estación local, unidos por una red privada— contra una única base de datos, y les tiramos 80 dispositivos simulados en tres oleadas. En modo de prueba el scheduler programa las sesiones a los cinco minutos en lugar del horario diario, así se observan muchos ciclos completos en poco tiempo.

Panel de Grafana mostrando la distribución de dispositivos entre los nodos del clúster

Lo que no funcionó

Esta es la parte que más me sirvió del proyecto, y la que no aparece en ningún diagrama de arquitectura.

La red celular real no permitía el diseño

El protocolo estaba diseñado como pull: el HES abre la conexión hacia el dispositivo en su ventana de despertar. Es el modelo correcto, porque deja al servidor decidir cuándo habla cada medidor. Presupone una sola cosa: que el dispositivo sea alcanzable en una dirección estable.

Con una SIM comercial sobre APN público, eso no se cumple. La operadora asigna direcciones IPv6 dinámicas que cambian entre activaciones, así que la dirección que el dispositivo anuncia al registrarse ya no sirve en la siguiente ventana. Y el tráfico atraviesa un CGNAT: una conexión iniciada desde el servidor no encuentra ninguna traducción abierta y se descarta antes de llegar al dispositivo. El diseño era correcto y la red simplemente no lo permitía.

Comparación de topologías: sobre APN público el pull directo del HES queda bloqueado por el CGNAT y la sesión la inicia el dispositivo; con APN privada e IP fija el pull directo funciona

La salida fue invertir temporalmente quién inicia la sesión. El dispositivo ya mantiene abierto un socket saliente hacia el servidor, y ese socket sí atraviesa el CGNAT dejando un pinhole por el que el servidor puede responder. Agregamos un mensaje, SESSION_START_REQUEST, cuya única función es avisarle al HES que dispare la sesión sobre ese socket. El resto del protocolo y toda la máquina de estados del firmware se reutilizan sin tocar nada.

Lo que más me importó fue que no dejara deuda. Toda esa lógica está condicionada a la compilación, detrás de un flag en el firmware y de una feature en el HES: se compila sin ellos y vuelve el modelo original, intacto. La solución de producción no es de software sino comercial: una APN privada con IP fija por dispositivo y una interconexión privada con la operadora. La lección es esa: en un sistema IoT, el aprovisionamiento de red es una decisión de arquitectura y se negocia al principio del proyecto, no cuando ya tenés el prototipo andando.

Los 32 KB que no alcanzaron

El STM32L031K6 se eligió por consumo, y para la operación normal del medidor la elección fue buena: la lógica de aplicación, las máquinas de estado del módem y el protocolo entran cómodos. El límite apareció con dos funciones que el protocolo ya tenía previstas. La actualización remota necesita alojar dos imágenes de firmware a la vez más un bootloader que las valide, y eso no entra en 32 KB de banco único. La autenticación de mensajes compite por esa misma memoria, sobre un núcleo sin aceleración criptográfica.

Acá no hubo solución elegante: hubo un compromiso aceptado y documentado. Las dos funciones quedaron pendientes, con el lugar reservado en el protocolo —la operación EXECUTE y el campo del MAC— y un camino de resolución concreto: una segunda revisión con un STM32L4, que el margen de autonomía medido banca sin comprometer los ocho años. La lección, cara: la memoria de un microcontrolador se dimensiona para la funcionalidad de todo el ciclo de vida del producto, no para la de la primera versión.

Un cuello de botella del servidor se paga en batería

La primera implementación del receptor de mensajes era secuencial: recibía un datagrama, lo procesaba entero —validación, escritura en la base, respuesta— y recién después volvía a escuchar. Alcanzaba para las pruebas funcionales y era claramente insuficiente para una ráfaga: un despliegue masivo, o todos los dispositivos reintentando juntos después de un corte.

Mientras el bucle está ocupado escribiendo en PostgreSQL, los datagramas UDP se acumulan en el buffer del socket hasta desbordarlo, y el sistema operativo los descarta sin avisar. Cada mensaje perdido es un dispositivo que agota su ventana de espera, reintenta y vuelve a prender la radio. Ahí es donde la cosa se pone interesante: en un sistema alimentado a batería, una decisión de concurrencia del servidor se traduce en años de vida útil en el campo.

El receptor se rediseñó como despachador concurrente sobre Tokio: el bucle principal recibe y decodifica, y delega cada mensaje en una tarea independiente. Un semáforo con tope configurable da la contrapresión para que una ráfaga no agote la memoria ni las conexiones a la base. Validado con oleadas de registros concurrentes, sin pérdida de mensajes.

La placa

La PCB la diseñé en KiCad: microcontrolador, módulo celular con su adaptación de impedancia y antena, alimentación desde la batería con el supercapacitor de reservorio que absorbe los picos de 411 mA de la transmisión, y los planos de masa. Tiene que entrar en la caja domiciliaria, ser estanca y cumplir las normas de compatibilidad electromagnética.

Render 3D de la placa del medidor, con el módulo celular, el microcontrolador y la bornera de conexión

Qué queda pendiente

  • Un piloto con aprovisionamiento de producción: APN privada con IP fija e interconexión con la operadora, para validar el modelo pull original en campo y sacar el mecanismo provisional.
  • La segunda revisión de hardware con un microcontrolador de más memoria, que habilita la actualización remota y la autenticación de mensajes.
  • Tecnologías de acceso alternativas: NB-IoT como principal donde la cobertura CAT-M1 sea pobre, y una variante LoRaWAN si la proveedora prefiere operar sus propios gateways.

El código

  • Head-end-system-TPP — el servidor central en Rust: clúster, scheduler, persistencia y monitoreo.
  • Smart-Meter-Firmware-TPP — el firmware del dispositivo, en C, de Gonzalo Puy.
  • TPP-PCB — el proyecto de KiCad: esquemáticos, layout y verificaciones.

El informe completo desarrolla todo esto con el detalle que un post no permite: la comparativa de tecnologías LPWAN, el presupuesto energético teórico, el diseño del protocolo mensaje por mensaje, el diseño del PCB y el análisis de viabilidad económica.

Descargar el informe

PDF, unos 14 MB

Cierre

Lo que más me llevo no es ninguna de las piezas por separado, sino haber tenido que hacerlas funcionar juntas: electrónica de bajo consumo, radiofrecuencia, firmware embebido, diseño de protocolos, sistemas distribuidos y evaluación económica. Son disciplinas que en la carrera se ejercitan por separado, y el proyecto no dejaba escaparse de ninguna. Los tres problemas que conté salieron todos de la misma raíz: una decisión tomada en una de esas capas apareciendo, muchos meses después, como un síntoma en otra.

La defensa es el 7 de septiembre de 2026.