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

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

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.

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

19 февраля 2024 08:04
Попробовал запитаться от одной 9-вольтовой «Кроны» (через пин «VIN») — без проблем получилось. Теперь стендик стал немного компактнее 😊.
Wintercore bimbo
24 февраля 2024 09:39
Сам несколько недель думал о таком приборчике. Видимо, ты считал проекцию моих мыслей из ноосферы. Но я хотел сделать еще проще: светодиод, фотодиод, микрофонный вход звуковой карты, любая программа для звукозаписи
24 февраля 2024 09:47
Wintercore bimbo, тут просто меня радует то, что это достаточно маленький и при этом полностью автономный приборчик получился 😊. А для твоего варианта придётся комп с собой таскать, как я понял. Хотя, это конечно нынче тоже не особо проблема 😄.
8 марта 2024 15:30
Тут некоторые люди высказывают мне своё «фи» на тему того, что, мол, нужно было этот гаджет оформить в виде полноценного устройства (в корпусе), а не как у меня, в виде простого испытательного стенда. Ну и у меня в этой связи к таким умникам вопрос: а зачем это делать? Вот я проверил на этом своём стенде все свои камеры (см. https://lead-pepelats.ru/blog/results-of-speeds-shutters-measurements-of-my-cameras/ ), и что дальше? Я потрачу массу времени на разработку для этого приборчика удобного и компактного корпуса, его печать на 3D-принтере, и п.д. и т.п., для того чтобы он просто валялся без дела? Какой в этом смысл? Я просто его теперь разберу, а освободившие детали послужат в других моих Arduino-проектах (благо идеи таких проектов у меня имеются). В конце концов, если он мне снова понадобится, то я просто снова его соберу — готовые схема и скетч теперь имеются. Такие дела, критики 😜.

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


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