← Índice del curso

Sensores y Actuadores · Tema 16

Taller: luz nocturna automática

Parece el proyecto más simple del curso: encender una luz cuando oscurece. Pero una lámpara que ilumina su propio sensor se apaga a sí misma, una sombra pasajera la enciende, y un LED conmutado de golpe resulta molesto. En este taller resolvemos cada problema: histéresis, confirmación temporal, compensación de la luz propia, corrección gamma y transiciones suaves.

01 · Punto de partida

Qué vamos a construir

Una luz nocturna que se enciende sola cuando la habitación queda a oscuras y se apaga cuando amanece. La especificación parece de una línea, y por eso sirve para ver cuánto hay detrás de un comportamiento «obvio». El taller usa lo que ya sabemos: el LDR y su divisor (tema 14), la histéresis (temas 7 y 13), el filtrado (tema 5), los eventos de un botón (tema 8) y el PWM del curso de Microcontroladores. Los requisitos son:

  • Medir la luz ambiente con un LDR y estimarla en lux.
  • Encender cuando haya menos de 10 lux y apagar cuando haya más de 30 lux, sin temblar entre ambos.
  • No reaccionar a sombras pasajeras, faros de autos o una linterna: exigir que la condición se mantenga 10 segundos.
  • Regular el brillo con PWM: tenue en penumbra, más intenso en oscuridad total, con la corrección que exige la percepción del ojo.
  • Pasar de un brillo a otro de forma gradual, nunca de golpe.
  • No confundir su propia luz con la del ambiente.
  • Admitir un botón para forzar el encendido y volver al modo automático.
  • No bloquear el programa en ningún momento.

02 · Paso 1

El comportamiento como máquina de estados

Antes de escribir código, se dibuja el comportamiento. «Encender si oscuro» no basta: entre oscuro y claro hay decisiones que se confirman con el tiempo, y eso se resuelve con cuatro estados:

Estados del control automático y sus transiciones.
EstadoLámparaPasa a…Cuando…
DÍAApagadaCONFIRMANDO NOCHELa luz estimada baja de 10 lux
CONFIRMANDO NOCHEApagadaNOCHE
DÍA
Pasan 10 s sin que la luz vuelva a subir de 10 lux
La luz vuelve a 10 lux o más (era una sombra)
NOCHEEncendida (brillo según la oscuridad)CONFIRMANDO DÍALa luz estimada supera 30 lux
CONFIRMANDO DÍAEncendidaDÍA
NOCHE
Pasan 10 s sin que la luz baje de 30 lux
La luz vuelve a 30 lux o menos (era un destello)

Los dos estados de confirmación son los que dan robustez: una condición debe sostenerse antes de actuar. Los umbrales 10 y 30 lux forman la banda de histéresis, y el tiempo de confirmación elimina los destellos breves. Se combinan, y cada uno cubre un tipo de perturbación: la histéresis, el ruido pequeño y continuo; la confirmación, los eventos grandes pero cortos.

Una pregunta de diseño central, que el taller deja para el paso 4: ¿qué luz se compara con los umbrales, la que mide el sensor o la del ambiente? Son distintas cuando la lámpara está encendida.

Plan de tareas y tiempos.
TareaPeríodoQué hace
Muestreo de luz y máquina de estados1 sLee el LDR, filtra, estima los lux y avanza el estado
Transición de brillo20 msMueve el brillo hacia el objetivo y actualiza el PWM
Botóncada vuelta del bucleDetecta clic y pulsación larga

03 · Paso 2

El cableado

Conexiones (Arduino Uno).
ElementoConexiónObservaciones
LDR5 V → LDR → A0Más luz, más tensión (tema 14)
Resistencia fijaA0 → 10 kΩ → masaSu valor fija la zona útil del divisor (10 a 1000 lux)
LEDD9 → resistencia de 220 Ω → LED → masaD9 tiene PWM; para una tira o un LED de potencia se necesita un MOSFET (tema 27)
BotónD2 → botón → masaCon el pull-up interno (tema 6)

El montaje físico concentra el principal problema del taller: el LDR no debe «ver» al LED. Conviene separarlos, orientar el LDR hacia la ventana o la habitación y el LED hacia el suelo o la pared opuesta, o aislarlos con una pantalla opaca. Cuanto menos luz propia llegue al sensor, más fácil es el control (paso 4). Y el LDR necesita un pequeño difusor para que no lo engañe un único rayo directo.

04 · Paso 3

Medir la luz con confianza

La cadena de medición es la del tema 14, con un filtro encima. Cada segundo se toma una muestra, se la guarda en una ventana de tres y se usa la mediana para rechazar valores aislados (un destello de una sola muestra no pasa); la mediana pasa por un filtro exponencial que suaviza el resto (tema 5). Luego se estima la luz con la ley de potencia del LDR:

const uint8_t PIN_LDR = A0;
const float R_FIJA = 10000.0;        // a masa; el LDR va a Vcc
const float R10 = 15000.0, GAMMA_LDR = 0.6;   // parámetros del LDR (hoja de datos)

float ventana[3] = {50, 50, 50};      // últimas tres lecturas, en lux
uint8_t indiceVentana = 0;
float luxFiltrado = 50;

float luxDesdeAdc() {
    int c = analogRead(PIN_LDR);
    if (c <= 1) return NAN;                       // LDR desconectado o oscuridad total
    if (c >= 1022) return 100000.0;               // saturado: mucha luz
    float rLdr = R_FIJA * (1023.0 - c) / c;
    return 10.0 * pow(R10 / rLdr, 1.0 / GAMMA_LDR);
}

float mediana3(float a, float b, float c) {
    return max(min(a, b), min(max(a, b), c));
}

void muestrearLuz() {                              // se llama una vez por segundo
    float lux = luxDesdeAdc();
    if (isnan(lux)) lux = 0.1;                     // sin LDR o a oscuras: se trata como oscuridad
    ventana[indiceVentana] = lux;
    indiceVentana = (indiceVentana + 1) % 3;
    float m = mediana3(ventana[0], ventana[1], ventana[2]);
    luxFiltrado += 0.3 * (m - luxFiltrado);        // filtro exponencial, alfa = 0,3
}

Dos decisiones merecen atención. El filtro se aplica a los lux (no a las cuentas): como la luz abarca décadas, un promedio lineal está dominado por los valores altos. Y un LDR desconectado (cuentas 0) se trata como oscuridad: en una luz nocturna, encenderse ante la duda es el comportamiento seguro, y coincide con el caso más probable (una habitación oscura). Elegir cómo se comporta el sistema ante una falla de modo que coincida con la acción correcta del caso normal simplifica el diseño.

05 · Paso 4

La lámpara ve su propia luz

Ahora, el problema central. Cuando la lámpara está encendida, parte de su luz llega al LDR, de modo que la luz medida es la del ambiente más el aporte de la lámpara:

Lmedida = Lambiente + A × brillo

donde A es la luz que la lámpara a pleno brillo aporta al sensor, en lux. Es una realimentación positiva de signo problemático: al encender, la luz medida sube; si sube por encima del umbral de apagado, la lámpara se apaga; entonces la luz medida baja de nuevo por debajo del umbral de encendido, y se vuelve a encender. El resultado es una oscilación permanente, aunque la habitación esté oscura y estable. Analicemos cuándo ocurre.

Con la lámpara encendida y el ambiente casi a oscuras (Lambiente ≈ 0), la luz medida es A. Para que no se apague hace falta A menor que el umbral de apagado. Pero con histéresis la condición es más fuerte: un ambiente apenas por debajo del umbral de encendido (10 lux) tiene que seguir dando una luz medida menor que 30 lux con la lámpara encendida:

A < Uapagado − Uencendido = 30 − 10 = 20 lux

Si el aporte de la lámpara es mayor que el ancho de la banda de histéresis, el sistema oscila en el entorno del anochecer. Hay cuatro remedios, que se combinan:

Remedios contra la realimentación óptica.
RemedioCómo funcionaLímite
Aislamiento ópticoPantalla, orientación y distancia que reduzcan ANo siempre es posible en un producto compacto
Banda de histéresis mayorSubir el umbral de apagado hasta que supere A con margenSe enciende a oscuras pero tarda en apagarse; reduce la sensibilidad
Confirmación temporalExige que la condición se sostenga varios segundosConvierte una oscilación rápida en una lenta, pero no la elimina
Compensación de la luz propiaRestar el aporte conocido: Lambiente = Lmedida − A × brilloExige conocer A (se mide en la instalación) y el brillo real

La compensación es el remedio de fondo, porque ataca la causa. Se mide A una vez, en la instalación, con el ambiente a oscuras: se enciende la lámpara a pleno y se anota la luz medida. Después, en cada ciclo, se estima el ambiente restando A × brillo, con el brillo realmente aplicado en ese momento. Hay que tener en cuenta el retardo: el sensor mide el efecto de un brillo que ya cambió, por eso conviene usar el brillo del ciclo anterior.

06 · Paso 5

Brillo percibido y PWM

El PWM regula la potencia media del LED, y un LED emite una luz aproximadamente proporcional a su corriente media. Pero el ojo no percibe la luz de forma lineal: es sensible a las relaciones, no a las diferencias (tema 14). Un PWM de 50 % no se ve «la mitad de brillante» que uno de 100 %, sino bastante más intenso; el brillo percibido sigue aproximadamente una potencia de 0,4 de la luz emitida. Si el programa varía el PWM linealmente, la lámpara parece cambiar mucho al principio y casi nada al final.

La solución es la corrección gamma: se define un nivel de brillo percibido entre 0 y 1 y se lo convierte en ciclo de trabajo elevándolo a una potencia (alrededor de 2,2):

ciclo de trabajo = brilloγ (γ ≈ 2,2) ⇒ duty = round(255 × brillo2,2)
Brillo percibido deseado y ciclo de trabajo PWM de 8 bits con γ = 2,2.
Brillo percibidoSin corrección (duty)Con gamma 2,2 (duty)
10 %262
20 %517
50 %12856
80 %204156
100 %255255

La tabla muestra un detalle con consecuencias: para un brillo del 10 % bastan 2 niveles de 255. Con un PWM de 8 bits, los brillos bajos tienen muy pocos escalones y se ven a saltos; es el precio de la corrección gamma. Por eso las lámparas de buena calidad usan 10 a 16 bits de resolución o dithering (alternar valores vecinos) en los niveles bajos. En una luz nocturna, que opera sobre todo a niveles bajos, conviene un PWM de mayor resolución (el Timer1 del ATmega328P admite hasta 16 bits). Otra cuestión: la frecuencia del PWM debe ser lo bastante alta (cientos de hertz como mínimo; mejor kilohertz) para que no se perciba el parpadeo ni interfiera con cámaras.

07 · Paso 6

Transiciones suaves

Una luz que se enciende de golpe a plena potencia en la oscuridad molesta, y una que se apaga bruscamente desconcierta. La solución es un limitador de velocidad (slew-rate limiter, tema 5): el brillo real persigue al brillo objetivo avanzando un paso máximo por unidad de tiempo.

const float PASO_FADE = 0.01;          // 1 % cada 20 ms: de 0 a 100 % en 2 s
float brillo = 0.0;                    // brillo percibido actual (0 a 1)
float objetivo = 0.0;                  // al que se quiere llegar

uint8_t dutyConGamma(float b) {
    return (uint8_t)(255.0 * pow(b, 2.2) + 0.5);
}

void actualizarBrillo() {              // se llama cada 20 ms
    float diferencia = objetivo - brillo;
    if (diferencia > PASO_FADE) brillo += PASO_FADE;
    else if (diferencia < -PASO_FADE) brillo -= PASO_FADE;
    else brillo = objetivo;
    analogWrite(PIN_LED, dutyConGamma(brillo));
}

Una consecuencia sutil: el brillo que mide el sensor (y que se usa en la compensación) es el brillo actual, no el objetivo. Por eso el programa guarda ambos: el objetivo decide, el actual se aplica y se descuenta.

08 · Paso 7

El programa completo

Con las piezas anteriores, el programa es la máquina de estados del paso 1 y dos tareas periódicas. El estado se actualiza una vez por segundo con la luz del ambiente (medida menos el aporte propio), y el brillo se mueve cada 20 ms:

const float    U_ENCENDER  = 10.0;     // lux: por debajo, oscuro
const float    U_APAGAR    = 30.0;     // lux: por encima, claro
const uint32_t T_CONFIRMAR = 10000;    // ms que debe sostenerse la condición
const float    A_LAMPARA   = 15.0;     // lux que aporta la lámpara a pleno (medido en la instalación)

enum Estado { DIA, CONFIRMANDO_NOCHE, NOCHE, CONFIRMANDO_DIA };
Estado estado = DIA;
uint32_t tEstado = 0;
bool forzado = false;                  // modo manual (luz de lectura)

float luzAmbiente() {
    return max(0.0, luxFiltrado - A_LAMPARA * brillo);   // se resta lo que aporta la propia lámpara
}

float brilloSegunOscuridad(float lux) {                 // 20 % en penumbra hasta 100 % a oscuras
    float t = constrain((U_ENCENDER - lux) / (U_ENCENDER - 0.5), 0.0, 1.0);
    return 0.2 + 0.8 * t;
}

void avanzarEstado(uint32_t ahora) {
    float lux = luzAmbiente();
    switch (estado) {
        case DIA:
            if (lux < U_ENCENDER) { estado = CONFIRMANDO_NOCHE; tEstado = ahora; }
            break;
        case CONFIRMANDO_NOCHE:
            if (lux >= U_ENCENDER) estado = DIA;                             // era una sombra
            else if (ahora - tEstado >= T_CONFIRMAR) estado = NOCHE;
            break;
        case NOCHE:
            if (lux > U_APAGAR) { estado = CONFIRMANDO_DIA; tEstado = ahora; }
            break;
        case CONFIRMANDO_DIA:
            if (lux <= U_APAGAR) estado = NOCHE;                             // era un destello
            else if (ahora - tEstado >= T_CONFIRMAR) estado = DIA;
            break;
    }
    bool encendida = (estado == NOCHE || estado == CONFIRMANDO_DIA);
    objetivo = forzado ? 0.6 : (encendida ? brilloSegunOscuridad(lux) : 0.0);
}

uint32_t tMuestra = 0, tFade = 0;

void loop() {
    uint32_t ahora = millis();

    if (ahora - tMuestra >= 1000) {          // tarea de 1 s
        tMuestra = ahora;
        muestrearLuz();
        avanzarEstado(ahora);
    }
    if (ahora - tFade >= 20) {               // tarea de 20 ms
        tFade = ahora;
        actualizarBrillo();
    }

    uint8_t ev = actualizar(boton);          // detector de eventos del tema 8
    if (ev & EV_CLICK) forzado = !forzado;   // un clic alterna la luz de lectura
    if (ev & EV_LARGA) forzado = false;      // pulsación larga: vuelve al automático
}

Fijate en las propiedades que se heredan del resto del curso: nada bloquea (todo son comparaciones con millis()), cada tarea tiene su período, el estado de confirmación usa restas sin signo, y el botón es el detector reutilizable del tema 8. La lógica de decisión está separada del PWM y del sensor, lo que permite probar la máquina de estados con luces simuladas, como hace el simulador de este tema.

09 · Paso 8

Verificar

Plan de pruebas de la luz nocturna.
PruebaCómo se haceResultado esperado
AnochecerBajar lentamente la luz (con una cartulina o un regulador)Tras 10 s por debajo de 10 lux, se enciende con una subida suave
AmanecerSubir la luz más allá de 30 luxTras 10 s, se apaga con una bajada suave
Sombra pasajeraTapar el LDR 3 s con la mano durante el díaNo se enciende (la confirmación se cancela)
Destello nocturnoIluminar el LDR con una linterna 3 s por la nocheNo se apaga
RealimentaciónEncender con el ambiente oscuro y estable, 10 minutosSe mantiene encendida sin parpadear
Medir AA oscuras, lámpara a pleno, anotar la luz medida; repetir al 50 %La luz medida es proporcional al brillo; A se carga en el programa
Banda de histéresisDejar la luz entre 10 y 30 luxMantiene el estado en que estaba, encendida o apagada
BotónClic, otro clic y pulsación largaEnciende al 60 %, apaga (auto) y vuelve al automático
LDR desconectadoDesenchufarloSe trata como oscuridad: se enciende (acción segura)
Brillos bajosMirar la lámpara al 5–10 % en la oscuridadSin saltos visibles; si los hay, aumentar la resolución del PWM

La prueba más reveladora es la de la realimentación: con el sistema sin compensar, una lámpara que aporta más luz que el ancho de la banda oscila durante la noche, y el fallo se ve a simple vista, con una luz que parpadea sin cesar, aunque nada cambie en la habitación.

10 · Paso 9

Fallas y robustez

  • LDR desconectado o en corto. Desconectado: cuentas cercanas a 0, tratado como oscuridad (la lámpara se enciende). En corto con Vcc: cuentas de 1023, tratado como mucha luz (la lámpara se apaga, con un día aparente permanente). Es la falla menos segura, y se detecta con un control de coherencia: una «mucha luz» que no varía nunca en 24 horas es sospechosa.
  • Envejecimiento del LED. Con el tiempo emite menos, y A cambia. Conviene revisar el valor de A en cada mantenimiento, o medirlo automáticamente en la primera noche tras la instalación.
  • Suciedad en el sensor. Un LDR cubierto de polvo ve menos luz y mantiene la lámpara encendida de día. Un difusor limpiable y una revisión periódica lo evitan.
  • Luz parásita nocturna. Farolas, pantallas y LED de otros equipos elevan la luz «nocturna» por encima de 10 lux. Los umbrales se ajustan en la instalación, no en el escritorio.
  • Desborde de millis(). Todas las comparaciones de tiempo usan restas sin signo y toleran los 49 días.
  • Corte de energía. Al volver, el programa arranca en DÍA con los filtros en un valor neutro; en la primera noche, tarda un ciclo de confirmación en reaccionar. Un valor inicial de los filtros cercano al umbral evita que la lámpara se encienda sin motivo al arrancar de día.

11 · Analogía con programación

Simular un día completo con cuatro estrategias

La máquina de estados no necesita hardware para probarse. Simulamos 24 horas, con una muestra por minuto: una curva de luz diaria con ruido del 20 %, tres destellos nocturnos de 150 lux (faros de autos) y una lámpara que aporta 15, 25 o 40 lux al sensor cuando está encendida. Comparamos cuántas veces cambia de estado cada estrategia. El ideal es 3: un encendido al comenzar la simulación (de noche), un apagado al amanecer y un encendido al anochecer.

Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.

import math


def azar(semilla):
    estado = semilla
    while True:
        estado = (1103515245 * estado + 12345) % 2**31
        yield estado / 2**31


def luz_del_dia():
    """Luz ambiente cada minuto: día de 6 a 18 h, noche de 0,3 lux, ruido de ±10 % y tres destellos."""
    g = azar(21)
    luz = []
    for minuto in range(1440):
        hora = minuto / 60
        base = 300 * math.sin(math.pi * (hora - 6) / 12) + 0.3 if 6 <= hora < 18 else 0.3
        luz.append(base * (1 + 0.2 * (next(g) - 0.5)))
    for minuto in (60, 200, 1380):               # faros de autos: 150 lux durante un minuto
        luz[minuto] += 150
    return luz


def simular(luz, aporte, estrategia, confirmar=5):
    """Cuenta los cambios de estado de la lámpara.
    A: un solo umbral de 20 lux.      B: histéresis 10/30.
    C: histéresis + confirmación.     D: C + compensación de la luz propia."""
    encendida, cambios, cuenta = False, 0, 0
    for ambiente in luz:
        medida = ambiente + (aporte if encendida else 0)          # el sensor ve la lámpara
        estimada = max(0, medida - (aporte if encendida else 0)) if estrategia == "D" else medida
        if estrategia == "A":
            deseada = estimada < 20
        elif not encendida and estimada < 10:
            deseada = True
        elif encendida and estimada > 30:
            deseada = False
        else:
            deseada = encendida
        if estrategia in "AB":                                    # sin confirmación: cambia al instante
            if deseada != encendida:
                encendida, cambios = deseada, cambios + 1
        elif deseada != encendida:                                # con confirmación: debe sostenerse
            cuenta += 1
            if cuenta >= confirmar:
                encendida, cambios, cuenta = deseada, cambios + 1, 0
        else:
            cuenta = 0
    return cambios


luz = luz_del_dia()
print("aporte de la lámpara     A     B     C     D")
for aporte in (15, 25, 40):
    resultados = [simular(luz, aporte, e) for e in "ABCD"]
    print(f"{aporte:10d} lux       " + " ".join(f"{r:5d}" for r in resultados))

Resultado: con un aporte de 15 lux (menor que la banda de 20 lux), el umbral único (A) cambia 33 veces y la histéresis sola (B) 9 veces, por los tres destellos; con confirmación (C) y con compensación (D), 3 veces, el ideal. Con 25 lux, mayor que la banda, el umbral único cambia 751 veces (oscila toda la noche), B 17 y C y D, 3. Con 40 lux, incluso la confirmación (C) sufre 147 cambios y B 735: solo la compensación (D) mantiene los 3 cambios ideales. Probá cambiar confirmar a 15 y el aporte a 40 para ver cómo se comporta C.

La tabla resume el taller: cada técnica resuelve un tipo de problema y solo la compensación ataca la realimentación de fondo. El modelo ignora la dinámica del brillo (el fade) y supone que la lámpara aporta su luz de inmediato.

12 · Exploración interactiva

El simulador de la luz nocturna

El simulador ejecuta el control con pasos de un segundo. Fijá la luz del ambiente (en escala logarítmica) y el aporte de la lámpara al sensor, elegí una de las cuatro estrategias y mirá el gráfico de los últimos 120 segundos: la luz que mide el sensor y el brillo de la lámpara. Podés inyectar un destello de faros, forzar la luz con los botones y dejar que corra solo. Para aislar el efecto de la realimentación, el simulador usa un brillo fijo (el que elijas) en lugar del brillo adaptativo del programa completo, y las estrategias 1 a 3 no compensan la luz propia.

Luz nocturna: control, sensor y lámpara

Luz real del ambiente—
Luz que mide el sensor—
Luz de ambiente que estima el control—
Estado—
Brillo percibido · PWM (gamma 2,2)—
Cambios de estado de la lámpara
0

Elegí una estrategia y presioná «Un segundo» o «Ejecutar solo».

En el gráfico, la línea tenue es la luz medida por el sensor (escala logarítmica de 0,1 a 1000 lux), las líneas punteadas son los umbrales de 10 y 30 lux y la línea gruesa es el brillo de la lámpara. Una lámpara que oscila se ve como un diente de sierra.

Recorrido guiado

  1. Con 1 lux de ambiente, aporte de 25 lux, brillo del 100 % y la estrategia 3 (histéresis y confirmación), presioná «Ejecutar solo». Pasados unos 10 s se enciende de forma suave. La luz medida sube a unos 26 lux (1 del ambiente más 25 de la lámpara), que sigue por debajo de 30 lux: la lámpara se mantiene encendida.
  2. Cambiá a la estrategia 1 (umbral único de 20 lux): con la lámpara encendida, la luz medida (26 lux) supera 20 lux, se apaga, vuelve a 1 lux, se enciende… oscila. Mirá el contador de cambios y el diente de sierra del brillo.
  3. Pasá a la estrategia 2 (histéresis 10/30): con 1 lux de ambiente es estable. Subí el ambiente a unos 7 lux: encendida, la luz medida es 7 + 25 = 32 lux, mayor que 30; se apaga, y entonces 7 lux es menor que 10 y se enciende otra vez. Oscila en la zona de 5 a 10 lux. Bajá el aporte a 15 lux: 7 + 15 = 22 lux, y se estabiliza. El aporte debe ser menor que el ancho de la banda.
  4. Con aporte de 40 lux, ambiente de 1 lux y la estrategia 3, la lámpara oscila lentamente (encendida: 41 lux, tras 10 s se apaga; apagada: 1 lux, tras 10 s se enciende). Pasá a la estrategia 4 (compensación): la luz estimada del ambiente vuelve a 1 lux y la lámpara queda quieta. Solo la compensación resuelve la realimentación de fondo.
  5. Con la estrategia 4 y la lámpara encendida, inyectá un destello de faros (5 s): no pasa nada, porque el destello dura menos de 10 s. Con la estrategia 2, la lámpara se apaga de inmediato y se vuelve a encender al terminar el destello.
  6. Con la estrategia 3 y aporte 0, dejá la lámpara encendida y subí el ambiente a 20 lux: sigue encendida (está dentro de la banda). Subilo a 50 lux y esperá 10 s: se apaga. Volvé a bajarlo a 20 lux: sigue apagada hasta que baje de 10 lux.
  7. Con la estrategia 1, aporte 25 y ambiente de 1 lux, bajá el brillo al 40 %: la lámpara aporta 10 lux, la luz medida es 11 lux, menor que 20, y deja de oscilar. Atenuar la lámpara también reduce la realimentación.
  8. Probá «Forzar encendida»: la lámpara pasa al 60 % sin tener en cuenta el ambiente. «Automático» devuelve el control.
Desafío: el aporte de la lámpara

Con la estrategia 4 el control compensa exactamente el aporte que le indica el parámetro, que en el simulador coincide con la realidad. En una instalación real, el valor de A se mide y puede equivocarse. Pensá qué ocurriría si el programa supone 15 lux pero la lámpara aporta 25: la luz del ambiente estimada queda 10 lux por encima de la real cuando la lámpara está a pleno. ¿La lámpara oscilaría? Probablemente no, porque 10 lux de error caben dentro de la banda de 20 lux; pero el margen de seguridad se reduce a la mitad. La compensación no tiene que ser perfecta, solo mucho mejor que nada.

13 · Método de trabajo

Lo aprendido, para cualquier control con un sensor afectado por el actuador

  1. Escribí el comportamiento como una máquina de estados, con estados de confirmación donde una decisión deba sostenerse.
  2. Combiná histéresis y confirmación temporal: la primera contra el ruido continuo; la segunda, contra los eventos cortos.
  3. Preguntate qué ve realmente el sensor. Si el actuador lo perturba, calculá el aporte A y compará con el ancho de la banda.
  4. Atacá la realimentación en este orden: aislar físicamente, ensanchar la banda, confirmar en el tiempo y, por último, restar el efecto conocido.
  5. Mide A en la instalación y dejalo como parámetro ajustable, no como una constante fija.
  6. Pensá en la percepción: corrección gamma y resolución suficiente para brillos bajos.
  7. Suavizá las transiciones con un limitador de velocidad y guardá el valor aplicado, que es el que influye en el sensor.
  8. Decidí la acción ante una falla de modo que coincida con la acción correcta del caso más probable.

El mismo esquema se repite en el resto del curso, sobre todo en los controles de lazo cerrado (tema 42): un sensor, una decisión con banda y confirmación, un actuador suave y un análisis honesto de cómo el actuador afecta al sensor.

14 · Comprensión

Confusiones frecuentes

«Con histéresis alcanza para que no parpadee»

Solo si el aporte de la lámpara al sensor es menor que el ancho de la banda. Si es mayor, la histéresis no impide la oscilación.

«Para atenuar, basta con variar el PWM linealmente»

El ojo percibe la luz de forma aproximadamente logarítmica. Sin corrección gamma, los cambios se perciben desiguales: grandes en los brillos bajos y casi nulos en los altos.

«La confirmación temporal elimina la oscilación por realimentación»

La hace más lenta, no la elimina: la lámpara sigue encendiéndose y apagándose, solo que con un período de varios segundos.

«Compensar es restar siempre el brillo máximo»

Hay que restar el aporte correspondiente al brillo real en ese momento (A × brillo), porque la lámpara está a media potencia durante las transiciones y en penumbra.

«Un PWM de 8 bits alcanza para todo»

Con corrección gamma, un brillo del 10 % usa solo 2 niveles de 255. En los brillos bajos, que son los de una luz nocturna, se ven escalones: conviene mayor resolución.

«Si falla el sensor, lo mejor es apagar todo»

Depende del uso. En una luz nocturna, encenderse ante la duda es lo seguro. El comportamiento ante fallas debe pensarse para cada aplicación.

15 · Práctica guiada

Predecí antes de comprobar

1. Condición de estabilidad

Los umbrales son 10 y 30 lux. ¿Cuál es el aporte máximo de la lámpara al sensor para que la histéresis, sola, evite la oscilación? ¿Qué pasa con 22 lux?

Ver solución

El aporte debe ser menor que el ancho de la banda: 30 − 10 = 20 lux. Con 22 lux, cuando el ambiente baja a unos 9 lux y la lámpara se enciende, la luz medida es 9 + 22 = 31 lux, mayor que 30: se apaga; entonces mide 9 lux y vuelve a encender. Oscila mientras el ambiente esté entre 8 y 10 lux.

2. Compensación

El sensor mide 34 lux con la lámpara a un brillo de 0,6, y el aporte a pleno es 25 lux. ¿Cuánta luz de ambiente hay? ¿Y si la lámpara estuviera apagada y midiera 34?

Ver solución

Aporte actual = 25 × 0,6 = 15 lux; ambiente = 34 − 15 = 19 lux. Con la lámpara apagada no hay nada que restar: el ambiente es 34 lux, ya por encima del umbral de apagado.

3. Gamma

Se quiere un brillo percibido del 30 % con γ = 2,2 y un PWM de 8 bits. ¿Qué duty se aplica? ¿Y sin corrección?

Ver solución

Con gamma: 255 × 0,32,2 = 255 × 0,0707 ≈ 18. Sin corrección: 255 × 0,3 = 77. Sin la corrección, la lámpara luciría mucho más brillante que el 30 % deseado.

4. Duración del fade

El brillo avanza 0,01 cada 20 ms. ¿Cuánto tarda en ir de 0 a 1? ¿Y si se quisiera una transición de 4 segundos con la misma tarea de 20 ms?

Ver solución

De 0 a 1 son 100 pasos × 20 ms = 2 s. Para 4 s hacen falta 200 pasos de 20 ms, es decir, un paso de 0,005.

5. Confirmación frente a destello

La lámpara está encendida (estado NOCHE) y pasa un auto cuyos faros dan 150 lux durante 6 s. El tiempo de confirmación es 10 s. ¿Qué hace el control? ¿Y si los faros duraran 12 s?

Ver solución

Con 6 s: la luz sube a más de 30 lux, el estado pasa a CONFIRMANDO DÍA, y cuando los faros se van (antes de los 10 s) la luz vuelve a 30 lux o menos y regresa a NOCHE: la lámpara no se apaga. Con 12 s: se cumple la confirmación y pasa a DÍA, se apaga; al terminar el destello, la luz baja de 10 lux, se confirma otros 10 s y se vuelve a encender. Un destello mayor que el tiempo de confirmación sí se atiende.

6. Falla del sensor

El cable del LDR se corta y las cuentas quedan en 0. ¿Qué hace la luz nocturna? ¿Y si el LDR se pone en cortocircuito con Vcc?

Ver solución

Cuentas 0: se interpreta como oscuridad y la lámpara se enciende (el fallo seguro). En cortocircuito: 1023 cuentas, «mucha luz», la lámpara se apaga permanentemente, una falla peligrosa por silenciosa. Se detecta con un control de coherencia: una luz que no varía nunca en 24 h es sospechosa.

16 · Síntesis

Ideas para recordar

  • Un control automático de luz es una máquina de estados con estados de confirmación: una decisión debe sostenerse antes de actuar.
  • La histéresis (10 y 30 lux) combate el ruido continuo; la confirmación temporal, los eventos cortos como sombras y destellos.
  • La luz medida es la del ambiente más A × brillo: la lámpara perturba a su propio sensor.
  • La histéresis sola evita la oscilación solo si A es menor que el ancho de la banda (aquí 20 lux).
  • Los remedios son aislar, ensanchar la banda, confirmar y, sobre todo, restar el efecto conocido (compensación).
  • El brillo percibido es aproximadamente logarítmico: el PWM debe llevar una corrección gamma (duty = brillo2,2).
  • Con la corrección gamma los brillos bajos usan pocos niveles; conviene un PWM de mayor resolución.
  • Las transiciones se suavizan con un limitador de velocidad; la compensación usa el brillo realmente aplicado.
  • El comportamiento ante fallas debe coincidir con la acción segura del caso más probable.

¿Listo para el bloque 5?

Antes de avanzar, calculá el aporte máximo de la lámpara que tolera una banda de 10 a 25 lux, explicá por qué un PWM lineal da un brillo mal percibido y describí qué hace la compensación con A × brillo. Si podés justificar las tres respuestas, ya sabés diseñar un control con realimentación óptica.

En el próximo bloque pasamos a la distancia y el movimiento, empezando por los sensores ultrasónicos (HC-SR04): tiempo de vuelo, velocidad del sonido y zonas ciegas.