Proiektua

Eguzkigrafia kamera

Proiektu honen helburua modu automatizatuan eguzki-analema jasotzea da. Eguzkiak zeruaren esferan duen batez besteko posiziotik (egun berean ordu berean eta leku beretik) aldentzen denean osatzen duen kurba da analema.

Taldea Katxarraroak

Eguzkigrafia kamera

Eguzkigrafia eguzkiak zeruan (Lur planetako leku bakoitzean modu ezberdinean) daukan ibilbidea behatzen duen efektua argazkigintzako praktika eta kontzeptua da. Paisaian horrek duen efektua argazkigintza estenopeikoa, tratamentu digitala eta Internet bidezko hedapena konbinatzen duen prozedimentu espezifikoa da. Rebelatu gabeko argazkigintzako papera erabiltzen da , kamara estenopeikoa eta eskanerra erabiltzen da eguzkiak egunero zeruan (orduak eta hilabeteen arteko esposizio luzeak) egiten duen ibilbidea jasotzen duen irudiak sortzeko. Bere sorreratik dauka mundu osoko afizionatuen artean Internet bidez hedatzeko, kolaboratzeko eta partekatzeko zaletasuna eta nahia.

Proiektu honen helburua modu automatizatuan eguzki-analema jasotzea da. Eguzkiak zeruaren esferan duen batez besteko posiziotik (egun berean ordu berean eta leku beretik) aldentzen denean osatzen duen kurba da analema. Gehienetan, terminoa Eguzkiak urtean zehar betetzen dituen posizioek zeruan marrazten duten irudia izendatzeko erabiltzen da. Analemak zortzi (8) formako kurba osatzen du.

Analema eskuz jasotzeak urte batez jarraian ordu berean eta leku berean argazki bat ateratzea esan nahi du. Batzuetan zaila gertatzen denez hori egitea argazki kamara bat edukitzea egunero ordu berean argazki bat aterako duena ariketa hau egiteko oso baliagarria izan daiteke.

Proiektu honetan Arduino bidez kontrolatzen den kamara bat sortu da; ordu sinkronizaziorako RTC-a (real time clock) erabili da eta kanpoko elikatze-iturrien beharrik ez izateko bateria sistema bat eta eguzki-panel bat. Sistema horrek eguzkiaren irudia jasotzeko eragozpenik gabeko leku zailetan kokatzea ahalbidetzen du. Kamararen obturadorea (pinhole motakoa) servo de 9gr kontrolatzen du, zeinek pinhole-aren zuloa ezkutatzen duen pieza bat mugitzen duen.

Pausuz pausu

  • Arduino Nano
  • RTC DS3231 moduloa
  • SparkFun SunnyBuddy
  • Eguzki panela
  • Lipo 1S 2000 mAh bateria
  • Servo 9gr
  • LED 5mm
  • 220 Ohm ERresistentzia
  • Konexio kablea
#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;
}

 

Eskeman azaldutako zirkuitua muntatu ondoren eta RTC -ak ordua ondo jarrita duela baieztatu ondoren (ordua jartzeko RTC DS3231 ematen duen adibidea erabiliz ) arduinoa goian azaldutako kodearekin programatu behar da. Horretarako nahi diren ordu kodeak konfiguratu beharko dira.

Denbora sekzioan hartualdi bakoitzaren  orduak, minutuak eta segundoak aldatuko dira, eta TOMA_SOL2 eta TOMA_SOL3 komentatu edo deskomentatuko dugu, baldin eta bat, bi edo hiru hartualdi nahi ditugun (eta beraz galeriako irudiko adibideko analemen kasua bezalaxe).

Ondoren arduinoa kodearekin programatuko dugu eta sistema guztia erabiliko dugun kameraren barruan montatua utzi. Hermetikoa den kaxa bat erabiltzea gomendatzen da, hartualdien neurrien araberako PVC konexioen kaxa bat (gure pinholearen araberakoa, foku-distantzia, etab.). Serboa pieza batekin itsatsiko dugu, modu horretan serboa 0º posizioan dagoenean obtuladorea estaliko du. Frogaren bat egin genezake aurretik, arduinoaren inguruko serboaren kontrolarekin, posizioaren eta mugimenduaren zentzuaren jarraipena egiteko.

Eguzki-panela, hegoalderantz begira jarriko dugu eta ikuspegia zeruertzera begira, eguzki-esposizioa maximizatzeko helburuarekin.

Kamera itxi aurretik, kodea berabiarazi behar da. Horretarako eskeman I/O moduan markatuak dauden pinak konektatuko dira eta plakari elikatze-iturria jarriko diogu, horrekin programak ulertuko du zerotik hasi behar duela. Ondoren guztia deskonektatuko dugu, I/O pinak barne eta sistema berriz ere elikatzen jarriko dugu. Hemendik aurrera hartualdiak automatikoki egiteko prest geratuko da. Sistema bizirik ote dagoen ikusteko modua eskemako LED-era begiratzea izango da, 30 segundoero kliskatu beharko luke-eta.