Open-source CCU control system for Blackmagic Design cameras with vMix tally integration using the Blackmagic Arduino SDI Shield
TallyCCU Pro is an Arduino-based solution that provides full Camera Control Unit (CCU) functionality for Blackmagic cameras via SDI using the Blackmagic Arduino SDI Shield, along with real-time tally light integration with vMix. Control your cameras from a web browser, Bitfocus Companion, or build your own integration using the TCP API.
- Full CCU Parameters: Iris, focus, zoom, white balance, ISO, shutter, ND filters
- Color Correction: Lift, gamma, gain, offset with visual color wheels
- Display Settings: Zebra, peaking, focus assist, LUT selection
- Audio Control: Mic levels, headphone mix, phantom power
- PTZ Support: Pan/tilt velocity and memory presets (for supported cameras)
- vMix Integration: Automatic tally lights from vMix program/preview state
- Flexible Mapping: Map any vMix input to any camera ID
- Adjustable Brightness: Independent front/rear tally brightness control
- Web Interface: Full control from any browser on your network
- Companion Module: Stream Deck integration via Bitfocus Companion
- TCP API: Real-time bidirectional sync on port 8098
- Serial Configuration: Initial setup without network access
- Server-Sent Events (SSE): Instant parameter sync between web interface and Companion
- Bidirectional Sync: Changes in Companion appear instantly in the web interface and vice versa
- Per-Camera State: Browser maintains state for all 8 cameras, enabling seamless switching
- Automatic State Recovery: When either client connects, it receives current state from the other
- Live Preset Updates: Preset names sync instantly across all interfaces
- Automatic Boot Loop Detection: System detects consecutive boot failures
- Safe Mode: After 3 failed boots, system starts without SDI Shield initialization
- Diagnostic Web Interface: Access troubleshooting page at device IP when in Safe Mode
- Network Access Preserved: Configure network, use vMix tally, and diagnose issues remotely
- One-Click Recovery: Restart in normal mode from the web interface after fixing the issue
- Save/Load Presets: Store complete camera configurations
- Per-Camera Presets: 5 presets per camera, stored on SD card
- Group Selection: Choose which parameter groups to include in presets
| Component | Model | Notes |
|---|---|---|
| Microcontroller | Arduino Mega 2560 | Must be Mega (not Uno) due to memory requirements |
| Network | Arduino Ethernet Shield 2 | W5500 chipset, includes SD card slot |
| SDI Interface | Blackmagic 3G-SDI Shield | For Arduino, directly from Blackmagic |
| Storage | MicroSD Card | 1-32GB, must be formatted correctly (see below) |
| Power | 9-12V DC Power Supply | Required - USB power alone is insufficient |
+---------------------+
3 | Blackmagic SDI | <- Top
+---------------------+
2 | Ethernet Shield | <- Middle
+---------------------+
1 | Arduino Mega 2560 | <- Bottom
+---------------------+
The Blackmagic SDI Shield is designed for Arduino Uno, which has I2C pins at A4/A5. The Arduino Mega has I2C on different pins (20/21), so you MUST add two jumper wires on the Blackmagic SDI Shield:
Bridge connections on SDI Shield:
- A4 --> SCL
- A5 --> SDA
These bridges route the I2C signals to the correct pins. Without them, the SDI shield will not communicate with the Arduino Mega.
The system requires external power (9-12V DC) connected to the Blackmagic SDI Shield's power input. USB power alone does not provide enough current and the system will fail to boot properly.
Note: Starting with v3.7, if the system detects repeated boot failures (e.g., due to missing 12V power or invalid SDI signal), it will automatically enter Safe Mode. See Safe Mode for details.
The SD card MUST meet these requirements:
- MBR Partition Table (not GPT) - Windows and Mac sometimes create GPT partitions
- Single Partition - Only one partition on the card
- Correct Filesystem:
- Cards 2GB or smaller: FAT16
- Cards 4GB or larger: FAT32
- exFAT will NOT work
Do NOT use Windows Explorer or Mac Disk Utility - they may create incompatible partition tables.
Use the official SD Card Formatter from the SD Association:
- Download from: https://www.sdcard.org/downloads/formatter/
- Select your SD card
- Choose "Overwrite format" (not quick format)
- Format the card
If you still have issues, use the SdFormatter sketch included in the SdFat library examples.
After formatting, copy these files to the SD card root:
SD Card Root/
├── index.html (Main CCU interface)
├── tally.html (Tally configuration)
├── sdcard.html (SD Card File manager)
└── safemode.html (Safe Mode diagnostics - v3.7+)
- Stack shields in order: Mega -> Ethernet -> SDI Shield
- Add I2C bridge wires: A4 to pin 20, A5 to pin 21
- Insert formatted SD card into Ethernet Shield slot
- Connect 9-12V power supply to SDI Shield
- Connect SDI output to your camera(s)
Required Libraries (install via Arduino Library Manager):
SdFatby Bill GreimanEthernet(built-in)
Blackmagic Library (manual install):
- Download from Blackmagic website (included with Desktop Video software)
- Copy to Arduino libraries folder
Upload Firmware:
- Open
Arduino/TallyCCUPro.inoin Arduino IDE - Select Board:
Arduino Mega or Mega 2560 - Select Port: Your Arduino's COM port
- Click Upload
Connect via serial monitor (115200 baud) or use the Serial Configurator tool:
Available commands:
ip 192.168.1.100 Set Arduino IP address
subnet 255.255.255.0 Set subnet mask
gateway 192.168.1.1 Set gateway
vmixip 192.168.1.50 Set vMix computer IP
status Show current configuration
reset Restart Arduino
safemode Force safe mode on next boot (v3.7+)
normalboot Exit safe mode and restart (v3.7+)
- Open browser:
http://YOUR_ARDUINO_IP/ - You should see the CCU Control interface
- Select a camera and adjust parameters to test
Access at http://YOUR_ARDUINO_IP/
Note: Always use
http://explicitly. Some modern browsers default to HTTPS, which is not supported. See Limitations.
The main control interface featuring:
- Camera Selector: Switch between cameras 1-8
- Parameter Groups: Lens, Video, Audio, Color Correction, Display, Tally, PTZ
- Color Wheels: Visual lift/gamma/gain/offset adjustment
- Sliders: Precise control with step buttons and reset
- Presets: Save and load 5 presets per camera
- Real-Time Sync: Changes from Companion appear instantly via SSE

- vMix IP: Address of computer running vMix
- Input Mapping: Map vMix inputs to camera IDs
- Connection Status: Real-time indicator

Safe Mode is a recovery feature introduced in v3.7 that helps diagnose and recover from hardware-related boot failures.
The system enters Safe Mode automatically after 3 consecutive boot failures. Common causes:
- Missing 12V Power: SDI Shield requires external 12V power
- Invalid SDI Signal: 4K signals or Level A 3G-SDI are not supported
- SDI Cable Disconnected: No signal during boot
- I2C Bus Conflict: Missing or incorrect bridge wires
| Feature | Status |
|---|---|
| Web Interface | ✓ Available (diagnostic page) |
| Network Configuration | ✓ Available |
| vMix Tally Connection | ✓ Receive only (no SDI output) |
| Companion TCP | ✓ Available |
| Serial Console | ✓ Available |
| SDI Tally Output | ✗ Disabled |
| CCU Camera Control | ✗ Disabled |
- Fix the underlying issue (connect 12V power, valid SDI signal, etc.)
- Access the diagnostic page at
http://YOUR_ARDUINO_IP/ - Click "Restart Normal Mode"
- The system will restart and attempt normal boot
Alternatively, use the serial command normalboot to exit Safe Mode.
For testing or troubleshooting, you can force Safe Mode on the next boot:
- Serial command:
safemode - The system will enter Safe Mode on the next restart
- Copy
companion-module/to Companion's dev modules directory - Run
yarn installinside the folder - In Companion Settings, set developer modules path
- Add connection: "TallyCCU Pro"
- All CCU parameters (set/increase/decrease/reset)
- Load/Save presets
- Change active camera
- vMix connection toggle
The Companion module automatically syncs with the web interface:
- Parameters changed in Companion are instantly reflected in the web UI
- Parameters changed in the web UI are instantly reflected in Companion variables
- When either client connects, it receives the current state from the other
For custom integrations, connect via TCP to port 8098.
SUBSCRIBE Subscribe to real-time updates
UNSUBSCRIBE Unsubscribe from updates
PING Keep-alive (responds with PONG)
STATUS Get connection status
CCU <cameraId> <paramKey> <value> Parameter changed
PRESET <cameraId> <presetId> <name> Preset loaded
PRESETSAVED <cameraId> <presetId> <name> Preset saved
REQUESTSYNC Request client to send cached state
PONG Ping response
SUBSCRIBED OK Subscription confirmed
CCUSYNC <cameraId> <paramKey> <value> Send cached parameter to Arduino
(forwarded to SSE clients)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Web UI │◄──SSE───│ Arduino │◄──TCP───│ Companion │
│ (Browser) │───POST─►│ (Mega2560) │───TCP──►│ Module │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ cameraStates[] │ │ cameraStates{}
│ (per-camera) │ │ (per-camera)
└────────────────────────┴───────────────────────┘
Bidirectional Real-Time Sync
- SSE (Server-Sent Events): Arduino pushes changes to web interface instantly
- TCP Broadcast: Arduino pushes changes to Companion module
- POST /syncState: Web sends cached state to Arduino for TCP broadcast
- REQUESTSYNC: Arduino requests state from connected clients on new connections
Power On
│
▼
SafeMode::begin()
│
├─► Check EEPROM boot flag
│
▼
┌───────────────────┐
│ Previous boot │──NO──► Clean boot, reset counter
│ completed? │
└────────┬──────────┘
│YES (flag present = crash)
▼
Increment counter
│
▼
┌───────────────────┐
│ Counter >= 3? │──NO──► Try normal boot
└────────┬──────────┘
│YES
▼
SAFE MODE
- Skip SDI Shield init
- Network/Web only
- Serve diagnostic page
TallyCCUPro/
├── firmware/ Arduino source code
│ ├── TallyCCUPro.ino Main sketch
│ ├── CCUControl.* Camera control
│ ├── CCUBroadcast.* TCP broadcast server
│ ├── TallyManager.* Tally light control
│ ├── VmixConnector.* vMix integration
│ ├── WebServer.* HTTP & SSE server
│ ├── Storage.* EEPROM management
│ ├── SdUtils.* SD card operations
│ ├── SafeMode.* Boot failure recovery (v3.7+)
│ └── Configuration.h Pin & address definitions
├── sdcard/ Web interface files
│ ├── index.html Main CCU interface
│ ├── tally.html Tally configuration
│ ├── sdcard.html File manager
│ └── safemode.html Safe Mode diagnostics (v3.7+)
├── companion-module/ Bitfocus Companion module
│ ├── main.js Module entry point
│ ├── actions.js CCU parameter actions
│ ├── tcp.js Real-time sync client
│ ├── variables.js Companion variables
│ └── params.js Parameter definitions
├── tools/ Serial configurator
└── README.md
TallyCCU Pro is optimized for Arduino Mega's limited 8KB RAM:
- Static buffers (no String objects in critical paths)
- SSE-based sync (state stored in browser, not Arduino)
- Efficient TCP handling with connection pooling
- Typical free RAM: ~1,500+ bytes (improved in v3.5)
The Arduino Mega cannot handle HTTPS connections due to hardware limitations (insufficient RAM and CPU for TLS encryption). Always use http:// when accessing the web interface.
Tip: If your browser defaults to HTTPS and shows a connection error, manually type
http://before the IP address.
The Blackmagic 3G-SDI Arduino Shield has the following limitations:
- Maximum resolution: 1080p60 (no 4K/UHD support)
- 3G-SDI Level B only: The shield only passes video when using 3G-SDI Level B. This is the default for Blackmagic devices, but other manufacturers may default to Level A. Check your camera/device settings if video is not passing through.
Only one SSE connection is supported at a time. Multiple browser tabs will share the same connection, but opening the interface on multiple devices simultaneously may cause sync issues.
The Arduino Ethernet library supports a maximum of 4 simultaneous TCP connections, shared between:
- HTTP requests (web interface)
- SSE connection (real-time sync)
- TCP clients (Companion, custom integrations)
- vMix connection (tally)
The Blackmagic SDI protocol is write-only - parameters can be sent to cameras but not read back. The system cannot query current camera settings; it only knows values that were set through TallyCCU Pro.
| Problem | Solution |
|---|---|
| Web interface not loading | Verify SD card is MBR/FAT16 or FAT32, reformat with SD Association tool |
| SDI shield not responding | Check I2C bridge wires (A4→SCL, A5→SDA on SDI shield) |
| System not booting | Connect external 9-12V power, USB is insufficient |
| System stuck in boot loop | Check 12V power and SDI signal; after 3 failures, Safe Mode activates automatically |
| Safe Mode activated | Fix hardware issue (12V power, valid SDI signal), then click "Restart Normal Mode" |
| vMix tally not working | Verify vMix IP in tally.html, check vMix TCP API is enabled |
| Camera not responding | Verify camera ID matches, check SDI connection and termination |
| Browser shows HTTPS error | Type http:// explicitly before the IP address |
| Sync not working | Ensure both web and Companion are connected; check serial monitor for SSE status |
| Settings reset after reboot | Update to v3.6+ which fixes the override persistence bug |
- New: Safe Mode recovery system for boot failures
- New: Automatic boot loop detection (enters Safe Mode after 3 consecutive failures)
- New: Diagnostic web interface (
safemode.html) for troubleshooting - New: Serial commands
safemodeandnormalbootfor manual control - New:
/safemode-statusand/safemode-exitAPI endpoints - Improved: TallyManager skips SDI Shield initialization in Safe Mode
- Improved: WebServer redirects to diagnostic page when in Safe Mode
- Version bump release
- New: Real-time synchronization via Server-Sent Events (SSE)
- New: Bidirectional sync between web interface and Companion
- New: Live preset name updates across all interfaces
- Improved: ~600 bytes RAM freed by moving state to browser
- Improved: Faster SSE connection establishment
- Fixed: Override settings (Tally/CCU/vMix) persistence bug
- Complete rewrite with modular architecture
- Web-based color correction with visual color wheels
- Companion module with full parameter support
- TCP broadcast for real-time updates
See RELEASE_NOTES.md for full version history.
Joaquin Villodre - github.com/fiverecords
This project is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0).
You are free to use, modify and redistribute this project for non-commercial purposes, provided that you give appropriate credit and keep derivatives under the same license.
This project is not affiliated with, endorsed by, or sponsored by Blackmagic Design or vMix. Blackmagic Design and vMix are registered trademarks of their respective owners.





