La Solarigrafía es un concepto y una práctica fotográfica basadas en la observación del recorrido del sol en el cielo (diferente en los distintos lugares de la tierra) y su efecto en el paisaje, captados mediante un procedimiento específico que combina fotografía estenopeica, tratamiento digital y difusión por internet. Se suele utilizar papel fotográfico sin revelado, una cámara estenopeica y un escáner para crear imágenes que recogen el recorrido diario del sol por el cielo mediante tiempos de exposición muy largos, entre varias horas y muchos meses. Tiene desde su inicio vocación de difusión, colaboración y compartición entre aficionados en todo el mundo gracias principalmente a los cauces de Internet.
Para este proyecto, el objetivo es automatizar la captura del Analema solar, que es la curva que describe la posición del Sol en el cielo si todos los días del año se lo observa a la misma hora del día (huso horario) y desde el mismo lugar de observación. El analema forma una curva que suele ser, aproximadamente, una forma de ocho (8) o lemniscata.
La captura del analema de forma manual requiere tomar una fotografía todos los días del año a la misma hora, lo que muchas veces es inviable porque no siempre se puede estar presente para hacerlo, por tanto una cámara automatizada que tome las imágenes siempre a la misma hora es una herramienta muy útil para este tipo de práctica.
Durante el proyecto se ha realizado una cámara controlada por arduino, usando un RTC (real time clock) para mantener la sincronización horaria, y con un sistema de batería y panel solar para que el sistema sea totalmente autónomo sin depender de fuentes de alimentación externas, lo que posibilita instalarlo en lugares de difícil acceso pero adecuados para capturar el sol sin obstrucciones. El obturador de la cámara (de tipo pinhole) es controlado por un servo de 9gr que mueve una pieza que tapa el orificio del pinhole.
Paso a paso
- Arduino Nano
- Módulo RTC DS3231
- SparkFun SunnyBuddy
- Panel solar
- Batería Lipo 1S 2000 mAh
- Servo 9gr
- LED 5mm
- Resistencia 220 Ohm
- Cable de conexión.
#include <DS3231.h> #include <Wire.h> #include <Servo.h> #include <EEPROM.h> #include <LowPower.h> // Soft reset #define RESTART asm("jmp 0x0000") #define PIN_ACT_OBTURADOR 3 // Arduino D3 #define PIN_CONFIGURACION_I 6 // D6 #define PIN_CONFIGURACION_O 7 // D7 #define EEPROM_NUM_ESTADOS 0 #define EEPROM_ESTADO_ACT 1 #define EEPROM_TIMEDATA_START 2 #define ANGULO_APERTURA 130 #define ANGULO_CIERRE 5 DS3231 rtc; Servo obturador; byte anyo; byte mes; byte dia; byte dia_semana; byte hora; byte minuto; bool h12, pm, siglo; byte ADay, AHour, AMinute, ASecond, ABits; bool ADy, A12h, Apm; struct rst_info* reset_info; byte estado_actual; byte num_estados; int init_mode; void setup() { delay(1); // Iniciamos el I2C Wire.begin(); // Aseguramos que estamos en modo de 24h rtc.setClockMode(false); siglo = false; // LED pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); // IO pinMode(PIN_CONFIGURACION_I, INPUT_PULLUP); pinMode(PIN_CONFIGURACION_O, OUTPUT); // set to LOW digitalWrite(PIN_CONFIGURACION_O, LOW); // Y el puerto serie Serial.begin(115200); Serial.println(); Serial.println("Iniciando..."); // Vemos si tenemos que reiniciar, entrar en la configuración o continuar. init_mode = digitalRead(PIN_CONFIGURACION_I); Serial.print("Configuración Leida: "); Serial.println(init_mode); if (!init_mode) { // configuración? delay(3000); // esperamos 3 segundos if (!digitalRead(PIN_CONFIGURACION_I)) { // configuración por puerto serie digitalWrite(LED_BUILTIN, HIGH); // LED continuo Serial.println("Esperando configuración..."); char serial_buffer[255]; char c = 0; int counter = 0; while ((c != 255) && (counter < 100)) { if (Serial.available() > 0) { c = Serial.read(); serial_buffer[counter] = c; counter++; } } // check marker if (serial_buffer[0] != 'x') { Serial.println("Bad configuration"); } for(;;); } else { // reiniciamos al estado inicial y continuamos Serial.println("Iniciando desde cero..."); // parpadeo largo for (int i = 0; i < 20; i++) { digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); delay(100); } // reiniciamos el estado // estado_actual = 0; EEPROM.write(EEPROM_ESTADO_ACT, estado_actual); EEPROM.write(EEPROM_NUM_ESTADOS, 2); EEPROM.write(EEPROM_TIMEDATA_START, 11); EEPROM.write(EEPROM_TIMEDATA_START+1, 15); EEPROM.write(EEPROM_TIMEDATA_START+2, 11); EEPROM.write(EEPROM_TIMEDATA_START+3, 20); // obturador cerrado obturador.attach(PIN_ACT_OBTURADOR); obturador.write(ANGULO_CIERRE); delay(250); obturador.detach(); // ponemos la primera alarma hora = EEPROM.read(EEPROM_TIMEDATA_START); minuto = EEPROM.read(EEPROM_TIMEDATA_START+1); rtc.setA1Time(0, hora, minuto, 0, 0x8, false, false, false); // Y la activamos rtc.turnOnAlarm(1); } } // modo normal // parpadeo digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); Serial.println("Continuando..."); // Cargamos datos desde la eeprom num_estados = EEPROM.read(EEPROM_NUM_ESTADOS); estado_actual = EEPROM.read(EEPROM_ESTADO_ACT); Serial.print("Estado leido: "); Serial.println(estado_actual); Serial.print("Num estados: "); Serial.println(num_estados); // Leemos el RTC mes = rtc.getMonth(siglo); dia_semana = rtc.getDoW(); dia = rtc.getDate(); hora = rtc.getHour(h12, pm); minuto = rtc.getMinute(); Serial.println(); Serial.print("---- "); Serial.print(mes); Serial.print("/"); Serial.print(dia); Serial.print(" "); Serial.print(hora); Serial.print(":"); Serial.println(minuto); delay(500); if (rtc.checkAlarmEnabled(1)) { Serial.println("\nAlarm 1 enabled"); } Serial.print("Alarm 1: "); rtc.getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm); Serial.print(ADay, DEC); if (ADy) { Serial.print(" DoW"); } else { Serial.print(" Date"); } Serial.print(' '); Serial.print(AHour, DEC); Serial.print(' '); Serial.print(AMinute, DEC); Serial.print(' '); Serial.print(ASecond, DEC); Serial.print(' '); if (A12h) { if (Apm) { Serial.print("pm "); } else { Serial.print("am "); } } Serial.print(' '); Serial.println(ABits, BIN); } void loop() { // Comprobamos alarma if (rtc.checkIfAlarm(1)) { Serial.println("Alarma!"); // dependiendo de si el estado actual es par o impar, abrimos o cerramos el obturador obturador.attach(PIN_ACT_OBTURADOR); if (estado_actual % 2 == 0) { obturador.write(ANGULO_APERTURA); Serial.println("Abriendo..."); } else { obturador.write(ANGULO_CIERRE); Serial.println("Cerrando..."); } delay(250); obturador.detach(); // pasamos al siguiente estado estado_actual = estado_actual + 1; if (estado_actual > num_estados) { estado_actual = 0; } hora = EEPROM.read(EEPROM_TIMEDATA_START + (estado_actual*2)); minuto = EEPROM.read(EEPROM_TIMEDATA_START + (estado_actual*2) + 1); // ponemos la nueva alarma dia_semana = rtc.getDoW(); rtc.setA1Time(0, hora, minuto, 0, 0x8, false, false, false); rtc.turnOnAlarm(1); } Serial.println("Sleep..."); // a dormir (bajo consumo) Serial.flush(); // wait for serial for (int i = 0 ; i < 15 ; i++) { LowPower.powerDown(SLEEP_2S, ADC_OFF, BOD_OFF); } RESTART; }
Después de ensamblar el circuito descrito en el diagrama, y asegurarse de que el RTC ya tenga la hora correcta (usando el ejemplo de la biblioteca RTC DS3231 para configurarlo el tiempo), será necesario programarlo con el código Arduino listado, y para ello primero tendremos que configurar en el código las horas deseadas para los disparos en su primer apartado.
Para ello modificaremos las horas, minutos y segundos de cada disparo en el apartado de tiempos, y comentaremos o descomentaremos las secuencias TOMA_SOL2 y TOMA_SOL3 en función de si queremos uno, dos o tres disparos (y por tanto anomalías como las que ocurren con la imagen del ejemplo de la galería).
Luego programaremos el arduino con este código y montaremos el sistema dentro de la cámara que vamos a utilizar. Recomendamos utilizar una caja totalmente estanca, posiblemente una caja de conexión de PVC adecuada al tamaño de la toma que queramos hacer (dependiendo de nuestro pinhole, distancia focal, etc.), y pegaremos el servo con una pieza que cuando el servo está en posición 0º tapar la persiana. Podemos hacer alguna prueba primero con el ejemplo de servocontrol incluido en el entorno arduino para ver las posiciones correspondientes y la dirección del movimiento.
Colocaremos el panel solar orientado hacia el sur y con un ángulo aproximado con respecto al horizonte en la latitud donde nos encontremos para maximizar su exposición solar.
Antes de cerrar la cámara, debemos reiniciar el código. Para ello conectaremos los pines marcados en el diagrama como E / S entre sí y alimentaremos la placa, para que el programa entienda que tiene que empezar de cero. Ahora desconectaremos todo, incluidos los pines de E / S y volveremos a encender el sistema, que ahora estará listo para realizar las tomas de forma automática. Podemos comprobar si el sistema está vivo mirando el LED esquemático, que debería parpadear aproximadamente cada 30 segundos.