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

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

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 г.)

Когда я узнал что микроконтроллеры 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.

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

  • 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 КБ
    Сканиваний: 2
  • sst_interrupt.cpp.hex

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

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

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

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

Cy_prus
6 июня 2024 07:56
Я бы добавил, что нужно брать плату с процессором Atmega 328P, а не с Atmega 168P, так как в последнем не хватит памяти для второй версии кода.
6 июня 2024 08:47
Да, но можно попробовать вместо библиотеки Adafruit использовать что-нибудь более компактное, например GyverOLED (она, кстати, сразу с кириллицей идёт 😊).
Шустрый_Пацак
23 января 2025 18:17
Три раза "ку" и десяток КЦ для тебя, о достойнейший. Ты предвосхитил все ТТХ, которые я мыслил в подобном приборе - простота, приемлемая точность и доступность комплектующих. Я повторил твою конструкцию, после ремонта нескольких старых камер была необходимость точно знать, что именно отрабатывают затворы, которым по 30-40 лет. И прибор пришелся очень кстати, в настройке/регулировке вещь незаменимая. Заодно посоветовал бы такой прибор пленочникам-любителям ретроаппаратов, у которых не получаются снимки, несмотря на, казалось бы, все ухищрения - может быть, затвор старой камеры просто устал, и выдает вместо 1/250 1/100, например. Благодарю и желаю всех благ!
23 января 2025 18:42
Шустрый_Пацак, ку! 🍻😊
Шустрый_Пацак
12 февраля 2025 19:19
Ку, плюкане! Всем пол-КЦ, и чатлов горсть.

Итак, позвольте поделиться опытом использования этой гравицаппы. Собственно, собрав по чертежам и схемам Lead Pepelats сей агрегат, я взялся тут же починять старинный Зенит-С, со шторно-щелевым затвором, если верить номеру, 1958 года выпуска, видел еще пятерых предыдущих ПЖ. Неисправность стандартная - тормозящие шторы и смазка как гудрон. Первично прогнал скорости тестером - естественно, ни одна выдержка правильно не работала. После ремонта, юстировки по всем правилам, снова прогоняю тест - и, о удивление, снова мимо, по показаниям, затвор не стал быстрее. Проверил тестер на осциллографе - нет, совпадают показания длины импульса и подсчета прибора. Перебирал затвор я раз пять, затянул пружины штор так, что они как гильотина щелкали - нет, не могу загнать выдержки в диапазон даже приблизительно. Подумал, что все, последний выдох Зенита.

И вот, опосля размышлений о своей криворукости пришла такая мысль - ведь одно дело, просто светить стробом в датчик, другое - когда пролетающая мимо него щель затвора открывает источник света. На 1/500 щель шириной 3.5 мм, а фототранзистор - 5 мм, и у него есть линза. А у линзы есть угол обзора, и он еще шире, чем диаметр корпуса. Сам же фототранзистор имеет размеры 0.5х0.5 мм. И получается, что фронт импульса совпадает с открытием источника света первой шторкой на краю поля зрения линзы, а срез импульса - когда вторая шторка покидает противоположный край этого поля. То есть, фотоэлемент видит свет дольше, чем скажем, точка на пленке. И если ограничить поле зрения датчика, точность должна вырасти.

Собрал стенд для проверки выкладок теории: сам тестер, осциллограф, проверяемую камеру и осветитель. И, удивительно - так и вышло. На выдержке 1/250 "голый" датчик показывал 7,9 мс, 1/126, а датчик с маской - отверстие 2 мм. - 4,6 мс., 1/216. Погрешность около 58%, весьма немало. Форма импульса так же, заметно отличалась, фронт и срез импульса с маской резче и четче.

Прошу суждений, я не электронщик, профильного образования нет, одни догадки и катание на цурлаппе интуиции по пескам опыта.
Шустрый_Пацак
12 февраля 2025 19:21
Вот осциллограммы: слева датчик без маски, справа с маской.
12 февраля 2025 20:53
Шустрый_Пацак, 🔥🔥🔥. Всё супер расписали, и за осциллограммы спасибище - интересно посмотреть 😊. Единственное только добавлю, что у меня есть фототранзисторы без линзы - у него вместо линзы ровная поверхность (см. фото).
12 февраля 2025 21:15
Надо будет тоже с маской поэкспериментировать 🤔.
Шустрый_Пацак
13 февраля 2025 02:25
Была мысль спилить линзу, отполировать спил плоскостью, но подумал, что не сумею сделать хорошо, потому сделал проще, смоделил-распечатал корпус для датчика и маску. Корпус как раз вставляется в кадровое окно, фиксировать можно хоть кусочком изоленты, вот так выглядит весь этот набор. stl могу поделиться, если есть необходимость:)
13 февраля 2025 06:35
Шустрый_Пацак, stl-ка может кому пригодится 😊.
Шустрый_Пацак
15 февраля 2025 14:33
Ку, плюкане!

Итак, вот окончательный вариант держалки для датчика (*.stl файл):

https://disk.yandex.ru/d/FfDm9ILttRTn1w

Состоит из трех частей, склеивается после печати в одно целое, для датчика в круглом корпусе 5 мм. Высоту конуса уменьшил, приблизив фотоэлемент к плоскости кадрового окна, теоретически, должно еще уменьшить ошибку. Материал - любой, хоть PETG, хоть PLA, черного цвета желательно. Я печатал PETG, сопло 0.4, температура экструдера 230*С, стола 70*С, заполнение 100%, высота слоя 0.2 мм.
15 февраля 2025 16:50
Шустрый_Пацак, спасибо! Я могу выкачать с яндеха и прикрепить вашу STL-ку к статье? Чтобы не потерялась 😊.
Шустрый_Пацак
15 февраля 2025 16:54
Да, конечно, пусть будет! 😃 Дойдут руки смоделить корпус, и будет вообще полный комплект😃
15 февраля 2025 17:27
По корпусу Mike Tanen уже провёл работу, рекомендую (есть ссылка на thingiverse.com в комментах выше) 😊.
Аноним
13 апреля 2025 20:04
Здравствуйте.
Появилась необходимость собрать данное устройство, но в программировании мало что понимаю...
НА первом скетче все работает. А на втором (цифровом) выдает ошибки при компиляции.
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)'
все ошибки в прикрепленном файле
подскажите куда двигаться
13 апреля 2025 21:51
На всякий случай сейчас проверил: прямо из статьи скопировал код скетча с аппаратн. прерываниями (который второй скетч) и попробовал его скомпилить - нормально скомпилилось без ошибок.

Вы библиотеки Adafruit_GFX и Adafruit_SSD1306 у себя поставили же? Я компилю и заливаю прошивки в ардуинку смартфоном при помощи программки ArduinoDroid, и у меня вот такие версии Адафрута установлены (см. картинку).
13 апреля 2025 22:03
Как вариант, могу скомпилированный HEX-файл к статье прикрепить 😄. Нужно кому? Погуглите как его запихать в Ардуинку?
Аноним
13 апреля 2025 22:54
Если не сложно ,то прикрепите пожалуйста файл. собрал пока на аналоговом входе, проверил любитель и яшику,на яшике после 1/500 каша, хочу еще киев 88 проверить ну и на яшике выдержки до1/2000. заранее спасибо.
13 апреля 2025 23:08
Приложил файл sst_interrupt.cpp.hex. Отпишитесь тогда получилось ли залить
Аноним
14 апреля 2025 20:23
Спасибо. Попробовали скопировать второй код еще раз и все получилось. Программа, Arduino IDE, скачала себе какое то обновление 😄

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


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