{"id":19838696,"url":"https://github.com/brayvid/shutter-controller","last_synced_at":"2026-05-12T11:39:00.939Z","repository":{"id":233185070,"uuid":"178606295","full_name":"brayvid/shutter-controller","owner":"brayvid","description":"Arduino camera controller for custom timelapse capture.","archived":false,"fork":false,"pushed_at":"2024-06-23T21:21:10.000Z","size":35161,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-11T11:18:35.154Z","etag":null,"topics":["arduino","bulb-ramping","diy","filmmaking","photography","sunrise","sunset","timelapse"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brayvid.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-30T20:08:45.000Z","updated_at":"2024-07-27T18:02:33.000Z","dependencies_parsed_at":"2024-06-23T22:38:39.165Z","dependency_job_id":null,"html_url":"https://github.com/brayvid/shutter-controller","commit_stats":null,"previous_names":["brayvid/shutter-controller"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Fshutter-controller","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Fshutter-controller/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Fshutter-controller/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brayvid%2Fshutter-controller/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brayvid","download_url":"https://codeload.github.com/brayvid/shutter-controller/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241209528,"owners_count":19927734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","bulb-ramping","diy","filmmaking","photography","sunrise","sunset","timelapse"],"created_at":"2024-11-12T12:18:42.715Z","updated_at":"2026-05-12T11:39:00.934Z","avatar_url":"https://github.com/brayvid.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Arduino DSLR Shutter Controller\n\nThis project provides a complete hardware and software solution for capturing \"holy grail\" timelapses—such as sunrises or sunsets—where the ambient light changes dramatically. It uses an Arduino to programmatically control a DSLR's shutter, adjusting the exposure time with a non-linear curve to produce smooth, flicker-free results.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/prototype.jpg\" width=\"80%\"\u003e\n  \u003cp align=\"center\"\u003e\n   \u003cb\u003eThe final hardware:\u003c/b\u003e (1) Arduino, (2) Shutter release circuit, (3) 2.5mm TRS port adapter, (4) 2.5mm shutter cable, (5) Interface, (6) 7-segment display\n\u003c/p\u003e\n\u003c/p\u003e\n\n## The Problem: Exposure in a Changing Environment\n\nStandard camera modes are not suitable for this task.\n*   **Manual Mode** is static and does not adapt to the changing light, leading to under or over-exposed footage.\n*   **Automatic Exposure (AE) Mode** (like Aperture Priority) introduces \"flicker\" as the camera's meter makes slight adjustments between shots.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/drastic.gif\" width=\"49%\"\u003e\n  \u003cimg src=\"img/flicker.gif\" width=\"49%\"\u003e\n  \u003cp align=\"center\"\u003e\n   Manual Mode (left) vs. AE Mode Flicker (right)\n  \u003c/p\u003e\n\u003c/p\u003e\n\n## The Solution: A Non-Linear Approach\n\nThe key challenge is that ambient light during a sunrise or sunset does not change linearly. It follows a logistic curve, changing slowly at the extremes (full day/night) and very rapidly during the transition.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/brightness.png\" width=\"48%\"\u003e\n  \u003cimg src=\"img/shutter.png\" width=\"48%\"\u003e\n  \u003cp align=\"center\"\u003e\n    Ambient brightness curve (left) and the required complimentary shutter speed curve (right).\n  \u003c/p\u003e\n\u003c/p\u003e\n\nTo achieve a perfectly smooth timelapse, this project implements a custom, complimentary shutter speed curve. It also calculates a dynamic interval (the pause between shots) to ensure the final video plays back at a smooth, consistent perceived speed.\n\nCommercial intervalometers that offer exposure ramping typically only use linear interpolation, which is insufficient for this non-linear problem.\n\n## How It Works\n\nThe project is split into two parts:\n\n1.  **Python Script (`calculate.py`):** A Python script that does the heavy lifting. You configure your desired parameters (e.g., number of frames, start/end shutter speeds), and it calculates the precise, non-linear shutter durations and inter-shot pauses. It then generates Arduino-ready C++ code.\n2.  **Arduino Sketch (`shutter_controller.ino`):** A simple sketch that reads the timing arrays generated by the Python script. It triggers the camera's shutter via a basic circuit, executing the pre-calculated sequence perfectly.\n\n---\n\n## How to Use\n\nFollow these steps to create your own custom timelapse sequence.\n\n### Step 1: Configure the Python Script\n\nOpen the `calculate.py` file. At the top of the script, you can edit the core parameters for your timelapse:\n\n```python\n# --- Core Parameters ---\nnum_frames = 240  # The total number of photos to take\n\n# --- Calculate Shutter and Pause Durations ---\n# Shutter speeds (in ms) increase from fast (day) to slow (night)\nshutters = times100(100, 180000, num_frames) # (start_speed, end_speed, frames)\n\n# Pause times (in ms) decrease as light changes faster\npauses = times100(120000, 1000, num_frames - 1) # (start_pause, end_pause, frames-1)\n```\n\n### Step 2: Run the Python Script\n\nExecute the script from your terminal:\n\n```bash\npython calculate.py\n```\n\nThe script will run the analysis, display the plots for your sequence, and most importantly, print a block of C++ code to the terminal.\n\n### Step 3: Update the Arduino Sketch\n\nCopy the entire C++ code block from your terminal output. It will look like this:\n\n```cpp\n// --- COPY AND PASTE THESE LINES INTO YOUR ARDUINO SKETCH ---\n// Automatically generated for 240 frames.\nconst unsigned long shutterListMS[] = {100, 200, 200, ...};\nconst unsigned long pauseListMS[] = {120000, 117700, 115300, ...};\n// --- END OF ARDUINO CODE BLOCK ---\n```\n\nOpen the `shutter_controller.ino` sketch in the Arduino IDE. Paste the copied code, replacing the existing `shutterListMS` and `pauseListMS` arrays.\n\n### Step 4: Upload and Shoot\n\n1.  **Upload** the updated sketch to your Arduino.\n2.  **Connect** the Arduino to your camera's shutter release port using the circuit.\n3.  **Set your camera** to **Bulb (B)** mode. This allows the Arduino to control the exposure time completely.\n4.  **Power on** the Arduino. It will wait for the initial pause (`initialPauseMS`) and then begin the capture sequence.\n\n## Hardware Components\n\nThe shutter release circuit is very simple and uses an optocoupler to safely trigger the camera without a direct electrical connection.\n\n*   Arduino (any model, e.g., Uno, Nano)\n*   PC817 Optocoupler (or similar)\n*   220Ω Resistor\n*   2.5mm TRS (stereo) jack or cable to connect to the camera\n*   (Optional) 7-segment display for frame count feedback","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrayvid%2Fshutter-controller","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrayvid%2Fshutter-controller","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrayvid%2Fshutter-controller/lists"}