[144] Arduino mierzy czasy migawek aparatów klasycznych cz. 2

[144] Arduino mierzy czasy migawek aparatów klasycznych cz. 2

Zbudowany w poprzednim artykule miernik czasu otwarcia migawki już działa, ale wyświetla wyniki w mikrosekundach. W fotografii przyjęło się używać innego formatu: części sekundy, upraszczając często prezentację do samego mianownika. Przeróbmy więc nieco nasz program, a raczej dopiszmy jeszcze kilka linii.


volatile unsigned long openingMoment = 0;  // Moment otwarcia migawki.
volatile unsigned long closingMoment = 0;  // Moment zamknięcia migawki.
volatile bool isMeasuring = false;         // Flaga - ustawiona, jeśli trwa pomiar.
const byte phototransistorPort = 2;        // Adres portu fototranzystora (2 albo 3)

void setup() {
  pinMode(phototransistorPort, INPUT);                                             // Deklaruj port fototranzystora jako wejście.
  Serial.begin(115200);                                                            // Inicjuj port monitora.
  attachInterrupt(digitalPinToInterrupt(phototransistorPort), interrupt, CHANGE);  // Włącz przerwania z portu fototranzystora.
}
void loop() {
  if (closingMoment > 0) {                                       // Jeśli pomiar jest zakończony...
    unsigned long exposureTime = closingMoment - openingMoment;  // Policz czas migawki.
    float shutter = 1000000.0 / exposureTime;                    // Policz czas migawki w formie fotograficznej.
    Serial.print(exposureTime);                                  // Wyświetl czas migawki.
    Serial.print(" µs (");                                       // Wyświetl napis.
    if (exposureTime < 1000000UL) {                              // Jeśli czasy migawki są krótsze od sekundy...
      Serial.print("1/");                                        // Wyświetl napis.
      Serial.print(shutter, 0);                                  // Wyświetl czas migawki w formie fotograficznej.
    } else {                                                     // Jeśli są równe lub dłuższe...
      float seconds = exposureTime / 1000000.0;                  // Załaduj do zmiennej seconds wartość mikrosekund dzieloną przez milion.
      Serial.print(seconds, 3);                                  // Wyświetl sekundy z trzema miejscami po przecinku.
    }
    Serial.println(" s)");  // Wyświetl napis.
    closingMoment = 0;      // Wyzeruj licznik dla kolejnego pomiaru.
  }
}
void interrupt() {
  if (digitalRead(phototransistorPort) == LOW) {  // Jeśli migawka została otwarta...
    if (!isMeasuring) {                           // Jeśli nie było mierzenia...
      openingMoment = micros();                   // Wpisz stan micros do zmiennej momentu otwarcia migawki.
      isMeasuring = true;                         // Włącz flagę mierzenia.
    }
  } else {                       // Jeśli migawka została zamknięta...
    if (isMeasuring) {           // Jeśli było mierzenie...
      closingMoment = micros();  // Wpisz stan micros do zmiennej momentu zamknięcia migawki.
      isMeasuring = false;       // Wyłącz flagę mierzenia.
    }
  }
}

Ten szkic różni się dodatkową operacją, zamieniającą czas w mikrosekundach na typowe wartości fotograficzne. A więc w przypadku czasów dłuższych od sekundy, dzielimy wyniki przez milion i mamy czas w sekundach, wraz z trzema miejscami po przecinku. Dla krótszych czasów znowu mamy formę jeden łamane przez – i tu odpowiednia cyfra. Takie wartości znajdziemy na kołach czasów w aparatach. Mają one jednak pewną wadę: im bliżej sekundy, tym większe przybliżenie tu widzimy. Nie ma to aż takiego znaczenia, ponieważ film traktuje światło wykładniczo i dla samego procesu powstawania obrazu nie jest ważne, czy naświetlanie trwało jedną sekundę, czy jedną i jedną dziesiątą. Lecz dla ukazania powtarzalności wyników pozostawiłem równoległe wyświetlanie wartości w mikrosekundach.

Przypatrzmy się serii odczytów. Zacznę od Pentaxa K1000. To urządzenie czysto mechaniczne, a to co otrzymałem jest piękne: Owszem, są pewne różnice względem deklarowanych, ale nie przekraczają kilku procent. Śmiało możemy brać ten aparat w plener.

Popularna Smiena także jest aparatem mechanicznym, ale tutaj jest kiepsko. Zamiast 1/15 mamy 1/22, potem błędy są mniejsze, ale w przypadku 1/125 wychodzi 1/80, a ostatni czas – 1/250 to niecała 1/200 Z powtarzalnością również nie jest wesoło, dlatego przedstawiłem po trzy pomiary.

Nikon FG20 jest mam mechaniczną migawkę wyzwalaną za pomocą elektroniki, więc czasy powinny być zgodne z deklarowanymi. I zgadza się – mniej więcej, widać że mechanizm dodaje nieco opóźnień. W rezultacie 1/1000 to tak naprawdę 1/750. Po jakimś czasie zastany mechanizm się rozruszał i najszybsza migawka przysunęła się do deklarowanej. Dlatego warto przed użyciem takich aparatów zrobić kilka tak zwanych ślepych zdjęć na różnych czasach.

Na koniec Canon 500N. Najmłodszy, w pełni elektroniczny, powinien trzymać czasy idealnie. Niestety tu także mechanika się zestarzała i od 1/250 mamy coraz większe opóźnienie migawki. Przy ostatnim czasie: 1/2000 wyciąga tylko 1/1250.

Jak więc widać, nie zawsze wyniki odpowiadają deklaracjom i gdy różnice zbliżają się do 1 EV, konsekwencje mogą być już widoczne wyraźnie. Ważniejsze jednak jest to, że możemy w ten sposób zdiagnozować migawki uszkodzone. A skoro mamy tu płytkę z wyświetlaczem, uwolnijmy pomiary od obecności komputera i przerzućmy odczyty na lokalny LCD.

#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze HD44780
#include <d44780ioClass/hd44780_I2Cexp.h>                              // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD

volatile unsigned long openingMoment = 0;  // Moment otwarcia migawki.
volatile unsigned long closingMoment = 0;  // Moment zamknięcia migawki.
volatile bool isMeasuring = false;         // Flaga - ustawiona, jeśli trwa pomiar.
const byte phototransistorPort = 2;        // Adres portu fototranzystora (2 albo 3)

void setup() {
  pinMode(phototransistorPort, INPUT);                                             // Deklaruj port fototranzystora jako wejście.
  lcd.begin(16, 2);                                                                // Inicjuj wyświetlacz LCD
  lcd.setCursor(0, 0);                                                             // Ustaw kursor.
  lcd.print("Waiting...");                                                         // Wyświetl napis.
  lcd.setCursor(0, 1);                                                             // Ustaw kursor.
  attachInterrupt(digitalPinToInterrupt(phototransistorPort), interrupt, CHANGE);  // Włącz przerwania z portu fototranzystora.
}
void loop() {
  if (closingMoment > 0) {                                       // Jeśli pomiar jest zakończony...
    unsigned long exposureTime = closingMoment - openingMoment;  // Policz czas migawki.
    float shutter = 1000000.0 / exposureTime;                    // Policz czas migawki w formie fotograficznej.
    lcd.setCursor(0, 1);                                         // Ustaw kursor.
    lcd.print(exposureTime);                                     // Wyświetl czas migawki.
    lcd.print(" us            ");                                // Wyświetl napis.
    lcd.setCursor(0, 0);                                         // Ustaw kursor.
    lcd.print("Shutter: ");                                      // Wyświetl napis.
    if (exposureTime < 1000000UL) {                              // Jeśli czasy migawki są krótsze od sekundy...
      lcd.print("1/");                                           // Wyświetl napis.
      lcd.print(shutter, 0);                                     // Wyświetl czas migawki w formie fotograficznej.
    } else {                                                     // Jeśli są równe lub dłuższe...
      float seconds = exposureTime / 1000000.0;                  // Załaduj do zmiennej seconds wartość mikrosekund dzieloną przez milion.
      lcd.print(seconds, 3);                                     // Wyświetl sekundy z trzema miejscami po przecinku.
    }
    lcd.print(" s    )");  // Wyświetl napis.
    closingMoment = 0;     // Wyzeruj licznik dla kolejnego pomiaru.
  }
}
void interrupt() {
  if (digitalRead(phototransistorPort) == LOW) {  // Jeśli shutter została otwarta...
    if (!isMeasuring) {                           // Jeśli nie było mierzenia...
      openingMoment = micros();                   // Wpisz stan micros do zmiennej momentu otwarcia migawki.
      isMeasuring = true;                         // Włącz flagę mierzenia.
    }
  } else {                       // Jeśli shutter została zamknięta...
    if (isMeasuring) {           // Jeśli było mierzenie...
      closingMoment = micros();  // Wpisz stan micros do zmiennej momentu zamknięcia migawki.
      isMeasuring = false;       // Wyłącz flagę mierzenia.
    }
  }
}

Szkic nie będzie się różnił ideą, natomiast dojdzie tu obsługa wyświetlacza na układzie HD44780 sterowanego przez ekspander I2C. Ten układ wystąpił u mnie już wielokrotnie, więc tylko wspomnę o koniecznych bibliotekach i deklaracjach oraz sformatowaniu danych w ten sposób, by na górnym wierszu ukazywał się wynik w postaci fotograficznej, a na dole – w mikrosekundach. Teraz już możemy testować aparaty z dala od komputera.

Dwie uwagi na koniec. Dokładność teoretyczna to 4 uS, co jest ogromnym zapasem nawet dla migawek 1/8000, które otwierają lamelki na 125 uS. Jednakże funkcja digitalRead() wprowadza dodatkowe 5 uS. Gdybyśmy potrzebowali większej dokładności, na przykład do pomiaru lamp błyskowych, należałoby adresować port bezpośrednio. No i druga ciekawostka, na którą musimy uważać. Latarka, której użyłem do doświadczeń mia dwa biegi: na pełnej mocy świeci światłem ciągłym, ale na połowie – jest kluczowana, co nasze urządzenie wykryje jako stroboskop, serwując cały ciąg wyników, fałszujący to, na co czekamy. Dlatego należy używać świateł zasilanych prądem stałym, które nie dadzą takich efektów.

Teoretycznie to już koniec, ale wpadł mi do rąk taki wyświetlacz i okazał się on bardzo wygodny w produkcji różnych urządzeń, dlatego w kolejnym artykule raz jeszcze powrócimy do pomiaru migawki.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2026 arduino.pl