~$178
Cheapest DSLR Build
ESP32 + DSLR (excl. camera)
144
Images / Day
Every 5 min, 6am–6pm
14B
Heartbeat Packet
Status, storage, GPS coords
$1–3
Per Month
NB-IoT data cost (M2MSIM)
Daily Cycle
Wake
RTC alarm 06:00 — Pi boots (25s) or ESP32 wakes (138ms)
Capture
Every 5 min via gphoto2, shutter cable, or Termux cron
Store
Locally on SD card — up to 3 months before extraction
Heartbeat
14-byte NB-IoT UDP packet every 30 min via Telstra
Sleep
18:00 shutdown — 8µA deep sleep or 0.5mA PV HAT
System Variants
Pi Zero 2W + DSLR — “Full Control”
- Cost: ~$359 (excl. DSLR + housing)
- Controller: Pi Zero 2W + PV PI HAT (MPPT, RTC wake)
- Capture: gphoto2 over USB — full image management
- Storage: 128GB microSD (OverlayFS root, ext4 images)
- Extraction: WiFi AP web interface — browser download
- Solar: 20W panel, 72Wh LiFePO4 (6-day autonomy)
- NB-IoT: Waveshare SIM7028 HAT (GPIO, 0.8µA PSM)
- Daily power: ~12Wh
ESP32 + DSLR — “Minimal Trigger”
- Cost: ~$178 (excl. DSLR + housing)
- Controller: LILYGO T-SIM7000G (ESP32 + NB-IoT + GPS)
- Capture: 2.5mm shutter cable via optocoupler
- Storage: 128GB SD card in DSLR directly
- Extraction: Physically swap or copy DSLR SD card
- Solar: 10W panel, 22–37Wh LiFePO4
- Wake: 138ms from deep sleep (8µA overnight)
- Daily power: ~5–7Wh
Samsung Galaxy — “Phone Camera”
- Cost: ~$103 + phone (excl. housing)
- Capture: Termux cron — termux-camera-photo every 5 min
- Resolution: 12MP (200MP headless inaccessible)
- Storage: 256GB phone — ~300 days capacity
- Extraction: WiFi hotspot + HTTP server (~30 seconds)
- Solar: 5W USB panel — smallest footprint
- NB-IoT: Separate ESP32 + SIM7028 sidecar module
- Daily power: ~3–5Wh
Heartbeat Packet (14 bytes)
Data Fields (12 bytes)
- camera_id [2B] — Unique device identifier (uint16)
- flags [1B] — Shooting, modem_alive, camera_connected, undervoltage
- storage_pct [1B] — Storage used 0–100%
- image_count [2B] — Images since last extraction
- minutes_since_capture [2B] — Freshness indicator
- cpu_temp [1B] — °C (ambient for ESP32)
- uptime_hours [2B] — Total runtime since boot
Protocol Notes
- Size: 14 bytes total (12 data + 2 HMAC)
- Transport: UDP via SIM7000G AT+CIPSTART
- Auth: Truncated SHA-256 HMAC per camera
- Byte order: Big-endian (network byte order)
- Interval: Every 30 min (daytime), PSM between sends
- GPS: Separate 15-byte packet (magic byte 0xBB)
- Data cost: ~$1–3/month (M2MSIM NB-IoT)
Software Stack
Device-Side
- Pi Zero: Python 3 + pyserial + python-gphoto2
- ESP32: C++ Arduino + TinyGSM library + DS3231 RTC
- Phone: Termux + termux-api + Python cron scripts
- AT commands: UART to SIM7000G / SIM7028 HAT at 115200 baud
- Service: systemd nbiot-camera.service (Pi variant)
- Pi UART: Bluetooth disabled (dtoverlay=disable-bt)
Server-Side (PHP + MySQL)
- UDP listener: PHP CLI daemon — socket_recvfrom()
- Database: MySQL — nbiot_cameras, nbiot_camera_status, heartbeat_log
- HTTP APIs: PHP 8 — status, history, command queue
- Alert cron: Offline detection and email notifications
- Downlink: Commands queued and sent on next heartbeat
- Error log: /camera-systems/nb-iot-basic/server/api/debug.php