Блог / Собираем устройство для проверки длительности выдержек затворов аналоговых фотоаппаратов
14 февраля 2024
Мне давно было интересно замерить фактическую длительность выдержек которые отрабатывают затворы имеющихся у меня аналоговых фотокамер, чтобы оценить насколько эти значения отличаются от номинальных. Тем интереснее, что я располагаю камерами самых разных систем, годов выпуска и стран производителей. При поиске решения, меня заинтересовала заметка, в которой описана конструкция гаджета для измерения скорости затвора, собранного на базе Arduino. Отлично! Хорошая возможность и свою задачу решить, и познакомиться с Arduino, сделав на нём свой первый, хоть и не очень сложный, но интересный проект. Ну что, народ, погнали?!!
Arduino
Arduino — это по сути электронный конструктор (см. подробнее тут). В основе устройств собранных на Arduino лежит программируемый микроконтроллер, что в сочетании с широчайшим спектром совместимых модулей расширения, датчиков и прочих компонентов, даёт практически неограниченные возможности по созданию самых разнообразных электронных и электро-механических устройств.
Идея
Да, идея устройства не моя, более того, и схему я, по сути, взял из оригинальной статьи (хоть я её и немного модифицировал добавив кнопку «сброса»). А вот прошивку для данного гаджета мне пришлось переписать почти полностью, т.к. прошивка из оригинальной статьи «не взлетела», и, надо сказать, «взлететь» не могла.
Схема, принцип работы и компоненты
На схеме указаны именно те компоненты которые использовал я.
Моя версия схемы устройства
По схеме принцип работы устройства понять совсем не сложно (мне-то точно, т.к. по первой специальности я радиотехник 😄): между выводами +5V и A3 (один из аналоговых входов/выходов) микроконтроллера установлен фототранзистор. Чем больше интенсивность света попадающего на этот фототранзистор, тем больше он «открывается», и подаёт на вход A3 большее напряжение (максимум 5 вольт). Соответственно, чем меньше света попадает на фототранзистор, тем на вход A3 попадает меньшее напряжение. В темноте фототранзистор как бы «закрывается», и фактически «разрывает» указанную цепь. Чтобы при «разрыве» цепи контакт A3 не «висел в воздухе» и не ловил как антенна наводки, он через резистор с номиналом 10 кОм выведен на «землю» (контакт «GND» на микроконтроллере). Микроконтроллер же измеряет продолжительность входного импульса (выше некоторого порогового значения указанного в прошивке) поданного на аналоговый вход A3 и, после обработки в соответствии с программой заложенной в его прошивке, выводит результат измерения на дисплей. Всё до гениальности просто.
Ну и список элементов которые использовал я:
-
Микроконтроллер Arduino Nano 3.0 CH340 Type-C
Arduino Nano я специально покупал с разъёмом Type-C — как-то он мне милее прочих «мелкоUSB».
-
Дисплей NFP1315-61A (SSD1306)
Разрешение: 128×32 пикс., диагональ: 0.96", цвет: голубой. -
Фототранзистор Kingbright L-53P3C
NPN, длина волны: 940 нм.Данный фототранзистор имеет немного большие время нарастания и время спада (15 мкс. против 10 мкс. у фототранзистора из оригинальной статьи), но даже для выдержки 1/500 сек. (2 мс.) это всё равно весьма незначительная величина (разница — два порядка).
-
Резистор 10 кОм.
В нашем случае достаточно двух резисторов -
Кнопка
Я купил относительно модную кнопу, но на самом деле подойдёт практически любая.
-
Беспаечная макетная плата
400 отверстий (клеммная колодка на 300 отверстий + две планки по 50 отверстий), 82×55×8.5 мм. -
Набор соединительных проводов
«Папа-папа», «папа-мама», «мама-мама». Длина: 10 см.Вообще, для этой схемы мне понадобились только провода «папа-папа» и три провода «папа-мама» для кнопки (для неё не хватило места на плате), но на всякий случай я прикупил все комбинации проводов.
Вот и все детали что нам понадобятся. Все элементы покупал под беспаечную установку (паяльника у меня нет, а покупать его не хочу).
Вот такой получился испытательный стендик 😊 (на фото с батарейным отсеком, т.е. с автономным питанием ☝️).
Я запитал схему от 6-ти вольт (4 батарейки «АА») через пин «VIN», но наверное и 9-вольтовая «Крона» потянула бы (через тот же пин). А вообще, можно и просто через USB 5-тью вольтами запитаться.
Прошивка (скетч)
Повторюсь, прошивку из оригинальной статьи я переписал почти полностью, оставив более менее нетронутыми только методы displayDuration() и displaySpeed(), хотя в последнем и добавил округление дробной части значения для выдержек меньше одной секунды (возможно это округление и лишнее, так что при желании можете его убрать в коде — это не сложно).
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define WIRE Wire
#define RECEIVER_PIN A3
#define RESET_PIN 2
#define THRESHOLD_LEVEL 500
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &WIRE);
void displayDuration(unsigned long duration) {
double msecs = duration / 1000.0;
String text = String("Time: ") + msecs + String(" msecs");
display.println(text);
Serial.println(text);
}
void displaySpeed(unsigned long duration) {
String text;
if (duration >= 1000000.0) {
double secs = duration / 1000000.0;
text = String("Speed: ") + secs + String(" secs");
}
else {
double speed = 1000000.0 / duration;
text = String("Speed: 1/") + round(speed) + String(" secs");
}
display.println(text);
Serial.println(text);
}
void durationMeter() {
display.clearDisplay();
display.setCursor(0,0);
display.println("\nWaiting for shoot...");
display.display();
unsigned long start_time = 0;
while (true) {
unsigned long value = analogRead(RECEIVER_PIN);
if (start_time == 0 && value > THRESHOLD_LEVEL) {
start_time = micros();
}
if (start_time > 0 && value < THRESHOLD_LEVEL) {
break;
}
}
unsigned long duration = (micros() - start_time);
display.clearDisplay();
display.setCursor(0,0);
displayDuration(duration);
displaySpeed(duration);
display.println("Press Reset for continue.");
display.display();
while (start_time > 0) {
if (digitalRead(RESET_PIN) == HIGH) {
start_time = 0;
}
}
display.clearDisplay();
}
void setup() {
pinMode(RECEIVER_PIN, INPUT);
pinMode(RESET_PIN, INPUT);
Serial.begin(9600);
Serial.println("OLED FeatherWing test");
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
// Address 0x3C for 128x32
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
for (;;);
}
Serial.println("OLED begun");
}
void loop() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
durationMeter();
}
Прошивку компилил и закатывал в контроллер посредством своего смартфона (Samsung Galaxy M30s | SM-M307FN/DS + прога ArduinoDroid), т.к. ардуиновская идэешка не захотела работать на моей 7-ой Винде (при запуске программы вылезает ошибка: «Точка входа в процедуру GetPackegeFamilyName не найдена в библиотеке DLL KERNEL32.dll.»), а разбираться с причинами этого отлупа у меня не было никакого желания. Правда пришлось прикупить OTG-переходник под USB Type-C.
Кстати, если решите также заморочиться со смартфоном, то сначала убедитесь что ваш аппарат поддерживает OTG.
Как пользоваться устройством
Кроме подопытного фотоаппарата и данного измерительного ардуино-девайса нам понадобится обыкновенный фонарик. Идея такая: фототранзистор нашего измерительного гаджета «смотрит» на затвор фотоаппарата с одной стороны, а фонарик светит на затвор с другой, и как только затвор отработает некоторую выдержку, наш ардуино-агрегат отобразит её фактическую продолжительность на дисплее — всё очень просто.
Всё приготовили для замера, нажимаем кнопку спуска на камере...
... получаем результат замера
Конечно же, перед замерами нужно открыть диафрагму объектива на максимум или вообще снять объектив с камеры (если это возможно). Если относительное отверстие объектива около f/4.5 или меньше (темнее), а снять его с камеры не представляется возможным, то просто придётся воспользоваться более ярким фонариком.
Измерения можно проводить при нормальном (не слишком ярком ☝️) освещении.
О точности измерений
(касательно повышения точности измерений см. обновление от 29 февраля 2024 г.)
Конечно, в таком деле важно понимать с какой точностью измерения мы имеем дело. Особенно это критично для выдержек 1/500 сек. и короче. Что же, давайте проанализируем факторы, которые могут влиять на точность рассмотренного прибора.
- Инерционность фототранзистора. Как я указал выше, у фототранзистора который использовал я, и время нарастания, и время спада равны 15 мкс. Если я всё правильно понял, эти параметры характеризуют инерционность реакции фототранзистора при попадании на него света и при его снятии. Т.е., о том что на него начал попадать свет, фототранзистор в полной мере «поймёт» в худшем случае с задержкой на 15 мкс, и с такой же задержкой «узнает» о том, что свет на него попадать перестал. Таким образом, получается взаимная компенсация и выходит что эти параметры не оказывают влияния на точность прибора. Если мои рассуждения неверны, поправьте меня в комментариях.
- Частота дискретизации. Немного поколдовав над скриптом, я замерил время которое уходит на одну итерацию в цикле запущенном на моём контроллере, и у меня получилось значение 112 мкс. Т.е., контроллер чекает сигнал от фототранзистора каждые 112 мкс (без малого 9 кГц). Таким образом, можно прикинуть что от выдержки 1/500 это время составляет 5.6%, а от выдержки 1/1000 — 11.2%. Собственно, исходя из этого можно оценить и возможную погрешность измерения столь коротких выдержек — если прибор показывает значение 1/500 сек, то надо понимать что реальное значение лежит в пределах от 1/473 сек. до 1/530 сек. (вы там за мной проверяйте, ничего ли я не напутал 😜). На более долгих выдержках эта погрешность будет, по сути, вообще нивелирована за счёт округления дробной части значения выдержки.
Таким образом, получается что, в принципе, точность измерения данным гаджетом выдержек длиннее 1/500 сек. весьма недурная, ну а при измерении более коротких выдержек конечно нужно держать погрешность в голове. Тем не менее, если вы выставили на затворе выдержку 1/1000 сек., а прибор показывает 1/200 сек., то тут уже точно можно говорить о том, что затвор данную выдержку отрабатывает некорректно. Так что, в любом случае, прибором имеет смысл прочекать и выдержки короче 1/500 сек.
И ещё...
Вы наверное обратили внимание на то, что на иллюстрациях к данной статье гаджет руссифицирован, а приведённый мной код прошивки нет. Так вот, если тоже захотите озадачиться кириллицей, то тут сможете узнать как это можно сделать (обратите внимание на то, какая у вас версия библиотеки «Adafruit-GFX» — «новая» или «старая»). Удачи!
Повышаем точность измерения коротких выдержек (обновление от 29 февраля 2024 г.)
Когда я узнал что микроконтроллеры Arduino поддерживают аппаратные прерывания, у меня появилась идея как можно усовершенствовать свой гаджет, повысив скорость его реакции, а, следовательно, его точность. Конечно же, в первую очередь это критично для коротких выдержек (1/500 сек. и короче). Аппаратные прерывания часто используют именно для детектирования коротких событий — импульсов.
У Arduino Nano (ATmega 328/168) аппаратные прерывания поддерживают только два пина — «D2» и «D3», так что пришлось немного изменить схему устройства, а именно, перекинуть провод с аналогового пина «A3» на цифровой пин «D3» («D2» у меня уже занят кнопкой сброса).
Вторая версия схемы
Ну, а дальше дело за скетчем:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define WIRE Wire
#define RECEIVER_PIN 3
#define RESET_PIN 2
volatile unsigned long start_time = 0;
volatile unsigned long end_time = 0;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &WIRE);
void displayDuration(unsigned long duration) {
double msecs = duration / 1000.0;
String text = String("Time: ") + msecs + String(" msecs");
display.println(text);
Serial.println(text);
}
void displaySpeed(unsigned long duration) {
String text;
if (duration >= 1000000.0) {
double secs = duration / 1000000.0;
text = String("Speed: ") + secs + String(" secs");
}
else {
double speed = 1000000.0 / duration;
text = String("Speed: 1/") + round(speed) + String(" secs");
}
display.println(text);
Serial.println(text);
}
void durationMeter() {
display.clearDisplay();
display.setCursor(0,0);
display.println("\nWaiting for shoot...");
display.display();
while (true) {
if (start_time > 0 && end_time > 0) {
break;
}
}
unsigned long duration = (end_time - start_time);
display.clearDisplay();
display.setCursor(0,0);
displayDuration(duration);
displaySpeed(duration);
display.println("Press Reset for continue.");
display.display();
while (start_time > 0) {
if (digitalRead(RESET_PIN) == HIGH) {
start_time = 0;
end_time = 0;
}
}
display.clearDisplay();
}
void listener() {
byte value = digitalRead(RECEIVER_PIN);
if (value == HIGH && start_time == 0) {
start_time = micros();
}
if (value == LOW && start_time > 0 && end_time == 0) {
end_time = micros();
}
}
void setup() {
pinMode(RECEIVER_PIN, INPUT);
pinMode(RESET_PIN, INPUT);
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(RECEIVER_PIN), listener, CHANGE);
Serial.println("OLED FeatherWing test");
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println("SSD1306 allocation failed");
for (;;);
}
Serial.println("OLED begun");
}
void loop() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
durationMeter();
}
Ума не приложу каким образом теперь оценить точность измерений, но по логике вещей она должна быть заметно выше чем у первой версии гаджета.
P.S. — В ближайшее время планирую посидеть со своими фотоаппаратиками и оценить точность работы затвора каждого из них. Результаты замеров опубликую отдельной заметкой. Интересно 😋! На днях прочекал данным гаджетом почти все свои фотокамеры, по итогам опубликовал заметку с результатами замеров — результаты получились весьма интересные.
P.P.S. — Ceterum censeo Washington esse delendam.
Читайте также:
Комментарии посетителей (12):
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
![](https://lead-pepelats.ru/tmpl/pepelats.theme/img/alien-avatar.jpg)
Сам несколько недель думал о таком приборчике. Видимо, ты считал проекцию моих мыслей из ноосферы. Но я хотел сделать еще проще: светодиод, фотодиод, микрофонный вход звуковой карты, любая программа для звукозаписи
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
Wintercore bimbo, тут просто меня радует то, что это достаточно маленький и при этом полностью автономный приборчик получился 😊. А для твоего варианта придётся комп с собой таскать, как я понял. Хотя, это конечно нынче тоже не особо проблема 😄.
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
Тут некоторые люди высказывают мне своё «фи» на тему того, что, мол, нужно было этот гаджет оформить в виде полноценного устройства (в корпусе), а не как у меня, в виде простого испытательного стенда. Ну и у меня в этой связи к таким умникам вопрос: а зачем это делать? Вот я проверил на этом своём стенде все свои камеры (см. https://lead-pepelats.ru/blog/results-of-speeds-shutters-measurements-of-my-cameras/ ), и что дальше? Я потрачу массу времени на разработку для этого приборчика удобного и компактного корпуса, его печать на 3D-принтере, и п.д. и т.п., для того чтобы он просто валялся без дела? Какой в этом смысл? Я просто его теперь разберу, а освободившие детали послужат в других моих Arduino-проектах (благо идеи таких проектов у меня имеются). В конце концов, если он мне снова понадобится, то я просто снова его соберу — готовые схема и скетч теперь имеются. Такие дела, критики 😜.
![](https://lead-pepelats.ru/tmpl/pepelats.theme/img/alien-avatar.jpg)
Очень интересное решение с увеличением точности измерений, прочитал бы раньше, обязательно бы применил в своем приборе! По поводу корпуса для сего девайса, сегодня наконец то выложил на фингверс мой долгострой. Правда версия без кнопки, за основу брал исходный проект. Возможно придется незначительно изменить размеры, толщину под конкретную плату и экран.
https://www.thingiverse.com/thing:6616581
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
Mike Tanen, круто! 👏👏👏 Вот бы ещё кнопку 😁.
![](https://lead-pepelats.ru/tmpl/pepelats.theme/img/alien-avatar.jpg)
Сейчас готовлю новую версию, на этот раз применю твой код и кнопку, также выложу на фингверс со ссылкой на эту статью, если ты не против. На самом деле проектов очень много, времени бы на все найти. Полистал твои заметки, очень любопытно, обратил внимание на твое особое внимание к чайке, также горячо люблю этот фотоаппарат. В качестве задумки есть даже корпус для двухобъективной зеркальной чайки. Проект родился сам собой, есть 2 объектива индустар-69, одна разрушенная чайка с рабочим затвором, пентапризма, фокусировочный экран и зеркало от зенита. В целом можно даже попробовать сделать управление ее центральным затвором соленоидом посредством ардуино. Но проблема в том что я по основной профессии конструктор. А данный проект требует слишком много времени на программирование.
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
Mike Tanen, конечно я не против, даже настаиваю чтобы ты и тут свой новый проект корпуса выложил 😁. Готов к любому сотрудничеству по этой теме 👍.
Ну а Чайка, конечно, оооочень забавная камера 😋. Кстати, как-то на Мешке видел в продаже самоделку двухобъективную на базе Чайки-2.
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
⚠️⚠️⚠️ К слову о проверке точности измерений выдержки для версии гаджета на аппаратных прерываниях. Собрал стендик который "зажигает" светодиод на выбранное время. Выставил 2 миллисекунды (это 1/500 сек) и замерил время свечения светодиода своим тестером выдержек. Результат на табло (на картинке 😄). Так что ИМХО аппаратик вполне подойдёт и для проверки 1/500 сек.
![](https://lead-pepelats.ru/tmpl/pepelats.theme/img/alien-avatar.jpg)
Я бы добавил, что нужно брать плату с процессором Atmega 328P, а не с Atmega 168P, так как в последнем не хватит памяти для второй версии кода.
![](https://lead-pepelats.ru/uploads/accounts/a7yfs3wg.png)
Да, но можно попробовать вместо библиотеки Adafruit использовать что-нибудь более компактное, например GyverOLED (она, кстати, сразу с кириллицей идёт 😊).