Собираем устройство для проверки длительности выдержек затворов аналоговых фотоаппаратов
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.
Читайте также:
Комментарии посетителей (4):
Сам несколько недель думал о таком приборчике. Видимо, ты считал проекцию моих мыслей из ноосферы. Но я хотел сделать еще проще: светодиод, фотодиод, микрофонный вход звуковой карты, любая программа для звукозаписи
Wintercore bimbo, тут просто меня радует то, что это достаточно маленький и при этом полностью автономный приборчик получился 😊. А для твоего варианта придётся комп с собой таскать, как я понял. Хотя, это конечно нынче тоже не особо проблема 😄.
Тут некоторые люди высказывают мне своё «фи» на тему того, что, мол, нужно было этот гаджет оформить в виде полноценного устройства (в корпусе), а не как у меня, в виде простого испытательного стенда. Ну и у меня в этой связи к таким умникам вопрос: а зачем это делать? Вот я проверил на этом своём стенде все свои камеры (см. https://lead-pepelats.ru/blog/results-of-speeds-shutters-measurements-of-my-cameras/ ), и что дальше? Я потрачу массу времени на разработку для этого приборчика удобного и компактного корпуса, его печать на 3D-принтере, и п.д. и т.п., для того чтобы он просто валялся без дела? Какой в этом смысл? Я просто его теперь разберу, а освободившие детали послужат в других моих Arduino-проектах (благо идеи таких проектов у меня имеются). В конце концов, если он мне снова понадобится, то я просто снова его соберу — готовые схема и скетч теперь имеются. Такие дела, критики 😜.