Caso práctico: luz nocturna solar con Arduino UNO

Caso práctico: luz nocturna solar con Arduino UNO — hero

Objetivo y caso de uso

Qué construirás: Construirás un controlador automático de luz nocturna solar que activa un arreglo de LED de alta potencia al anochecer. Utiliza un LDR para la detección de luz ambiental y un divisor de voltaje con resistencias para monitorear activamente y proteger una batería de 12V contra descargas profundas.

Por qué es importante / Casos de uso

  • Protección de la batería: Monitorea activamente el estado de la batería y corta la carga cuando el voltaje cae por debajo de los umbrales seguros (p. ej., < 10.5V), previniendo daños permanentes a las celdas de plomo-ácido o de iones de litio.
  • Eficiencia energética: Utiliza un LDR con histéresis por software para asegurar que la iluminación se active solo cuando sea realmente necesario, evitando el parpadeo rápido y el desperdicio de energía durante las horas del crepúsculo.
  • Automatización fuera de la red (Off-Grid): Forma la lógica autónoma central para la iluminación remota de paradas de autobús, cobertizos de jardín o luces de seguridad para senderos que operan de manera totalmente independiente de la red eléctrica.
  • Control de potencia escalable: Utiliza un MOSFET de canal N de nivel lógico para demostrar cómo un microcontrolador de bajo consumo de 5V puede conmutar de manera segura grandes cargas de CC (hasta 5A/60W).

Resultado esperado

  • Lectura precisa de voltaje: El Arduino escalará y medirá correctamente el voltaje de la batería de 12V a través del circuito divisor con un margen de error < 0.1V.
  • Actuación confiable: Conmuta de forma fluida la carga del LED de alta potencia con una latencia < 10ms una vez que el LDR detecta el umbral de oscuridad objetivo.
  • Preservación de la batería: Desconecta con éxito el arreglo de LED automáticamente cuando la capacidad de la batería cae al límite crítico de seguridad de 10.5V.

Audiencia: Desarrolladores de IoT, creadores de hardware y entusiastas de los sistemas fuera de la red; Nivel: Intermedio

Arquitectura/flujo: LDR & Divisor de voltaje (Sensores) → ADC de Arduino (Lógica/Procesamiento) → MOSFET de canal N (Interruptor) → Arreglo de LED de 12V (Salida)

Nota educativa de validación

Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.

Evidencia de validación publicada

  • Resultado automático: PASS.
  • Estructura parseada: 3 apartados, 2 tablas y 2 bloques de código detectados antes de publicar.
  • Código comprobado: 1 Python/py_compile, 1 Arduino/arduino-cli compile.
  • Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
  • Hallazgos del informe: sin hallazgos bloqueantes.

Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.

Nota educativa de seguridad

Este proyecto es un prototipo educativo de bajo voltaje, no un producto certificado. Antes de encender la configuración, verifique el cableado de su Arduino UNO R3, evite cortocircuitar 5 V, GND o los pines digitales, desconecte la alimentación antes de cambiar las conexiones y use módulos de interfaz adecuados para relés, motores o cargas externas.

Diagrama de bloques conceptual

Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.

Arquitectura funcional

LDR & Divisor de voltaje (Sensores)

ADC de Arduino (Lógica/Procesamiento)

MOSFET de canal N (Interruptor)

Arreglo de LED de 12V (Salida)

Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.

Ruta de validación

Sketch

arduino-cli compile

Upload

Prueba funcional

Resumen conceptual de las herramientas usadas para comprobar el material publicado.

Requisitos previos

Para completar con éxito este tutorial, debe tener una comprensión básica de la Ley de Ohm (específicamente los cálculos del divisor de voltaje), programación fundamental en C++ para Arduino (variables, declaraciones if/else, millis() para la temporización) y familiaridad con el funcionamiento de una interfaz de línea de comandos. Debe tener instalado y configurado Arduino CLI en su computadora host.

Materiales

Necesitará los siguientes componentes exactos para construir este prototipo:

  • Microcontrolador: Arduino UNO R3 (ATmega328P)
  • Sensor de luz: 1x LDR estándar (Fotorresistencia)
  • MOSFET: 1x IRLZ44N (MOSFET de potencia de canal N de nivel lógico)
  • Resistencias (1/4 de vatio):
    • 1x 30kΩ (Divisor de batería R1)
    • 2x 10kΩ (Divisor de batería R2, LDR pull-down)
    • 1x 10kΩ (Compuerta del MOSFET pull-down)
    • 1x 220Ω (Limitador de corriente de la compuerta del MOSFET)
  • Carga: 1x Arreglo de LED de 12V o tira de LED de 12V (Máximo 2 Amperios para pruebas en protoboard)
  • Fuente de alimentación: 1x Batería de 12V (p. ej., paquete de iones de litio 3S o batería de plomo-ácido sellada de 12V)
  • Prototipado: 1x Protoboard, cables puente macho a macho variados

Configuración/Conexión

Debido a que el Arduino UNO R3 funciona a 5V, no puede medir directamente una batería de 12V ni accionar una carga de 12V. Debemos utilizar circuitos de interfaz específicos.

1. El divisor de voltaje de la batería
El ADC de Arduino solo puede medir hasta 5V. Para medir una batería de 12V (que puede alcanzar hasta 14.4V durante la carga), usamos un divisor de voltaje. Conecte la resistencia de 30kΩ (R1) al terminal positivo de la batería (BAT+). Conecte el otro extremo de la resistencia de 30kΩ al pin A0 de Arduino. Conecte la resistencia de 10kΩ (R2) desde el pin A0 de Arduino a Tierra (GND).
Fórmula: Vout = Vin * (R2 / (R1 + R2)). A una entrada de 20V, A0 ve exactamente 5V. El factor de escala en el código será 4.0.

2. El divisor del LDR
Conecte una pata del LDR al pin de 5V de Arduino. Conecte la otra pata del LDR al pin A1 de Arduino. Conecte una resistencia de 10kΩ desde el pin A1 de Arduino a Tierra (GND).
Comportamiento: En luz brillante, la resistencia del LDR disminuye, acercando A1 a 5V. En la oscuridad, la resistencia del LDR aumenta y la resistencia de 10kΩ acerca A1 a 0V.

3. El controlador LED MOSFET
Sostenga el MOSFET IRLZ44N de modo que la pestaña de metal quede en la parte posterior y el texto lo mire a usted. Los pines de izquierda a derecha son Compuerta (Gate) (1), Drenador (Drain) (2) y Surtidor (Source) (3).
* Conecte el Pin 9 de Arduino a una resistencia de 220Ω, luego a la Compuerta del MOSFET.
* Conecte una resistencia de 10kΩ desde la Compuerta del MOSFET directamente a Tierra (esto evita que el LED parpadee mientras el Arduino arranca).
* Conecte el Surtidor del MOSFET a Tierra.
* Conecte el Drenador del MOSFET al cable negativo (Cátodo) de su arreglo de LED de 12V.
* Conecte el cable positivo (Ánodo) de su arreglo de LED de 12V directamente al terminal positivo de la batería (BAT+).

4. Tierra común
Asegúrese de que el GND del Arduino, el terminal negativo de la batería, el Surtidor del MOSFET y todas las conexiones a tierra del divisor estén unidas en el riel negativo de la protoboard.

Tabla de asignación de pines

Pin de Arduino UNO R3Conexión del componenteFunción
A0Unión de resistencias de 30kΩ y 10kΩDetección de voltaje de la batería
A1Unión del LDR y resistencia de 10kΩDetección de luz ambiental
Pin 9 (PWM)Resistencia de 220Ω → Compuerta del MOSFETBrillo / Conmutación del LED
5VPata superior del LDRVoltaje de referencia para el LDR
GNDRiel de tierra comúnRetorno del sistema / Referencia
VINNo conectado en esta pruebaAlimentar Arduino vía USB para pruebas

Código validado

La siguiente sección contiene dos archivos. El primero es el firmware en C++ para el Arduino UNO R3. El segundo es un script de Python opcional que se ejecuta en su computadora para registrar los datos en serie del Arduino en un archivo CSV, lo cual es muy útil para validar la curva de descarga de la batería y los puntos de conmutación.

Firmware de Arduino: solar_night_light.ino

Cree una carpeta llamada solar_night_light y coloque este código dentro de un archivo llamado solar_night_light.ino.

Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.

/*
 * Solar Night Light Controller
 * Target: Arduino UNO R3 (ATmega328P)
 * Purpose: Controls a 12V LED via MOSFET based on LDR light levels,
 *          incorporating Low Voltage Disconnect (LVD) for battery protection.
 */

// --- Hardware Pins ---
const int PIN_BATTERY_SENSE = A0;
const int PIN_LIGHT_SENSE   = A1;
const int PIN_LED_DRIVE     = 9;

// --- Calibration & Thresholds ---
// Voltage Divider: R1 = 30k, R2 = 10k. Ratio = (30+10)/10 = 4.0
const float VOLTAGE_DIVIDER_RATIO = 4.0;
const float ADC_REFERENCE_VOLTAGE = 5.0;
const float ADC_MAX_VALUE = 1023.0;

// Battery Thresholds (12V Lead-Acid / 3S Li-ion example)
const float BATT_LVD_DISCONNECT = 10.5; // Turn off below 10.5V
const float BATT_LVD_RECONNECT  = 11.5; // Require 11.5V to turn back on

// Light Thresholds (0-1023). Higher value = brighter ambient light.
const int LIGHT_THRESHOLD_DARK  = 300;  // Below this is considered night
const int LIGHT_THRESHOLD_LIGHT = 450;  // Above this is considered day

// --- System State ---
enum SystemState {
  STATE_DAYTIME,
  STATE_NIGHT_ON,
  STATE_LOW_BATTERY
};

SystemState currentState = STATE_DAYTIME;

// --- Timing ---
unsigned long lastLogTime = 0;
const unsigned long LOG_INTERVAL_MS = 1000;

void setup() {
  Serial.begin(115200);

  pinMode(PIN_BATTERY_SENSE, INPUT);
  pinMode(PIN_LIGHT_SENSE, INPUT);

  // Initialize MOSFET drive pin
  pinMode(PIN_LED_DRIVE, OUTPUT);
  analogWrite(PIN_LED_DRIVE, 0); // Ensure LED is OFF at boot

  Serial.println("Solar Night Light Controller Initialized.");
  Serial.println("Timestamp_ms,Battery_V,Light_ADC,State,PWM_Out");
}

void loop() {
  // 1. Read Sensors
  int rawBatteryADC = analogRead(PIN_BATTERY_SENSE);
  int rawLightADC = analogRead(PIN_LIGHT_SENSE);

  // 2. Calculate Real Voltage
  float pinVoltage = (rawBatteryADC / ADC_MAX_VALUE) * ADC_REFERENCE_VOLTAGE;
  float batteryVoltage = pinVoltage * VOLTAGE_DIVIDER_RATIO;

  // 3. State Machine Logic
  switch (currentState) {

    case STATE_DAYTIME:
      // Transition to NIGHT if it gets dark AND battery is healthy
      if (rawLightADC < LIGHT_THRESHOLD_DARK) {
        if (batteryVoltage > BATT_LVD_RECONNECT) {
          currentState = STATE_NIGHT_ON;
        } else {
          currentState = STATE_LOW_BATTERY; // Too dark, but battery is dead
        }
// ...

🔒 Este contenido es premium. Con la suscripción mensual (7 días gratis) podrás desbloquear el material didáctico completo y el pack PDF listo para imprimir.🔓 Desbloquéalo — 7 días gratis
/*
 * Solar Night Light Controller
 * Target: Arduino UNO R3 (ATmega328P)
 * Purpose: Controls a 12V LED via MOSFET based on LDR light levels,
 *          incorporating Low Voltage Disconnect (LVD) for battery protection.
 */

// --- Hardware Pins ---
const int PIN_BATTERY_SENSE = A0;
const int PIN_LIGHT_SENSE   = A1;
const int PIN_LED_DRIVE     = 9;

// --- Calibration & Thresholds ---
// Voltage Divider: R1 = 30k, R2 = 10k. Ratio = (30+10)/10 = 4.0
const float VOLTAGE_DIVIDER_RATIO = 4.0;
const float ADC_REFERENCE_VOLTAGE = 5.0;
const float ADC_MAX_VALUE = 1023.0;

// Battery Thresholds (12V Lead-Acid / 3S Li-ion example)
const float BATT_LVD_DISCONNECT = 10.5; // Turn off below 10.5V
const float BATT_LVD_RECONNECT  = 11.5; // Require 11.5V to turn back on

// Light Thresholds (0-1023). Higher value = brighter ambient light.
const int LIGHT_THRESHOLD_DARK  = 300;  // Below this is considered night
const int LIGHT_THRESHOLD_LIGHT = 450;  // Above this is considered day

// --- System State ---
enum SystemState {
  STATE_DAYTIME,
  STATE_NIGHT_ON,
  STATE_LOW_BATTERY
};

SystemState currentState = STATE_DAYTIME;

// --- Timing ---
unsigned long lastLogTime = 0;
const unsigned long LOG_INTERVAL_MS = 1000;

void setup() {
  Serial.begin(115200);

  pinMode(PIN_BATTERY_SENSE, INPUT);
  pinMode(PIN_LIGHT_SENSE, INPUT);

  // Initialize MOSFET drive pin
  pinMode(PIN_LED_DRIVE, OUTPUT);
  analogWrite(PIN_LED_DRIVE, 0); // Ensure LED is OFF at boot

  Serial.println("Solar Night Light Controller Initialized.");
  Serial.println("Timestamp_ms,Battery_V,Light_ADC,State,PWM_Out");
}

void loop() {
  // 1. Read Sensors
  int rawBatteryADC = analogRead(PIN_BATTERY_SENSE);
  int rawLightADC = analogRead(PIN_LIGHT_SENSE);

  // 2. Calculate Real Voltage
  float pinVoltage = (rawBatteryADC / ADC_MAX_VALUE) * ADC_REFERENCE_VOLTAGE;
  float batteryVoltage = pinVoltage * VOLTAGE_DIVIDER_RATIO;

  // 3. State Machine Logic
  switch (currentState) {

    case STATE_DAYTIME:
      // Transition to NIGHT if it gets dark AND battery is healthy
      if (rawLightADC < LIGHT_THRESHOLD_DARK) {
        if (batteryVoltage > BATT_LVD_RECONNECT) {
          currentState = STATE_NIGHT_ON;
        } else {
          currentState = STATE_LOW_BATTERY; // Too dark, but battery is dead
        }
      }
      // Transition to LOW_BATTERY if voltage drops even during day
      if (batteryVoltage < BATT_LVD_DISCONNECT) {
        currentState = STATE_LOW_BATTERY;
      }
      break;

    case STATE_NIGHT_ON:
      // Transition back to DAYTIME if light returns
      if (rawLightADC > LIGHT_THRESHOLD_LIGHT) {
        currentState = STATE_DAYTIME;
      }
      // Transition to LOW_BATTERY if voltage drops below safe limit
      if (batteryVoltage < BATT_LVD_DISCONNECT) {
        currentState = STATE_LOW_BATTERY;
      }
      break;

    case STATE_LOW_BATTERY:
      // Only recover from Low Battery if voltage rises above reconnect threshold
      if (batteryVoltage > BATT_LVD_RECONNECT) {
        if (rawLightADC > LIGHT_THRESHOLD_LIGHT) {
          currentState = STATE_DAYTIME;
        } else {
          currentState = STATE_NIGHT_ON;
        }
      }
      break;
  }

  // 4. Actuate Outputs
  int pwmValue = 0;
  if (currentState == STATE_NIGHT_ON) {
    pwmValue = 255; // 100% duty cycle (Full brightness)
  }
  analogWrite(PIN_LED_DRIVE, pwmValue);

  // 5. Telemetry Logging (Non-blocking)
  unsigned long currentMillis = millis();
  if (currentMillis - lastLogTime >= LOG_INTERVAL_MS) {
    lastLogTime = currentMillis;

    Serial.print(currentMillis);
    Serial.print(",");
    Serial.print(batteryVoltage, 2);
    Serial.print(",");
    Serial.print(rawLightADC);
    Serial.print(",");

    if (currentState == STATE_DAYTIME) Serial.print("DAYTIME");
    else if (currentState == STATE_NIGHT_ON) Serial.print("NIGHT_ON");
    else if (currentState == STATE_LOW_BATTERY) Serial.print("LOW_BATT");

    Serial.print(",");
    Serial.println(pwmValue);
  }
}

Script registrador de puerto serie: serial_logger.py

Este script de Python lee la salida en serie en formato CSV del Arduino y la guarda en un archivo. Guarde esto en el mismo directorio que la carpeta de su proyecto de Arduino.

#!/usr/bin/env python3
"""
Serial Logger for Solar Night Light Controller
Reads CSV telemetry from Arduino and writes to 'telemetry.csv'
Requires: pip install pyserial
"""

import serial
import time
import argparse

def main():
    parser = argparse.ArgumentParser(description="Log Arduino Serial Data to CSV")
    parser.add_add_argument("--port", required=True, help="Serial port (e.g., COM3 or /dev/ttyACM0)")
    parser.add_argument("--baud", type=int, default=115200, help="Baud rate")
    args = parser.parse_args()

    try:
        ser = serial.Serial(args.port, args.baud, timeout=2)
        print(f"Connected to {args.port} at {args.baud} baud.")

        with open("telemetry.csv", "w") as f:
            while True:
                if ser.in_waiting > 0:
                    line = ser.readline().decode('utf-8').strip()
                    print(line)
                    if "Initialized" not in line:
                        f.write(line + "\n")
                        f.flush()

    except serial.SerialException as e:
        print(f"Error opening serial port: {e}")
    except KeyboardInterrupt:
        print("\nLogging stopped by user.")
    finally:
        if 'ser' in locals() and ser.is_open:
            ser.close()

if __name__ == "__main__":
    main()

Comandos de compilación/flasheo/ejecución

Use Arduino CLI para compilar y flashear el firmware en su Arduino UNO R3. Asegúrese de que su Arduino esté conectado a través de USB.

Tabla de comandos

ComandoPropósito
arduino-cli core update-indexActualiza la lista de núcleos de Arduino disponibles
arduino-cli core install arduino:avrInstala el núcleo requerido para el UNO R3
arduino-cli compile --fqbn arduino:avr:unoCompila el sketch solar_night_light.ino
arduino-cli upload --fqbn arduino:avr:uno --port <PORT>Flashea el binario compilado en la placa

Flujo de trabajo

  1. Obra su terminal y navegue hasta el directorio que contiene la carpeta solar_night_light.
  2. Asegúrese de que su núcleo esté actualizado:
    arduino-cli core update-index
    arduino-cli core install arduino:avr
  3. Compile el firmware:
    arduino-cli compile --fqbn arduino:avr:uno solar_night_light
  4. Identifique su puerto (p. ej., COM3 en Windows o /dev/ttyACM0 en Linux).
  5. Suba el firmware:
    arduino-cli upload --fqbn arduino:avr:uno --port /dev/ttyACM0 solar_night_light
  6. Inicie el registrador de Python para monitorear la salida (reemplace el puerto con su puerto real):
    python3 serial_logger.py --port /dev/ttyACM0

Validación paso a paso

Realice estas comprobaciones para validar el funcionamiento lógico y eléctrico del controlador. Mantenga el registrador de Python en ejecución para poder observar el estado del sistema.

  1. Comprobación de calibración de voltaje del ADC
    • Acción: Conecte una fuente de voltaje conocida (p. ej., una batería de 12V o fuente de alimentación de banco) a la entrada del divisor de la batería. Mida el voltaje real de la batería con un multímetro digital (DMM).
    • Observación esperada: La columna Battery_V en la salida en serie debe coincidir con la lectura del DMM con una diferencia de ±0.2V.
    • Condición de aprobación: El Arduino escala con precisión la lectura analógica al voltaje del mundo real.
  2. Verificación del estado diurno
    • Acción: Ilumine el LDR directamente con una linterna o luz de habitación brillante. Asegúrese de que el voltaje de la batería esté por encima de 11.5V.
    • Observación esperada: La salida en serie reporta DAYTIME, PWM_Out es 0. El arreglo de LED de 12V permanece completamente apagado.
    • Condición de aprobación: El sistema identifica correctamente el día y desactiva la carga.
  3. Transición al anochecer e histéresis
    • Acción: Cubra lentamente el LDR con su mano para simular el anochecer.
    • Observación esperada: Light_ADC disminuye. Una vez que cae por debajo de 300, el estado cambia a NIGHT_ON y PWM_Out salta a 255. El arreglo de LED se enciende. Descubrir ligeramente el LDR (el ADC sube a 350) no apaga el LED.
    • Condición de aprobación: El LED se enciende en la oscuridad y la banda muerta (300 a 450) evita que el LED parpadee en el umbral exacto.
  4. Activación de desconexión por bajo voltaje (LVD)
    • Acción: Mientras está en el estado NIGHT_ON, simule una batería agotándose reduciendo el voltaje de entrada al divisor por debajo de 10.5V (usando una fuente de alimentación variable o cambiando temporalmente la resistencia de 30kΩ por una de mayor valor).
    • Observación esperada: El estado cambia inmediatamente a LOW_BATT. PWM_Out cae a 0. El arreglo de LED se apaga.
    • Condición de aprobación: El controlador protege con éxito la batería al cortar la carga.
  5. Bloqueo de reconexión del LVD
    • Acción: Aumente el voltaje de entrada ligeramente a 11.0V.
    • Observación esperada: El sistema permanece

Encuentra este producto y/o libros sobre este tema en Amazon

Ir a Amazon

Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.

Quiz rápido

Pregunta 1: ¿Cuál es el objetivo principal del proyecto descrito en el artículo?




Pregunta 2: ¿Qué componente se utiliza para la detección de luz ambiental en el proyecto?




Pregunta 3: ¿Qué método se utiliza para monitorear activamente y proteger la batería de 12V?




Pregunta 4: ¿Por debajo de qué voltaje aproximado el sistema corta la carga para proteger la batería?




Pregunta 5: ¿Qué tipos de baterías se mencionan que son protegidas contra descargas profundas?




Pregunta 6: ¿Qué técnica de software se utiliza junto con el LDR para evitar el parpadeo rápido de la luz durante el crepúsculo?




Pregunta 7: ¿Qué tipo de iluminación activa el controlador al anochecer?




Pregunta 8: ¿Cuál es un caso de uso mencionado para este sistema fuera de la red (Off-Grid)?




Pregunta 9: ¿Cómo opera el sistema en relación con la red eléctrica?




Pregunta 10: ¿Qué problema principal previene el corte de carga cuando el voltaje de la batería cae?




Carlos Núñez Zorrilla
Carlos Núñez Zorrilla
Electronics & Computer Engineer

Ingeniero Superior en Electrónica de Telecomunicaciones e Ingeniero en Informática (titulaciones oficiales en España).

Sígueme:
Scroll al inicio