Hello everyone, apologies for the delayed responses.
After a lot of testing, here are some updates.
Let’s start with what I have available at home, without the need to buy anything else or wait 10 days to get additional parts.
I have an ESP32 S3 and a handful of Arduino Nanos.
As for sensors, here’s what I have:
- A pair of IR sender and receiver, without a brand or specifications.
- Some IR LEDs and photodiodes, also without a brand and therefore no datasheet.
- A few visible light photodiodes, no brand.
- An ISO203 photodiode with AMP (more info here: Documents about laser sensor DS18B20 - #5 by ruilviana)
- A TEMT6000 phototransistor https://www.vishay.com/docs/81579/temt6000.pdf
Cameras: all focal plane shutter, except the Olympus
- Canon EOS 300V (the reference one)
- Canon EOS 33V
- Konica T3N
- Konica T4
- Konica FT-1
- Konica TC
- Olympus RC35 (leaf shutter)
- Minolta 7000
Setup:
- I used the photodiodes (both IR and visible light) with a 10k resistor and read them using
analogRead, on both Arduino and ESP32. For the IR, I placed an IR emitter diode on the opposite side of the lens, and for visible light, I used a simple LED flashlight. - I tested the sender and receiver pair in digital mode, modulating the sender at 38 kHz with another Arduino and reading the receiver with the ESP32 (which is faster than Arduino for digital reads).
- Finally, I connected the TEMT6000 (since it's on a breakout board) to 5V and read the output using
analogReadon the ESP32.
Findings:
- Regardless of the solution or code implementation (whether using
analogReaddirectly or analyzing the high/low states of the digital pin), I was never able to get reliable readings faster than 1/125s: the readings increase, but with progressively larger errors (for example, 1/500 is read as 1/300, and 1/1000 as slightly over 1/500). - I’m confident in the accuracy of one of my cameras, as it is new (with fewer than 2000 shots, maybe 2500 after all this testing
) and of the latest generation, with a shutter controlled by a microprocessor. - The ISO203 sensor, which paradoxically has the potential for the fastest reading based on its datasheet, is the only one I couldn’t get to work reliably. I believe it’s due to the breakout board it’s mounted on, though I didn’t try connecting it directly to the Arduino with the proper resistors (honestly, after days of testing, I lost the motivation to do so).
- I can’t say for sure if using the photodiode suggested in one project (NJL7502L) would give reliable readings, but honestly, it costs about 15 euros in Germany, and I’m not eager to spend more money. There are alternative sensors suggested, like those from OSRAM, but the minimum order quantity is 10 pieces, and I really don’t feel like making another purchase.
Possible Conclusions:
- None of my sensors are fast enough to read the correct times: according to the datasheets, I should be able to get reliable readings at least up to 1/500 at least with the TEMT6000, but that's not the case.
OR - Due to the measurement method using flash sync and the movement of the shutter blades, it is impossible to measure reliably beyond the flash sync speed, which is 1/125 (this is still unclear to me, as many projects claim precision up to 1/1000).
How I Concluded:
In the end, I built a small circuit using the TEMT6000 and ESP32-S3, which gives me the same accuracy as the other methods I tried but it is at least more practical: very good up to 1/125s, with necessary compensation for faster shutter speeds, but repeatable and consistent. With a shutter speed of 1/1000 over 10 measurements, I get errors of about 1/150, which is acceptable for my needs.
Ultimately, I just needed an estimate of how my cameras perform to know if I need to compensate when shooting, and the accuracy is good enough for my purposes. I calibrated the software compensation on my reference camera and found that some of my other cameras are pretty close, while others are quite far off (some are even half the indicated shutter speed), so I’m satisfied overall.
Here are some photos of the device (I used a Kallax L plastic piece from Ikea as the structure
).
And here's the code:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "esp_timer.h"
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_SDA 2
#define OLED_SCL 1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
#define TEMT6000_PIN 8
volatile uint32_t shutterSpeed = 0;
TaskHandle_t displayTaskHandle;
static bool measuring = false;
const int LIGHT_THRESHOLD = 1000;
int lastLightLevel = 0;
void IRAM_ATTR checkLightChange() {
int lightLevel = analogRead(TEMT6000_PIN);
if (!measuring && lightLevel > LIGHT_THRESHOLD && lastLightLevel <= LIGHT_THRESHOLD) {
shutterSpeed = esp_timer_get_time();
measuring = true;
}
else if (measuring && lightLevel <= LIGHT_THRESHOLD && lastLightLevel > LIGHT_THRESHOLD) {
shutterSpeed = esp_timer_get_time() - shutterSpeed;
measuring = false;
xTaskNotifyGive(displayTaskHandle);
}
lastLightLevel = lightLevel;
}
void displayTask(void *pvParameters) {
while (true) {
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
display.clearDisplay();
display.setCursor(0, 5);
display.println("Shutter Speed Tester");
display.setCursor(15, 25);
display.println("Shutter Speed:");
display.setCursor(20, 40);
display.print(shutterSpeed);
display.println(" us");
float speedFraction = 1000000.0 / shutterSpeed;
float correctionFactor = (speedFraction < 125) ? 1.0 :
(speedFraction <= 250) ? 1.04 :
(speedFraction <= 500) ? 1.12 :
(speedFraction <= 1000) ? 1.3 :
(speedFraction <= 2000) ? 1.5 : 1.7;
display.setCursor(20, 50);
display.print("1/");
display.print((int)(speedFraction * correctionFactor));
display.display();
vTaskDelay(5000 / portTICK_PERIOD_MS);
display.clearDisplay();
display.setCursor(0, 5);
display.println("Shutter Speed Tester");
display.setCursor(50, 25);
display.println("READY");
display.display();
}
}
void setup() {
pinMode(TEMT6000_PIN, INPUT);
Wire.begin(OLED_SDA, OLED_SCL);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (true);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 5);
display.println("Shutter Speed Tester");
display.setCursor(50, 25);
display.println("READY");
display.display();
xTaskCreatePinnedToCore(displayTask, "DisplayTask", 4096, NULL, 1, &displayTaskHandle, 0);
}
void loop() {
checkLightChange();
}
Let me know if you have ideas or comments ![]()

