En cualquier tienda de electrónica de Santiago encuentras displays de 7 segmentos rojos de 0,56 pulgadas. Funcionan, cuestan poco y se ven exactamente igual que hace cuarenta años. Este proyecto toma esa misma lógica. siete segmentos que se prenden y se apagan para formar un dígito. y la reconstruye con LEDs WS2812 individuales dispuestos en curva, de modo que cada segmento puede tomar cualquiera de 16 millones de colores.

El resultado es un reloj de cuatro dígitos que muestra la hora, intercala la temperatura ambiente y cambia de color solo, cada minuto. Al terminar vas a saber tres cosas concretas: cómo se mapea una cadena lineal de LEDs a una matriz de segmentos, cómo leer la hora desde un DS3231 por I²C, y cómo alimentar 30 WS2812 sin quemar el regulador del Arduino en el intento.

Una aclaración antes de empezar: el proyecto original se armó sobre un Arduino Nano R4, la versión nueva con núcleo Renesas. Acá lo replicamos con el Arduino Nano V3 clásico (ATmega328), que es el que se consigue en Chile a menos de cinco mil pesos y que corre este código sin cambiar una sola línea. Los pines 2 a 6 que usa el firmware existen en ambas placas y las tres librerías del proyecto. FastLED, TimeLib y DS3232RTC. están portadas para AVR desde hace años.

Componentes necesarios para armar el reloj de segmentos redondos con LEDs NeoPixel

El concepto: siete segmentos, pero de luz direccionable

Un display de 7 segmentos tradicional es un bloque de plástico con siete barras en forma de ocho. Encendiendo distintas combinaciones se dibujan los dígitos del 0 al 9. La geometría es rígida: las barras son rectas, el color viene de fábrica y el brillo se ajusta con una resistencia.

El rediseño reemplaza cada barra recta por un segmento curvo iluminado por un LED WS2812. Cuatro dígitos de siete segmentos suman 28 LEDs, más dos para los dos puntos que parpadean entre horas y minutos: 30 en total. Como los WS2812 son direccionables, se conectan todos en cadena y un solo pin de datos del Arduino controla los 30.

Diseño del dígito de segmentos redondos con la disposición curva de cada segmento

Por qué basta un cable de datos para 30 LEDs

Esto no lo explica el tutorial original y vale la pena entenderlo, porque es la razón de que el montaje sea tan simple. Cada WS2812 lleva adentro un controlador que hace de repetidor: recibe la trama completa por su pin DIN, se queda con los primeros 24 bits (8 de verde, 8 de rojo, 8 de azul) y retransmite el resto por su pin DOUT hacia el siguiente LED de la cadena.

El protocolo codifica los bits por ancho de pulso a 800 kHz: un "0" es un pulso alto de ~0,4 µs y un "1" uno de ~0,8 µs, siempre dentro de un período de 1,25 µs. Refrescar 30 LEDs toma entonces 30 × 24 × 1,25 µs ≈ 0,9 ms, más un pulso de reset de 50 µs. Por eso FastLED.show() no se nota: bloquea el procesador menos de un milisegundo.

La consecuencia práctica es que el orden físico de la cadena define el índice del arreglo. El LED que soldaste primero es leds[0], el siguiente leds[1], y así. Si te equivocas en el orden al montar, no se rompe nada, pero los segmentos se prenden en lugares que no corresponden. Vale la pena numerarlos con marcador antes de pegarlos.

Hardware y presupuesto eléctrico

La lista es corta: la placa controladora, el reloj de tiempo real, los 30 LEDs, tres pulsadores (hora, minutos y horario de verano), un interruptor de encendido y la alimentación a batería.

Placa Arduino Nano usada como controlador del reloj

El DS3231 es la pieza que hace que esto sea un reloj y no una cuenta desde el último reset. Trae un cristal compensado por temperatura con una deriva típica de ±2 ppm, o sea alrededor de un minuto al año, y una pila de respaldo que mantiene la hora aunque desconectes todo. De yapa incluye un sensor de temperatura interno con resolución de 0,25 °C, que es justamente el que este reloj usa para mostrar la temperatura ambiente. No hay sensor externo en el proyecto: es el termómetro del propio chip del RTC.

Cuánta corriente consumen realmente 30 WS2812

Este es el punto donde más proyectos con NeoPixel fallan, y el tutorial original lo pasa por alto. Los números:

  • Un WS2812 5050 a blanco pleno consume unos 60 mA (20 mA por canal).
  • 30 LEDs a blanco pleno: 1,8 A. Muy por encima de lo que entrega el regulador AMS1117 del Nano, que se calienta antes de llegar a 500 mA.
  • En la práctica el reloj nunca llega ahí. Con FastLED.setBrightness(75) estás al 29 % del máximo, y una hora típica prende unos 20 de los 30 LEDs en un solo color, no en blanco. El consumo real ronda los 150 a 350 mA.

Aun así, 350 mA es demasiado para colgarlos del pin 5V del Arduino. La regla es simple: los LEDs se alimentan desde el convertidor boost, no desde la placa, y las masas se unen en un punto común. El Arduino solo aporta la señal de datos.

Dos protecciones que conviene agregar aunque el diseño original no las traiga: una resistencia de 330 Ω en serie con el pin de datos, para amortiguar reflexiones en el cable, y un condensador electrolítico de 1000 µF entre 5 V y GND cerca del primer LED, que absorbe el golpe de corriente del encendido.

La alimentación se resuelve con una batería 18650 de litio, un módulo cargador TP4056 con protección de sobredescarga, y un convertidor boost que sube los 3,7 V de la batería a los 5 V que piden los WS2812. Con 4800 mAh y un consumo promedio de 250 mA, el reloj aguanta cerca de un día desconectado; la idea es que quede enchufado y la batería sea respaldo.

Esquema de conexiones del reloj: Arduino, RTC DS3231, cadena de LEDs y pulsadores

Las conexiones quedan así:

Señal Pin del Arduino Nano
Datos de la cadena WS2812 D6
SDA del DS3231 A4
SCL del DS3231 A5
Botón de horas D2
Botón de minutos D3
Sensor de luz / brillo D4
Botón de horario de verano D5

Los tres botones van directo a masa: el firmware activa las resistencias de pull up internas del ATmega328, así que no necesitas resistencias externas.

El software: de una cadena de LEDs a un dígito legible

El firmware se apoya en tres librerías. FastLED genera la trama de bits del protocolo WS2812, DS3232RTC habla I²C con el reloj y TimeLib provee las estructuras de fecha y hora.

C++
#include <DS3232RTC.h>
#include <TimeLib.h>
#include <Wire.h>
#include <FastLED.h>
DS3232RTC myRTC(false);
#define NUM_LEDS 30
#define COLOR_ORDER RGB  // Define color order for your strip
#define LED_PIN 6 // Data pin for led comunication
#define DST_PIN 5  // Define DST adjust button pin
#define MIN_PIN 3  // Define Minutes adjust button pin
#define HUR_PIN 2  // Define Hours adjust button pin
#define BRI_PIN 4 // Define Light sensor pin
CRGB leds[NUM_LEDS];

Si al encender los colores salen cambiados. el rojo aparece verde, por ejemplo. el culpable es COLOR_ORDER. Muchos lotes de WS2812B esperan GRB en vez de RGB. Cambiar esa línea es todo el arreglo; no toques el cableado.

La tabla de segmentos

Acá está el corazón del asunto. Una tira de LEDs es un arreglo lineal; un dígito es una matriz de siete segmentos. El puente entre ambos es una tabla de consulta:

C++
byte digits[12][7] = {
 {1,0,1,1,1,1,1},
 {1,0,1,0,0,0,0},
 {0,1,1,1,0,1,1},
 {1,1,1,1,0,0,1},
 {1,1,1,0,1,0,0},
 {1,1,0,1,1,0,1},
 {1,1,0,1,1,1,1},
 {1,0,1,1,0,0,0},
 {1,1,1,1,1,1,1},
 {1,1,1,1,1,0,0},
 {0,0,0,1,1,1,1},
 {0,1,1,1,1,0,0}};

Cada fila es un símbolo y cada columna un segmento. Un 1 enciende ese segmento y un 0 lo deja apagado. Las diez primeras filas son los dígitos del 0 al 9; las dos últimas son símbolos hechos a medida para el modo termómetro. el círculo del grado y la letra C. , y por eso la tabla tiene doce filas y no diez.

Fíjate en la fila del 8: {1,1,1,1,1,1,1}, todos los segmentos encendidos, que es exactamente lo que uno espera. Y la del 1: {1,0,1,0,0,0,0}, solo dos segmentos. Si algún día quieres mostrar letras, agregar una fila más a esta tabla es todo el trabajo.

La rutina que dibuja recorre los cuatro dígitos de derecha a izquierda extrayendo cifras con Now % 10 y Now /= 10, y para cada una posiciona un cursor en el LED donde empieza ese dígito: 21 para el de las unidades de minuto, 14, 7 y 0 para el resto. Son saltos de siete porque cada dígito ocupa siete LEDs consecutivos.

Inicialización

C++
void setup(){ 
 Serial.begin(9600); 
 Wire.begin();
 myRTC.begin();
 FastLED.addLeds<WS2812B, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
 FastLED.setBrightness(75); // Set initial brightness
 pinMode(DST_PIN, INPUT_PULLUP); // Define DST adjust button pin
 pinMode(MIN_PIN, INPUT_PULLUP); // Define Minutes adjust button pin
 pinMode(HUR_PIN, INPUT_PULLUP); // Define Hours adjust button pin
 pinMode(BRI_PIN, INPUT_PULLUP); // Define bright adjust 
 TempShow = false; // do not show temperature 
}

INPUT_PULLUP es la razón de que los botones no lleven resistencias: el microcontrolador mantiene el pin en 3,3 a 5 V por dentro y la pulsación lo baja a masa.

La lectura de la hora

C++
int GetTime(){
 tmElements_t Now;
 myRTC.read(Now);
 int hour=Now.Hour;
 int minute=Now.Minute;
 int second =Now.Second;
 if (second % 2==0)
  {Dot = false;}
   else {Dot = true;};

 // Apply DST adjust before 12-hour conversion
 if (DST){   
   hour = (hour + 1) % 24;
 };
 if (hour >= 12) {
   hour -= 12;
 }
 if (hour == 0) {
   hour = 12;
 }
 return (hour*100+minute);
};

Dos detalles finos. El parpadeo de los dos puntos no usa ningún temporizador: sale de mirar si el segundo actual es par o impar, lo que da un parpadeo exacto de un segundo gratis. Y la hora completa se comprime en un solo entero. las 16:15 se vuelven 415— para poder desarmarla después con divisiones sucesivas.

Ojo con la línea del horario de verano. En el código viene bool DST = true;, o sea suma una hora sobre lo que marca el RTC. En Chile continental el cambio de hora rige entre septiembre y abril, así que lo más cómodo es dejar el RTC con la hora real y usar el botón D5 para activar o desactivar ese ajuste cuando corresponda, en vez de reprogramar el reloj dos veces al año.

El problema de los delays bloqueantes

El firmware original funciona, pero tiene un defecto que se nota apenas lo usas: bloquea el procesador durante segundos completos. Hay dos culpables.

El primero es el efecto de transición cylon(), que barre la cadena con un arcoíris cada vez que cambia el minuto. Son dos ciclos de 30 iteraciones con un delay(10) adentro: unos 600 ms en que el Arduino no lee ningún botón.

El segundo es más grave. Al final del bucle principal está esto:

C++
void loop()  // Main loop
{
 BrightnessCheck(); // Check brightness
 DSTcheck(); // Check DST
 TimeAdjust(); // Check to se if time is geting modified
 TimeToArray(); // Get leds array with required configuration
 TempToArray();
 FastLED.show(); // Display leds array
 if (TempShow == true)
 delay (8000);

}

Cuando el segundo 27 dispara el modo termómetro, el delay(8000) congela todo por ocho segundos. Si en ese rato aprietas el botón de la hora, no pasa nada: el evento se pierde. Es el clásico caso en que el usuario cree que el botón está malo cuando en realidad el firmware no está mirando.

La solución es la de siempre, millis() en lugar de delay(). En vez de detener el programa, anotas cuándo empezó la ventana de ocho segundos y en cada vuelta preguntas si ya pasó:

C++
// Reemplazo no bloqueante del delay(8000) del bucle original.
// La temperatura se sostiene 8 s sin dejar de leer los botones.
unsigned long tempInicioMs = 0;
bool mostrandoTemp = false;

void loop() {
  BrightnessCheck();
  DSTcheck();
  TimeAdjust();

  if (mostrandoTemp) {
    if (millis() - tempInicioMs >= 8000) mostrandoTemp = false;
    FastLED.show();
    return;
  }

  TimeToArray();
  TempToArray();
  if (TempShow) {
    mostrandoTemp = true;
    tempInicioMs = millis();
  }
  FastLED.show();
}

La resta millis() - tempInicioMs no es un capricho de estilo: escrito así el código sigue funcionando cuando millis() desborda a los 49 días de encendido. Comparar directo con millis() < limite falla justo en ese momento y deja el reloj pegado.

Montaje: con PCB o sin ella

El autor original diseñó una PCB en EasyEDA con los 30 LEDs por delante y el Arduino, el RTC y los botones por detrás.

Diseño de la PCB del reloj con los LEDs distribuidos según los segmentos

Placas PCB fabricadas listas para el montaje

Cara frontal de la PCB con los 30 LEDs WS2812 soldados

Es la opción prolija, pero mandar a fabricar una PCB desde Chile significa tres a cuatro semanas de espera y un costo de envío que suele superar el de las placas mismas.

La alternativa sin PCB funciona igual de bien y es la que recomendamos para una primera versión:

  1. Imprime en papel el patrón de los cuatro dígitos a tamaño real. Basta con dibujar los siete segmentos curvos en cualquier programa de diseño y repetir el dígito cuatro veces con el espacio de los dos puntos al medio.
  2. Pega el papel sobre una plancha de MDF de 3 mm o cartón pluma y perfora un agujero en el centro de cada segmento.
  3. Corta la cinta WS2812B por las marcas de corte. vienen cada tres LEDs en las de 60 LED/m, así que corta de a uno por los almohadillados de cobre. y pega cada LED sobre su segmento respetando la flecha de dirección de datos impresa en la cinta.
  4. Suelda los tres puentes (5V, GND, DIN→DOUT) entre LED y LED con cable delgado, siguiendo el orden que definiste.

Es más lento que soldar sobre una PCB, pero no dependes de ningún proveedor externo y puedes rehacer la geometría cuando quieras. La flecha de la cinta es lo único que no perdona: si la inviertes en un LED, todos los que vienen después quedan apagados.

Para la carcasa, el diseño original se imprimió en 3D en dos colores: las primeras capas en filamento blanco, que actúa como difusor y reparte la luz de cada LED por todo el segmento, y el resto en negro para dar contraste. Si tu impresora no hace cambio de color, imprime la carcasa completa en negro y pega encima una lámina de acrílico opal o simplemente papel mantequilla: el efecto difusor es prácticamente el mismo.

Diseño 3D de la carcasa del reloj

Impresión 3D de la carcasa con la técnica de dos colores para el difusor

Pruebas y puesta en hora

Antes de cerrar la carcasa, conviene verificar por partes:

  • Los LEDs, primero solos. Carga el ejemplo Blink de FastLED con NUM_LEDS 30 y confirma que los 30 responden. Si se cortan en el LED número 12, ahí hay una soldadura fría.
  • El RTC, por el monitor serie. El firmware imprime la temperatura leída. Si sale un valor absurdo o -127, el I²C no está enganchando: revisa SDA en A4 y SCL en A5.
  • El orden de los dígitos. Es el error más común del montaje sin PCB. Si la hora se muestra al revés o los dígitos aparecen barajados, no toques el código: reordena la cadena física, que es lo que estaba mal.
  • La hora. Con el reloj andando, ajusta con los botones D2 (horas) y D3 (minutos). Cada pulsación escribe el valor nuevo directamente en el DS3231, así que la hora sobrevive a un corte de luz.

En el segundo 27 de cada minuto el display cambia solo a la temperatura durante ocho segundos y después vuelve a la hora. No es un error: es el modo termómetro.

Reloj de segmentos redondos completamente armado

Reloj funcionando y mostrando la hora con el cambio automático de color

Variantes y mejoras

Tres extensiones que el proyecto original no cubre y que se montan sobre lo que ya tienes:

Brillo automático de verdad. El firmware lee el pin D4 como si fuera un sensor de luz, pero lo hace con digitalRead(), o sea solo distingue "claro" u "oscuro". Cambia D4 por una entrada analógica (A0, por ejemplo) con un LDR y una resistencia de 10 kΩ formando divisor, y usa map(analogRead(A0), 0, 1023, 10, 120) para tener brillo continuo. Un reloj que a las tres de la mañana no te encandila vale el cambio.

Sincronización por WiFi. Reemplaza el Arduino Nano por un ESP32 y el DS3231 pasa a ser opcional: con la librería time.h y un servidor NTP la hora se ajusta sola, incluido el cambio de horario chileno si configuras la zona <-04>4<-03>,M9.1.6/24,M4.1.6/24. Puedes dejar el RTC igual como respaldo para los cortes de internet.

Temperatura y humedad exteriores. El DS3231 mide la temperatura de su propio chip, que dentro de una carcasa cerrada corre uno o dos grados por sobre la real. Agregando un DHT22 o un BME280 por fuera de la caja obtienes una lectura honesta, y con los dos símbolos libres de la tabla digits[12][7] puedes alternar entre temperatura y humedad.

Personalización para Chile

Todo lo necesario está en el catálogo de MechatronicStore:

  • Arduino nano V3.0 CH340 Compatible + Cable (SKU N-302). $4.490 CLP
  • Módulo Reloj RTC DS3231 (SKU G-101V2). $6.490 CLP
  • Cinta led WS2812B 5 V 5050 RGB 60/PCB 5M IP65 (SKU G-599). $23.990 CLP
  • Botón pulsador switch de 4 pines 12x12x8mm (SKU GA6-16). $290 CLP c/u, necesitas 3
  • Interruptor de palanca MTS 101 de 2 pines On/Off (SKU GD2-6). $890 CLP
  • Batería 18650 original 3.7V 4800 mah (SKU GT2-10). $3.390 CLP
  • Porta Batería 18650×1 (SKU L-325). $1.390 CLP
  • TP4056 controlador y protector de carga batería 18650 Tipo C (SKU GQ2-12). $1.990 CLP
  • Convertidor Boost Step Up Regulador De Voltaje 5V/8V/9V/12V (SKU GN1-5). $1.490 CLP
  • Fila de 40 pines pin header hembra 2.54mm (SKU GD2-3). $490 CLP
  • Fila de pin header 2.54mm 40 pines macho Negro (SKU GD3-3). $290 CLP

Dos equivalencias que conviene tener claras:

El tutorial original usa un Arduino Nano R4, que no se vende en Chile. El Nano V3 con ATmega328 del catálogo corre este firmware sin modificaciones: los pines D2 a D6 y el bus I²C en A4/A5 están en el mismo lugar, y las tres librerías son compatibles con AVR. La única diferencia real es la memoria, y este proyecto usa una fracción de la que tiene el ATmega328.

Sobre los LEDs: el proyecto pide 30 WS2812 sueltos para soldar en una PCB. La forma de conseguirlos acá es cortar la cinta WS2812B de 5 metros, que trae 60 LEDs por metro con almohadillas de cobre entre cada uno. Sacas los 30 que necesitas y te quedan 270 para los próximos proyectos. Si prefieres módulos individuales ya montados en plaquita, el catálogo tiene el 1 Bit WS2812 5050 (SKU C-330), pero su stock suele estar por debajo de las 30 unidades que pide este reloj, así que revisa disponibilidad antes de encargarlo.

Los dos ítems que no se venden en tienda son la PCB personalizada. que puedes reemplazar por el montaje sobre plantilla descrito más arriba. y el filamento PLA blanco y negro para la carcasa impresa en 3D.

Presupuesto total aproximado: $61.000 CLP, contando la cinta completa de 5 metros. Si ya tienes cinta WS2812B de otro proyecto, baja a menos de $30.000.

Recursos

Versión chilena inspirada en el proyecto de Circuit Digest, adaptada al Arduino Nano V3 clásico y con componentes en stock local en MechatronicStore.