Интервалометр с LCD для Sony NEX

Интервалометр — устройство, предназначенное для съемки длительных процессов, так называемое TimeLapse-фото. Как правило, интервалометр представляет собой отдельную коробочку, на которой выставляется пауза между снимками и который через ИК дает команду фотокамере на спуск затвора. При этом, в самом фотоаппарате должен быть включен режим управления от пульта ДУ.

При помощи интервалометра, вы к примеру можете снять роспуск цветка, а потом смонтировать полученные кадры в видеоролик. Применений в фотоискусстве интервалометру можно найти множество.

В данной статье речь пойдет об изготовлении интервалометра с LCD-экранчиком на базе платы Arduino. Период между снимками в секундах задается в меню. Тестировалось на фотоаппарате Sony NEX 5N, но я думаю он должен подойти для любых беззеркалок NEX и зеркалок Sony Alpha, т.к. пульты ИК у них совместимые.

Необходимые комплектующие:
Arduino Nano (или любая совместимая Arduino-плата)
Serial LCD (можно использовать и обычный LCD)
Модуль джойстика (Joystick Module)
ИК светодиод и резистор ~200 Ом
Выключатель питания
Корпус
Батарейка крона 9В

Первые 3 компонента и корпус я покупал на eBay.

Принципиальная схема интервалометра:

Принципиальная схема интервалометра

Serial LCD имеет 4 вывода: GND, VCC, SDA, SCL. Линия SDA (data) подключается к Analog In 4, а SCL (clock) к Analog In 5. Vcc подключается к 5V Arduino, а GND к GND Arduino.

Для подключения джойстика необходимо 5 проводов: ось X (к Analog IN 0), ось Y (к Analog IN 1), кнопка Z (к Digital IN 2), питание Vcc и общий GND.

Схема подключения всех компонентов выглядит следующим образом:

Схема подключения

Питается схема от 9В батарейки. Плюсовой вывод батарейки подключается к входу Vin контроллера Arduino. Плата Arduino содержит встроенный преобразователь напряжения 5В, которые необходимы нам для питания LCD.

Анод ИК светодиода подключается через токоограничительный резистор, подключенный к 10 выводу Arduino. Катод к GND. Резистор и выводы светодиода я поместил в термоусадочную трубку. Сам провод питания ИК светодиода поместил в гибкую белую длинную трубку.

ИК светодиод и токоограничительный резистор

После того, как была собрана схема на макетной плате, я заметил, что LCD дисплей нормально инициализируется только после нажатия кнопки Reset на Arduino, никакие программные ухищрения не помогали. Видимо это недоработка Serial LCD библиотеки. Возможно, что в другом LCD с этим будет все нормально. Но мне пришлось вывести внешнюю кнопку Reset.

Пробная схема

Для интервалометра нужен нормальный корпус. Это было самой сложной и долгой частью проекта. В начале, я вырезал все необходимые отверстия под LCD, джойстик, кнопку и провод ИК-светодиода:

Изготовление корпуса интервалометра

Затем сделал крепление под джойстик, LCD, батарейку и плату Arduino. Использовал обычный рекламный пластик и суперклей.

Изготовление корпуса интервалометра

Для прижима батарейки, чтобы она не гуляла, использовал кусок ненужного материала для шумоизоляции авто (Акцент 10).

Изготовление корпуса интервалометра

Все в сборе:

Изготовление корпуса интервалометра

Итог работы:

Интервалометр

Программа

Программа отображает меню и отрабатывает взаимодействие с ним. Также, в ПО предусмотрена функция выключения подсветки дисплея, для экономии батарейки. При нажатии на любую кнопку подсветка снова включается. Исходный код представлен ниже, я постарался максимально подробно его прокомментировать.

 #include "Wire.h"  #include "LiquidCrystal_I2C.h"  #define axis_X 0    // ось Х подключена к Analog 0 #define axis_Y 1    // ось Y подключена к Analog 1 #define axis_Z 2    // ось Z (кнопка джойстика) подключена к Digital 2 #define pinIRLED 10 // пин ИК-светодиода #define LEDgreen 13 // встроенный onboard LED  #define autoOFF 10  // кол-во секунд через которое выключается подсветка дисплея при бездействии  LiquidCrystal_I2C lcd(0x27,16,2);    // установка I2C адреса LCD в 0x27, а также указываем что 16 символов, 2 строки  int value_X, value_Y, value_Z = 0;   // переменные для хранения значений осей int pos = 0;                         // текущая позиция (0 - установка delay, 1 - работа) int interval = 1;                    // пауза между снимками (в секундах) int cntPict = 0;                     // кол-во посланных пакетов, в режиме работа boolean working = false;  unsigned long currentTime; unsigned long TimeShot, TimeLCDOff;  void setup() {   pinMode(axis_Z, INPUT);         // кнопка джойстика   pinMode(pinIRLED, OUTPUT);      // ИК светодиод      lcd.init();                     // инициализация LCD    lcd.backlight();                // включаем подсветку LCD   lcd.clear();                    // очистка LCD   show_menu();                    // функция отображения меню      currentTime = millis();         // считываем время, прошедшее с момента запуска программы   TimeShot = currentTime;         // таймер снимка   TimeLCDOff = currentTime;       // таймер для подсветки   //Serial.begin(115200); }  void loop() {   value_X = analogRead(axis_X);    // считываем аналоговое значение оси Х   value_Y = analogRead(axis_Y);    // считываем аналоговое значение оси Y   value_Z = digitalRead(axis_Z);   // считываем цифровое значение оси Z (кнопка)   value_Z = value_Z ^ 1;           // инвертируем значение      if(working == false){     if(value_Y > 540){              // джойстик вверх       pos = 0;       lcd.backlight();              // включаем подсветку        TimeLCDOff = currentTime;     // в TimeLCDOff записываем новое значение       show_menu();      }     else if(value_Y < 500){         // джойстик вниз       pos = 1;       lcd.backlight();              // включаем подсветку        TimeLCDOff = currentTime;     // в TimeLCDOff записываем новое значение       show_menu();     }     if(value_X > 530){              // джойстик влево       lcd.backlight();              // включаем подсветку        TimeLCDOff = currentTime;     // в TimeLCDOff записываем новое значение       if(pos == 0){           --interval;           if(value_X > 900) interval = interval-10;  // джойстик сильно влево           if(interval < 1) interval = 1;       }       show_menu();     }     else if(value_X < 490){         // джойстик вправо       lcd.backlight();              // включаем подсветку        TimeLCDOff = currentTime;     // в TimeLCDOff записываем новое значение       if(pos == 0) {           ++interval;           if(value_X < 100) interval = interval+10;  // джойстик сильно вправо       }       show_menu();     }   }    if(value_Z == 1){               // если нажали кнопку джойстика      lcd.backlight();              // включаем подсветку      TimeLCDOff = currentTime;     // в TimeLCDOff записываем новое значение     if(working == true){       working = false;            // прерываем режим "работа"       pos = 0;       show_menu();                // если были в рабочем режиме, то прерываем     }      if(pos == 1) show_working();  // включаем режим работы   }      delay(200);      currentTime = millis();         // считываем время, прошедшее с момента запуска программы   if(working == true){     if(currentTime >= (TimeShot + (interval*1000))){  // сравниваем текущий таймер с переменной loopTime + delay       digitalWrite(LEDgreen, HIGH);                   // моргнем встроенным LED       delay(100);       digitalWrite(LEDgreen, LOW);                           takePicture();                                  // посылаем ИК пакет       TimeShot = currentTime;                         // в loopTime записываем новое значение       ++cntPict;                                      // увеличиваем счетчик снимков       show_working();                                 // обновляем LCD     }   }      if(currentTime >= (TimeLCDOff + (autoOFF*1000))){   // сравниваем текущий таймер с константой TimeLCDOff + delay                     lcd.noBacklight();                              // выключаем подсветку   }    }  void show_menu() {   cntPict = 0;        // обнуляем счетчик снимков      lcd.clear();   lcd.setCursor(0, pos);   lcd.print("*");     // маркер текущей позиции      lcd.setCursor(1, 0);    lcd.print("delay:");      lcd.setCursor(8, 0);    lcd.print(interval);      lcd.setCursor(1, 1);    lcd.print("go work"); }  void show_working() {   lcd.clear();   lcd.setCursor(3, 0);    lcd.print("working...");   lcd.setCursor(2, 1);    lcd.print("shots:");   lcd.setCursor(9, 1);   lcd.print(cntPict);   working = true; }  void pulseON(int pulseTime) {   unsigned long endPulse = micros() + pulseTime;        // create the microseconds to pulse for   while( micros() < endPulse) {     digitalWrite(pinIRLED, HIGH);                       // turn IR on     delayMicroseconds(13);                              // half the clock cycle for 38Khz (26.32ГѓпїЅ10-6s) - e.g. the 'on' part of our wave     digitalWrite(pinIRLED, LOW);                        // turn IR off     delayMicroseconds(13);                              // delay for the other half of the cycle to generate wave/ oscillation   } } void pulseOFF(unsigned long startDelay) {   unsigned long endDelay = micros() + startDelay;       // create the microseconds to delay for   while(micros() < endDelay); } void takePicture() {   for (int i=0; i < 2; i++) {    // импульс посылаем дважды     pulseON(2336);     pulseOFF(646); 	.......     .......     // Всю функцию не привожу, т.к. она очень длинная..   }  } 

Работа с интервалометром очень проста — после его включения появляется меню с двумя пунктами: delay и go work. При выборе delay, джойстиком влево и вправо можно настроить период между снимками в секундах. Причем, если немного отклонить джойстик, то кол-во изменяется на 1, а если до конца, то на 10. Т.о. это облегчает установку крупного значения. После того, как установлен период, необходимо перейти в пункт go work и нажать кнопку джойстика. Начнется работа интервалометра, при котором ИК-светодиод будет посылать импульсы для срабатывания затвора в камеру. ИК светодиод при этом необходимо расположить напротив ИК-приемника камеры (у Sony NEX 5 он находится спереди, сразу под кнопкой спуска). У меня нормально работает на расстоянии до 50 см.
В режиме работы появляется надпись working…, а на второй строке — счетчик количества сделанных снимков:

Интервалометр в работе

Для экономии батареи, через 10 секунд выключается подсветка дисплея (время выключения задается в настройках). Для того, чтобы выйти из рабочего режима, необходимо нажать кнопку джойстика.