Un seguidor solar de doble eje es un sistema que orienta una superficie hacia la zona de mayor iluminación mediante movimientos de azimut y elevación.
La orientación influye en la energía que recibe un panel, aunque la mejora real depende de la ubicación, la época del año, las sombras y el consumo del propio mecanismo. Este prototipo sirve para entender el control diferencial; no pretende optimizar una instalación fotovoltaica real.
Este proyecto es un ejemplo perfecto de un Sistema de Control en Bucle Cerrado. El Arduino no sabe dónde está el sol por GPS ni por hora; lo “busca” activamente comparando la luz que recibe desde diferentes direcciones y corrigiendo su posición hasta encontrar el máximo brillo.
Este principio no solo sirve para paneles solares. Es la misma lógica que usan los radares de seguimiento o las antenas parabólicas auto-orientables.
El comparador diferencial
¿Cómo sabe el Arduino hacia dónde moverse? La clave está en no usar un solo sensor, sino cuatro, dispuestos en cruz y separados por tabiques opacos (una cruz de cartón o plástico).
La lógica es puramente comparativa:
- Si los sensores de la Izquierda reciben más luz que los de la Derecha, significa que el sol está a la izquierda. Acción: Girar el motor horizontal hacia la izquierda.
- Si los sensores de Arriba reciben más luz que los de Abajo, el sol está más alto. Acción: Subir el motor vertical.
El objetivo del sistema (su estado de equilibrio) es que la diferencia sea cero, es decir, que los cuatro sensores reciban la misma cantidad de luz.
Componentes
- [1x|blue] Arduino Uno | El cerebro del proyecto
- [1x|green] Servomotor (SG90 o MG90S) | Eje X (Azimut/Horizontal)
- [1x|green] Servomotor (SG90 o MG90S) | Eje Y (Elevación/Vertical)
- [4x|orange] Fotorresistencias (LDR) | Detectan luz en cada cuadrante
- [4x|gray] Resistencia de 10kΩ | Divisores de tensión para LDRs
- [Varios|gray] Estructura de soporte | Impresión 3D, cartón o metacrilato
Necesitaremos una estructura móvil. Podéis imprimirla en 3D (hay miles de “Pan/Tilt bracket” en Thingiverse) o hacerla con cartón y pegamento caliente.
Esquema de conexión
Sensores y divisores de tensión
Las LDR varían su resistencia con la luz. Arduino solo mide voltaje. Por tanto, necesitamos crear un divisor de tensión para cada LDR.
[ { “from”: “LDR Arriba Izq (TL)”, “to”: “Pin A0”, “color”: “orange”, “note”: “Con pull-down 10kΩ a GND” }, { “from”: “LDR Arriba Der (TR)”, “to”: “Pin A1”, “color”: “orange”, “note”: “Con pull-down 10kΩ a GND” }, { “from”: “LDR Abajo Izq (BL)”, “to”: “Pin A2”, “color”: “orange”, “note”: “Con pull-down 10kΩ a GND” }, { “from”: “LDR Abajo Der (BR)”, “to”: “Pin A3”, “color”: “orange”, “note”: “Con pull-down 10kΩ a GND” }, { “from”: “LDR VCC”, “to”: “5V Arduino”, “color”: “red” }, { “from”: “Resistencias 10kΩ”, “to”: “GND Arduino”, “color”: “black” } ]
- Un extremo de la LDR a 5V.
- El otro extremo de la LDR al Pin Analógico y también a una resistencia de 10kΩ.
- El otro extremo de la resistencia a GND.
Servos
La señal de cada servo sale de Arduino, pero la alimentación conviene llevarla por separado.
[ { “from”: “Servo Horizontal señal”, “to”: “Pin 9”, “color”: “green” }, { “from”: “Servo Vertical señal”, “to”: “Pin 10”, “color”: “green” }, { “from”: “Servos VCC”, “to”: “Fuente externa regulada”, “color”: “red” }, { “from”: “Servos GND”, “to”: “GND fuente + GND Arduino”, “color”: “black” } ]
Alimenta los servos con una fuente externa regulada para su tensión nominal y une las tierras (GND). Dos servos moviéndose a la vez pueden reiniciar el Arduino si intentas alimentarlos solo desde el USB.
El código
El código implementa una lógica de búsqueda continua. La parte crítica aquí es la Tolerancia (o banda muerta). No queremos que el robot tiemble (jitter) por diferencias minúsculas de luz o ruido eléctrico. Solo se moverá si la diferencia es significativa.
#include <Servo.h>
// --- Configuración de Hardware ---
Servo servoHorizontal;
int servoh = 90; // Posición inicial horizontal
int servohLimitHigh = 180;
int servohLimitLow = 0;
Servo servoVertical;
int servov = 90; // Posición inicial vertical
int servovLimitHigh = 180;
int servovLimitLow = 0;
// Pines de las LDR
const int ldrTL = A0; // Top Left
const int ldrTR = A1; // Top Right
const int ldrBL = A2; // Bottom Left
const int ldrBR = A3; // Bottom Right
// --- Configuración de Control ---
int tolerancia = 50; // Sensibilidad: Ajustar según la luz ambiente
int tiempoRespuesta = 10; // Delay para suavizar movimiento
void setup() {
Serial.begin(9600);
servoHorizontal.attach(9);
servoVertical.attach(10);
// Mover a posición de inicio
servoHorizontal.write(servoh);
servoVertical.write(servov);
delay(2000); // Dar tiempo a posicionarse
}
void loop() {
// 1. Lectura de Sensores
int lt = analogRead(ldrTL); // Top Left
int rt = analogRead(ldrTR); // Top Right
int ld = analogRead(ldrBL); // Down Left
int rd = analogRead(ldrBR); // Down Right
// 2. Cálculo de Promedios
int avt = (lt + rt) / 2; // Promedio Arriba (Average Top)
int avd = (ld + rd) / 2; // Promedio Abajo (Average Down)
int avl = (lt + ld) / 2; // Promedio Izquierda
int avr = (rt + rd) / 2; // Promedio Derecha
// 3. Lógica Vertical (Elevación)
int dvert = avt - avd; // Diferencia arriba - abajo
// Solo movemos si la diferencia supera la tolerancia (Banda muerta)
if (abs(dvert) > tolerancia) {
if (avt > avd) {
servov++; // Si hay más luz arriba, subimos
} else {
servov--; // Si hay más luz abajo, bajamos
}
// Limitamos el rango físico del servo para no romper el mecanismo
servov = constrain(servov, servovLimitLow, servovLimitHigh);
servoVertical.write(servov);
}
// 4. Lógica Horizontal (Azimut)
int dhoriz = avl - avr; // Diferencia izquierda - derecha
if (abs(dhoriz) > tolerancia) {
if (avl > avr) {
servoh--; // Según el montaje del servo, puede ser ++ o --
} else {
servoh++;
}
servoh = constrain(servoh, servohLimitLow, servohLimitHigh);
servoHorizontal.write(servoh);
}
delay(tiempoRespuesta);
}
Ajuste y calibración
Cuando carguéis este código, es probable que ocurra una de estas cosas:
- El robot huye de la luz en vez de buscarla: Significa que la lógica del servo está invertida. Cambia el
servoh++porservoh--(o viceversa) en el código. - El robot tiembla constantemente: La
toleranciaes demasiado baja. Auméntala de 50 a 100. - Se mueve muy lento: Reduce el
tiempoRespuesta.
Cuándo aporta un segundo eje
Un seguidor solar de un solo eje (solo Este-Oeste) puede captar mucha energía extra, pero ignora la variación estacional de la altura del sol (el sol está más alto en verano que en invierno).
Con un sistema de doble eje, garantizamos que los rayos inciden a 90º perfectos tanto a lo largo del día como a lo largo del año. En instalaciones reales, esto puede suponer un incremento de eficiencia de hasta un 40% frente a paneles fijos.
Siguientes pasos
Para convertir este prototipo de juguete en algo serio:
- Limitar el consumo: El sol se mueve despacio. Podemos aplicar un modo de bajo consumo compatible con la placa y despertar periódicamente para corregir la posición.
- Sensores de final de carrera: Para evitar que el robot gire 360º y rompa los cables.
- Modo “Noche”: Detectar cuando la luz total es muy baja (noche) y rebobinar los servos hacia el Este automáticamente para esperar el amanecer del día siguiente.