Свинцовый Пепелац

Блог / Собираем устройство для проверки длительности выдержек затворов аналоговых фотоаппаратов

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 сек. и короче. Что же, давайте проанализируем факторы, которые могут влиять на точность рассмотренного прибора.

  1. Инерционность фототранзистора. Как я указал выше, у фототранзистора который использовал я, и время нарастания, и время спада равны 15 мкс. Если я всё правильно понял, эти параметры характеризуют инерционность реакции фототранзистора при попадании на него света и при его снятии. Т.е., о том что на него начал попадать свет, фототранзистор в полной мере «поймёт» в худшем случае с задержкой на 15 мкс, и с такой же задержкой «узнает» о том, что свет на него попадать перестал. Таким образом, получается взаимная компенсация и выходит что эти параметры не оказывают влияния на точность прибора. Если мои рассуждения неверны, поправьте меня в комментариях.
  2. Частота дискретизации. Немного поколдовав над скриптом, я замерил время которое уходит на одну итерацию в цикле запущенном на моём контроллере, и у меня получилось значение 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 г.)

Когда я узнал что микроконтроллеры Ардуино поддерживают аппаратные прерывания, у меня появилась идея как можно усовершенствовать свой гаджет, повысив скорость его реакции, а, следовательно, его точность. Конечно же, в первую очередь это критично для коротких выдержек (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.

Прикреплённые файлы:

  • FT_holder_with_mask.stl

    Держатель для датчика от пользователя «Шустрый_Пацак» ( см. https://lead-pepelats.ru/blog/device-for-checking-value-of-camera-shutter-speed/?msg=7898#p.msgs7898 ).

    Состоит из трех частей, склеивается после печати в одно целое, для датчика в круглом корпусе 5 мм.

    Материал любой, хоть PETG, хоть PLA, черного цвета желательно. Протестировано на PETG, сопло 0.4, температура экструдера 230°С, стола 70°С, заполнение 100%, высота слоя 0.2 мм.
    Дата публикации: 25 фев. 2025
    Расширение: STL
    Размер файла: 43.83 КБ
    Сканиваний: 11
  • sst_interrupt.cpp.hex

    HEX-файл прошивки тестера затворов аналоговых фотоаппаратов (версия с аппаратными прерываниями).
    Дата публикации: 13 апр. 2025
    Расширение: HEX
    Размер файла: 54.44 КБ
    Сканиваний: 21

Поддержать проект «Свинцовый Пепелац»:

Вы можете поддержать проект «Свинцовый Пепелац» финансово, переведя в его пользу любую сумму (от 1 руб.)

Комментарии посетителей (58):

Знаменский23
2 августа 2025 20:38
По возможности сделайте скетч на русском. Я ведь вообще древний. Для меня вражеские буквы это проблема.
2 августа 2025 20:52
Сделаю, только мгновенно у меня это не получиться, т.к. я всё это дело крутил-вертел и компилил на старом своём смартфоне, который перед новым годом почил в бозе 😵, так что придётся немного вспомнить что я там как делал 😊. Но уверен, что всё получиться 💪.

P.S. — мне на родном языке тоже как-то приятнее 😊.
2 августа 2025 21:26
Знаменский23, маленькая поправка: скетч с русским языком сам по себе нормально не скомпилится (скорее всего крокозяблы вместо русских букв будут), т.к. у библиотеки Adafruit-GFX, нет поддержки кириллицы (ведь нет же ещё?). Так что я только могу HEX-файл скомпиленный приложить к статье (когда сделаю его). А если вы прямо сами хотите из скетча своего компилить с кириллицей, я в статье оставил ссылку на рецепт как это сделать (статья «Русификация библиотеки Adafruit-GFX и вывод русских букв на дисплей в кодировке UTF-8 из Arduino IDE»).
Знаменский23
2 августа 2025 21:31
Я вот о чем чтобы как у вас слово "выдержка" было на русском.... Вообщем для древний и от этого могу говорить наивные преставления.
2 августа 2025 21:49
Короче, вы там пока тогда схемой занимайтесь (или уже собрали?), а там разберёмся 😊. Как залить прошивку в контроллер вы разобрались же? Если да, то дальше дело за малым 😊.
Знаменский23
2 августа 2025 22:39
Купил на маркетплейсе всё за раз. Жду. Ну а пока, сидя на работе, подготавливаю теорию. У меня фотобарохла много. Тут на старости глядя на «Смена 8М» решил было я опять в плёнку вернуться. Купил средний формат: «Москва-5», «Искра», «Любитель-166У», «Киев-60» (вообще новым). И вот я тут понял, что затворы этих аппаратов давно щёлкают, так сказать, от балды. Взялся интернет шерстить, попал на ваш сайт. От радости запрыгал до потолка. Вот на днях приеду с вахты северной, открою сундук с аппаратами, соберу это устройство и... наверно, расстроюсь. Собрать эту машину я смогу, но вот мозги ей вставить может быть долгим и тернистым приключением. Заранее благодарю за спасибо за помощь. Я еще дам о себе знать.
2 августа 2025 22:49
Знаменский23, не переживайте, подскажем и поможем 😊. Если что, напишите мне с формы обратной связи ( https://lead-pepelats.ru/feedback/ ), перейдём в приватное общение чтобы тут не флудить 😊.
Знаменский23
13 августа 2025 07:05
Итак, мои познания закрепились. Сейчас не без сомнений однако основываясь на собственной наивности а следовательно и поэтому уверенности могу утверждать, что данное устройство измеряет выдержку возможно точно, но только до 1/499 секунды. А дальше видимо ее характеристики не предназначены. По крайней мере у меня так получается. Я экспериментировал с двумя фотоаппаратами, Киев 60, Zenit KM-plus. Первый со шторным механизмом, второй фотоаппарат имеет электромеханический привод так сказать ламельный. Измерения показали относительно правильные числа, но как только выдержка составила больше 1/499 устройство от выдает ошибку измерения.
13 августа 2025 07:31
Знаменский23, приветствую! Не очень понял что значит "устройство выдает ошибку измерения" 🤔.
Знаменский23
13 августа 2025 17:34
Возможно оно пишет, что-то другое, но я так понял. Вот что я увидел: скорость, точнее, болле короткую длительность чем 1/499 секунды оно измерить не способно технически. Это мое понимание. Не претендую на правильность моих представлений. Но это (!) не точно!
13 августа 2025 17:57
Знаменский23, короче так: для начала убедитесь что источник света (фонарик), который вы используете при измерениях, светит без пульсаций (диодные фонарики этим часто грешат). Прибор весьма чувствителен (в плане реакции) и в случае пульсирующего источника света может реагировать не на работу затвора, а на пульсации этого самого источника света ☝️.

Уточню: Вы таки смогли успешно залить скетч или HEX-файл в своего терминатора? Если да, то это очень круто 👍.

Далее: там вроде на экране всё достаточно просто-понятно пишется, но если Вы чего-то не понимаете из отображённого на экране девайса, то просто задайте вопрос в комментах приложив фото экрана тестера — подскажем и объясним 😊.
Знаменский23
13 августа 2025 20:41
Спасибо, вам большое, действительно квест по установки скетч(а) я прошел, не первого раза. Спасибо вам. Действительно, я использовал диодный фонарь, я осознаю, что фонарь может работать с частотой. Однако я всё же пренебрег, рассчитывая на русское авось. И вот что мне удалось увидеть. На двух фотоаппаратах Киев60 89г.в. и Зенит КМ+ 2005 г.в. выдержки до 1/500 показывали красивые цифры. Например Киев60 показывал на 1/30 разброс 1/24-1/37, и такие разбросы были почти на всех установках. На 1/500 показывал 1/437-1/499 и иногда устройство матюкалось. И всегда матюкалось на выдержках 1/1000. Так же показал себя и Зенит КМ+, правда разброс сжался значительно. Но на выдержке 1/500 показывал либо меньше 1/500 либо выдавал нецензурную брань. И вот на выдержке 1/1000 перешел на простое ругательство, но цифр уже не показывал. Поэтому я сделал не сложный вывод, что ардуино наше с данным скетчем или фототранзистор не могут просчитать время всплеска которое меньше 1/500. Завтра если будет желание я проверю его еще на одном фотоаппарате.
ade
5 сентября 2025 23:21
Здравствуйте, решил собрать ваш девайс и не могу понять в чём причина неисправности. Не хочет выводить данные на экран пока не конснусь пальцами GND и D2 при чем касаясь диэлектриком ничего не происходит. Но стоит замкнуть пальцем или грифелем карандаша эти контакты как он выдаёт все данные.
6 сентября 2025 09:18
ade, приветствую!
Так, конечно, сложно сказать, но, скорее всего, тут либо неконтакт где-то (если вы как и я на беспаечной плате собирали, то это легко может быть), либо что-то вы напутали в соединениях. Надо все соединения перепроверить ещё раз, проверить «землю». Вы пишите: «Но стоит замкнуть пальцем или грифелем карандаша эти контакты как он выдаёт все данные» — а данные хоть адекватные? Это же может быть просто сигнал наводки. Нет?
Tuzemak
26 сентября 2025 13:14
Можно проще же и без бабуино. На голом C с выводом на USART.
26 сентября 2025 14:02
Tuzemak, ну если так как вы сказали проще, то подробнее опишите как сделать, обсудим при необходимости 🤷‍♂️.
Tuzemak
3 октября 2025 22:06
Накидал примерно. Схема та же остаётся за исключением экранчика, вывод идёт через UART.
https://gitlab.com/tuzemak/shutter-speed/-/blob/main/main.c
3 октября 2025 22:49
Tuzemak, прикольно 😊!
Я лично на настоящем C не пишу (как собака — понимаю более-менее что написано, но не говорю 😂), ну и надо понимать, что тут подавляющая часть читателей это, по понятный причинам, глубоко «аналоговые» человеки 😊, так что если бы вы всё доходчиво пояснили: куда что как подключать,... и т.д. и т.п. было бы просто замечательно! Я сам пока не до конца вашу идею понял, но что-то явно интересное 😊👍.
Tuzemak
4 октября 2025 14:11
Схема та же самая - фототранзистор к пину прерывания, дисплей из схемы исключен.
Вывод идёт в UART(в случае с бабуино этот UART распаян на USB переходнит FT232 на плате). Подключение через любую терминалку
- putty, minicom и.т.д. на скорости 9600 к порту, через который прошиватся бабуино. Если прошивается голый МК, то UART распаивается на тот же DB-9.
Прошивка заводит внутренний таймер микроконтроллера на счет интервалов и ведёт счет общего uptime работы.
Внешнее прерывание сконфигурировано на срабатывание по изменению уровня. Обработчик прерывания фиксирует время срабатывания относительно uptime, счетчик четности определяет фиксирует момент открытия/закрытия шторки.
На выход выдаётся выдержка в миллисекундах и в долях секунды(насколько гуляет ).
Прошивка с рядом косяков, но в общих чертах работает.
4 октября 2025 15:11
Tuzemak, 👏👏👏! Спасибо 🤝!

Написать комментарий:


Максимальный размер файла загружаемого изображения 10 МБ