Блог / Собираем устройство для проверки длительности выдержек затворов аналоговых фотоаппаратов
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.
Читайте также:
Поддержать проект «Свинцовый Пепелац»:
Вы можете поддержать проект «Свинцовый Пепелац» финансово, переведя в его пользу любую сумму (от 1 руб.)
Комментарии посетителей (30):
- 2
- 1

Я бы добавил, что нужно брать плату с процессором Atmega 328P, а не с Atmega 168P, так как в последнем не хватит памяти для второй версии кода.

Да, но можно попробовать вместо библиотеки Adafruit использовать что-нибудь более компактное, например GyverOLED (она, кстати, сразу с кириллицей идёт 😊).

Три раза "ку" и десяток КЦ для тебя, о достойнейший. Ты предвосхитил все ТТХ, которые я мыслил в подобном приборе - простота, приемлемая точность и доступность комплектующих. Я повторил твою конструкцию, после ремонта нескольких старых камер была необходимость точно знать, что именно отрабатывают затворы, которым по 30-40 лет. И прибор пришелся очень кстати, в настройке/регулировке вещь незаменимая. Заодно посоветовал бы такой прибор пленочникам-любителям ретроаппаратов, у которых не получаются снимки, несмотря на, казалось бы, все ухищрения - может быть, затвор старой камеры просто устал, и выдает вместо 1/250 1/100, например. Благодарю и желаю всех благ!

Шустрый_Пацак, ку! 🍻😊

Ку, плюкане! Всем пол-КЦ, и чатлов горсть.
Итак, позвольте поделиться опытом использования этой гравицаппы. Собственно, собрав по чертежам и схемам Lead Pepelats сей агрегат, я взялся тут же починять старинный Зенит-С, со шторно-щелевым затвором, если верить номеру, 1958 года выпуска, видел еще пятерых предыдущих ПЖ. Неисправность стандартная - тормозящие шторы и смазка как гудрон. Первично прогнал скорости тестером - естественно, ни одна выдержка правильно не работала. После ремонта, юстировки по всем правилам, снова прогоняю тест - и, о удивление, снова мимо, по показаниям, затвор не стал быстрее. Проверил тестер на осциллографе - нет, совпадают показания длины импульса и подсчета прибора. Перебирал затвор я раз пять, затянул пружины штор так, что они как гильотина щелкали - нет, не могу загнать выдержки в диапазон даже приблизительно. Подумал, что все, последний выдох Зенита.
И вот, опосля размышлений о своей криворукости пришла такая мысль - ведь одно дело, просто светить стробом в датчик, другое - когда пролетающая мимо него щель затвора открывает источник света. На 1/500 щель шириной 3.5 мм, а фототранзистор - 5 мм, и у него есть линза. А у линзы есть угол обзора, и он еще шире, чем диаметр корпуса. Сам же фототранзистор имеет размеры 0.5х0.5 мм. И получается, что фронт импульса совпадает с открытием источника света первой шторкой на краю поля зрения линзы, а срез импульса - когда вторая шторка покидает противоположный край этого поля. То есть, фотоэлемент видит свет дольше, чем скажем, точка на пленке. И если ограничить поле зрения датчика, точность должна вырасти.
Собрал стенд для проверки выкладок теории: сам тестер, осциллограф, проверяемую камеру и осветитель. И, удивительно - так и вышло. На выдержке 1/250 "голый" датчик показывал 7,9 мс, 1/126, а датчик с маской - отверстие 2 мм. - 4,6 мс., 1/216. Погрешность около 58%, весьма немало. Форма импульса так же, заметно отличалась, фронт и срез импульса с маской резче и четче.
Прошу суждений, я не электронщик, профильного образования нет, одни догадки и катание на цурлаппе интуиции по пескам опыта.


Надо будет тоже с маской поэкспериментировать 🤔.

Была мысль спилить линзу, отполировать спил плоскостью, но подумал, что не сумею сделать хорошо, потому сделал проще, смоделил-распечатал корпус для датчика и маску. Корпус как раз вставляется в кадровое окно, фиксировать можно хоть кусочком изоленты, вот так выглядит весь этот набор. stl могу поделиться, если есть необходимость:)

Шустрый_Пацак, stl-ка может кому пригодится 😊.

Ку, плюкане!
Итак, вот окончательный вариант держалки для датчика (*.stl файл):
https://disk.yandex.ru/d/FfDm9ILttRTn1w
Состоит из трех частей, склеивается после печати в одно целое, для датчика в круглом корпусе 5 мм. Высоту конуса уменьшил, приблизив фотоэлемент к плоскости кадрового окна, теоретически, должно еще уменьшить ошибку. Материал - любой, хоть PETG, хоть PLA, черного цвета желательно. Я печатал PETG, сопло 0.4, температура экструдера 230*С, стола 70*С, заполнение 100%, высота слоя 0.2 мм.

Шустрый_Пацак, спасибо! Я могу выкачать с яндеха и прикрепить вашу STL-ку к статье? Чтобы не потерялась 😊.

Да, конечно, пусть будет! 😃 Дойдут руки смоделить корпус, и будет вообще полный комплект😃

По корпусу Mike Tanen уже провёл работу, рекомендую (есть ссылка на thingiverse.com в комментах выше) 😊.

Здравствуйте.
Появилась необходимость собрать данное устройство, но в программировании мало что понимаю...
НА первом скетче все работает. А на втором (цифровом) выдает ошибки при компиляции.
C:\Users\PC\AppData\Local\arduino\sketches\FE0DB024A155DFBB7E22FDE61E1C3873\libraries\Adafruit_GFX_Library\Adafruit_GFX.cpp.o (symbol from plugin): In function `Adafruit_GFX::writeLine(int, int, int, int, unsigned int)':
(.text+0x0): multiple definition of `Adafruit_GFX::drawFastVLine(int, int, int, unsigned int)'
все ошибки в прикрепленном файле
подскажите куда двигаться

На всякий случай сейчас проверил: прямо из статьи скопировал код скетча с аппаратн. прерываниями (который второй скетч) и попробовал его скомпилить - нормально скомпилилось без ошибок.
Вы библиотеки Adafruit_GFX и Adafruit_SSD1306 у себя поставили же? Я компилю и заливаю прошивки в ардуинку смартфоном при помощи программки ArduinoDroid, и у меня вот такие версии Адафрута установлены (см. картинку).

Как вариант, могу скомпилированный HEX-файл к статье прикрепить 😄. Нужно кому? Погуглите как его запихать в Ардуинку?

Если не сложно ,то прикрепите пожалуйста файл. собрал пока на аналоговом входе, проверил любитель и яшику,на яшике после 1/500 каша, хочу еще киев 88 проверить ну и на яшике выдержки до1/2000. заранее спасибо.

Приложил файл sst_interrupt.cpp.hex. Отпишитесь тогда получилось ли залить

Спасибо. Попробовали скопировать второй код еще раз и все получилось. Программа, Arduino IDE, скачала себе какое то обновление 😄
- 2
- 1