Товарищи, ищу братьев по разуму в DSLR фотокамерами - вы меня точно поймете. Решил я собрать ИНТЕРВАЛОМЕТР для интервальной фотосъемки (устройство выдает команду на спуск затвора через выставляемый интервал).
Перекопал массу проектов на эту тему, но увы.. 90% их них проводные (т.е с разъемом вставляемым в камеру, что не есть хорошо), а хотелось бы использовать "не инвазивный" метод фактический повторение ИК команды с пульта ДУ на спуск затвора через ИК диод, размещенный вблизи ИК порта фотокамеры.
ВНИМАНИЕ! Эта схема авторская, не финальная (финальную см.ниже)
Для сборки понадобится: Дисплей 16x2 с i2c, Ардуинка Nano, модуль джойстика, ИК диод, резистор на 200ом, кнопка (сброса). И всё!!!
Покопался, нашел один древний и очень простенький проект ВОТ ЭТОТ, собрал его - а он увы (сразу) не заработал как надо и судя по комментариям на которые автор не отвечает - не заработал ни у кого.
Итак о проблемах:
A) -собранное устройство запускается, дисплей работает, даже пытается работать, переходя в соответствующий режим но... странно ведет себя мини-джойстик управления (дурачится, срывает выбор и т.д). Такое впечатление что проблема или в кнопке "выбора" она должна быть инвертирована или нет, не понятно. А так же в том что в момент исполнения через несколько секунд поступает команда с джойстика будто его кто-то тронул и исполнение прекращается. P.S. - РЕШЕНО (см. ниже)
Б) и главное - вшитый код команды "спуск затвора" не для моей камеры, а хотелось бы что бы или был выбор производителя с меню, или хотя бы выбор камеры путем правки в коде. Метод PulseOn/OFF (код в конце поста) как мне кажется тут перечеркивает все замашки на универсальность. P.S. - НЕ РЕШЕНО
Задача:
1) - Разобраться с управлением или поменять его на другой метод.
2) - В общем, вычитал я что есть библиотека multi-Camera-IR-Control (от Sebastian Setz) в которой автор предусмотрительно подсобрал ИК коды для разных производителей фотокамер, но проектов где можно подсмотреть скетч для этой библиотеки - для нее я так и не нашел (может у вас получится). С другой стороны, можно использовать любой метод засылки СЧИТАННОГО с оригинального пульта ИК кода, но уж точно не PulseOn/OFF.
3) - если кто-то проявит материализованный энтузиазм и доведет до ума затею, лично проставлю ему стакан коньяка. А вообще, устройство любому фотографу реально нужное и было бы неплохо продумать вариант с OLED дисплеем и дополнительными функциями, вроде автоматического вычисления сколько нужно снимков, что бы сделать ролик заданной длинны с заданной частотой кадров.
В общем, буду благодарен за любые советы и помощь как скрестить одно с другим и сделать очень полезную штуку для увлеченных астрофотографией.
ВНИМАНИЕ! Код исходный, авторский со всеми косяками - исправленный см. ниже.
Перекопал массу проектов на эту тему, но увы.. 90% их них проводные (т.е с разъемом вставляемым в камеру, что не есть хорошо), а хотелось бы использовать "не инвазивный" метод фактический повторение ИК команды с пульта ДУ на спуск затвора через ИК диод, размещенный вблизи ИК порта фотокамеры.
ВНИМАНИЕ! Эта схема авторская, не финальная (финальную см.ниже)
Для сборки понадобится: Дисплей 16x2 с i2c, Ардуинка Nano, модуль джойстика, ИК диод, резистор на 200ом, кнопка (сброса). И всё!!!
Покопался, нашел один древний и очень простенький проект ВОТ ЭТОТ, собрал его - а он увы (сразу) не заработал как надо и судя по комментариям на которые автор не отвечает - не заработал ни у кого.
Итак о проблемах:
A) -
Б) и главное - вшитый код команды "спуск затвора" не для моей камеры, а хотелось бы что бы или был выбор производителя с меню, или хотя бы выбор камеры путем правки в коде. Метод PulseOn/OFF (код в конце поста) как мне кажется тут перечеркивает все замашки на универсальность. P.S. - НЕ РЕШЕНО
Задача:
1) - Разобраться с управлением или поменять его на другой метод.
2) - В общем, вычитал я что есть библиотека multi-Camera-IR-Control (от Sebastian Setz) в которой автор предусмотрительно подсобрал ИК коды для разных производителей фотокамер, но проектов где можно подсмотреть скетч для этой библиотеки - для нее я так и не нашел (может у вас получится). С другой стороны, можно использовать любой метод засылки СЧИТАННОГО с оригинального пульта ИК кода, но уж точно не PulseOn/OFF.
3) - если кто-то проявит материализованный энтузиазм и доведет до ума затею, лично проставлю ему стакан коньяка. А вообще, устройство любому фотографу реально нужное и было бы неплохо продумать вариант с OLED дисплеем и дополнительными функциями, вроде автоматического вычисления сколько нужно снимков, что бы сделать ролик заданной длинны с заданной частотой кадров.
В общем, буду благодарен за любые советы и помощь как скрестить одно с другим и сделать очень полезную штуку для увлеченных астрофотографией.
ВНИМАНИЕ! Код исходный, авторский со всеми косяками - исправленный см. ниже.
C++:
// Article http://english.cxem.net/arduino/arduino6.php
// Version 1.0
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
#define axis_X 1 // axis Х of Joystic connected to Analog 0
#define axis_Y 0 // axis Y of Joystic connected to Analog 1
#define axis_Z 3 // axis-button Z of Joystic connected to Digital 3
#define pinIRLED 10 // IR LED
#define LEDgreen 13 // onboard LED
#define autoOFF 10 // autoOFF backlight LCD
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
int value_X, value_Y, value_Z = 0; // axis values
int pos = 0; // current position (0 - delay, 1 - work)
int interval = 1; // pause between shots (sec)
int cntPict = 0; // shots count
boolean working = false;
unsigned long currentTime;
unsigned long TimeShot, TimeLCDOff;
void setup()
{
pinMode(axis_Z, INPUT); // Joystic button
pinMode(pinIRLED, OUTPUT); // IR LED
lcd.init(); // init LCD
lcd.backlight(); // turn LCD backlight ON
lcd.clear(); // clear LCD
show_menu(); // function show menu
currentTime = millis();
TimeShot = currentTime; // shots timer
TimeLCDOff = currentTime; // backlight timer
Serial.begin(115200);
}
void loop()
{
value_X = analogRead(axis_X); // read the analog value of the X axis
value_Y = analogRead(axis_Y); // read the analog value of the Y axis
value_Z = digitalRead(axis_Z); // read the digital value of the Z axis (button)
value_Z = value_Z ^ 1; // invert the value
if(working == false){
if(value_Y > 550){ // joystick up
pos = 0;
lcd.backlight(); // LCD backlight ON
TimeLCDOff = currentTime; // new value of TimeLCDOff
show_menu();
}
else if(value_Y < 390){ // joystick down (middle postition data from joystick is Y= 516)
pos = 1;
lcd.backlight(); // LCD backlight ON
TimeLCDOff = currentTime; // new value of TimeLCDOff
show_menu();
}
if(value_X > 530){ // joystick left (middle postition data from joystick is X= 511)
lcd.backlight(); // LCD backlight ON
TimeLCDOff = currentTime; // new value of TimeLCDOff
if(pos == 0){
--interval;
if(value_X > 800) interval = interval-10; // joystick full left
if(interval < 1) interval = 1;
}
show_menu();
}
else if(value_X < 500){ // joystick right
lcd.backlight(); // LCD backlight ON
TimeLCDOff = currentTime; // new value of TimeLCDOff
if(pos == 0) {
++interval;
if(value_X < 100) interval = interval+5; // joystick full right
}
show_menu();
}
}
if(value_Z == 1){ // joystick button press
lcd.backlight(); // LCD backlight ON
TimeLCDOff = currentTime;
if(working == true){
working = false;
pos = 0;
show_menu();
}
if(pos == 1) show_working(); // turn on work mode
}
delay(200);
currentTime = millis();
if(working == true){
if(currentTime >= (TimeShot + (interval*1000))){
digitalWrite(LEDgreen, HIGH); // blink onboard LED
delay(100);
digitalWrite(LEDgreen, LOW);
takePicture(); // send IR
TimeShot = currentTime;
++cntPict; // increase the counter shots
show_working(); // refresh LCD
}
}
if(currentTime >= (TimeLCDOff + (autoOFF*1000))){
lcd.noBacklight(); // LCD backlight OFF
}
}
void show_menu()
{
cntPict = 0; // zero out counter shots
lcd.clear();
lcd.setCursor(0, pos);
lcd.print("*"); // current position
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;
}
// pulse the infrared emitter for a specified duration (in microseconds)
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 - e.g. the 'on' part of our wave
digitalWrite(pinIRLED, LOW); // turn IR off
delayMicroseconds(13); // half a clock cycle for a 38 Khz (26.32 microseconds period)
}
}
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++) { // impulse send twice
pulseON(2336);
pulseOFF(646);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(11008);
pulseON(2336);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(11008);
pulseON(2336);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(646);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1168);
pulseOFF(621);
pulseON(1093);
pulseOFF(696);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(621);
pulseON(572);
pulseOFF(1218);
pulseON(497);
pulseOFF(1292);
pulseON(422);
pulseOFF(1367);
pulseON(373);
pulseOFF(11803);
pulseON(298);
pulseOFF(2659);
pulseON(199);
pulseOFF(1590);
pulseON(174);
pulseOFF(1019);
pulseON(174);
pulseOFF(1615);
pulseON(174);
pulseOFF(1615);
pulseON(149);
pulseOFF(1044);
pulseON(149);
pulseOFF(1640);
pulseON(124);
pulseOFF(1093);
pulseON(149);
pulseOFF(1044);
pulseON(124);
pulseOFF(1665);
pulseON(124);
pulseOFF(1068);
pulseON(124);
pulseOFF(1665);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(12101);
pulseON(149);
pulseOFF(2833);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(75);
pulseOFF(1715);
pulseON(75);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1118);
pulseON(99);
pulseOFF(1093);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(1690);
pulseON(99);
pulseOFF(646);
}
}
Изменено: