16.2 KiB · text History 10112a6

+++ title = “Acme Camera” description = “” date = 2026-10-13

[extra] reveal_theme = “black” reveal_transition = “slide” +++

Acme Camera

A Proposal


Product Overview

A wireless security system architecture supporting long operational life

Note: The pitch: months on a charge, a person-confirmed alert in seconds, and fleet data that proves both


Assumptions

Area Assumption
Battery ~6000 mAh Li-ion pack
External power regulated 5 V, solar included
Activity ~20 events/day, ~10 s clips
Network 2.4 GHz Wi-Fi to a home AP
Recording event clips, live view on demand
Backend exists, we own the device side

Note: These drive every number later in the deck, so happy to rerun the math if Acme’s are different Solar is just another 5 V source, the panel’s own controller handles MPPT No continuous recording, a battery camera can’t afford it


Hardware Design

 


SOC + MCU

–

MCU

ultra-low power attached to motion sensors, lighting, and power control

SOC

attached to camera/storage and spends most of its time in deep sleep

–

MCU Candidates

  • nRF54L
  • nRF52840

SOC Candidates

  • Rockchip RV1106
  • Ingenic T41
  • Ambarella CV7

Motion

Configurable

PIR

plus

MMWave

Note: Power Efficient Setup, PIR is used to wake the SOC and then mmwave is used to determine if people are present


LED Driver

to support Infrared and Visible Spots for lighting areas for improved visibility


Environmental

  • Temperature
  • Luminosity

Power Subsystem

  • Battery Charge Controller & Gauge

–

What about solar?

Let’s set the expectation that any input power source provides regulated 5V, solar included

–

Solar Charge Controller

  • TI bq25504
  • e-peas AEM10941 / AEM13920:

Note: nPM1300 does not provide the MPP support for the solar cells so we need an external IC to properly do it


Software Design

Note: mcuctl sets the motion and light mode on the embedded mcu powerctl controls the power domain for the battery charger and reads the fuel gauge portalctl provides the initial configuration UI and subsequent status web portals cameractl reads frames and dispatches them to whatever has been configured configctl is the source of truth that gets configuration requests broker: mqtt, likely mosquitto infctl: inference controller for on-chip npus to load models (bonus)


Build & OS

  • Yocto on the SOC vendor’s BSP
  • Read-only rootfs in A/B slots, writable /data
  • Signed images, built reproducibly in CI
  • Rust daemons as sandboxed systemd units

Note: Yocto for layers, an SDK for app developers, and license manifests / SBOM for free; Buildroot if the chosen vendor only supports that Kernel trimmed to what the board needs, suspend-to-RAM tuned so a wake is a resume, not a boot Read-only rootfs means an update is a whole-slot swap, nothing drifts between devices /data holds config, credentials and the clip buffer, and is the only thing a factory reset wipes

–

Process Model

Unit Can reach
broker /run/broker.sock
mcuctl UART to the MCU
powerctl PMIC over I²C
cameractl sensor, ISP, clip buffer
portalctl soft-AP, HTTP
configctl /data/config

Note: Each unit runs as its own user with ProtectSystem=strict and DeviceAllow for only its hardware The broker checks the connecting uid (SO_PEERCRED) against per-topic ACLs, so portalctl can request config but never write it A crashed daemon is restarted by systemd and counted in telemetry


Boot Plan

Note: Uses an A+B boot that only changes the boot target once we’ve booted successfully and connected to the backend


Security

Trust from boot to cloud

Note: Home security buyers ask about this first, and a compromised camera is a camera pointed into someone’s home

–

Layers

Layer Measure
Boot secure boot, signed A/B images
Keys secure element / OTP, never in rootfs
Storage encrypted /data and clips
Processes per-service users, sandboxed units
Broker per-topic ACLs by peer uid
Setup soft-AP only while unprovisioned
Cloud per-device certs, mutual TLS

Note: The claim token from setup is exchanged for a per-device cert, nothing shared across the fleet Telemetry carries metrics only, no video and nothing personal beyond the display name Factory reset wipes /data and revokes the device cert server side


Components

Component Role
broker MQTT on a Unix socket
mcuctl motion and lights via the MCU
powerctl power modes, PMIC telemetry
portalctl setup and status portals
cameractl frames to storage and cloud
configctl source of truth for settings
infctl on-device inference (bonus)

Note: Details and types for each are in the appendix, the links jump there


Anatomy of an Event

Step t
PIR trips, MCU wakes the SOC 0
SOC resumes from suspend ~200 ms
Radar confirms a person ~300 ms
First frame from the sensor ~700 ms
Wi-Fi reconnects ~1.5 s
Notification sent ~2 s
Clip uploaded, back to sleep ~15 s

Note: The SOC resumes in parallel with the radar check, if the radar doesn’t confirm it goes straight back to sleep Capture starts before the network is up, frames go to the local clip buffer first, so the first frame isn’t waiting on Wi-Fi ~15 s at ~400 mA is the ~1.5 mAh per event the power budget uses Keeping Wi-Fi associated while asleep would cut 1.5 s but costs standby current, a config trade-off


Metrics

  • Performance within the configured power envelope

leading to insights for better defaults

  • Battery life across the fleet

Note: Every config choice (motion mode, light mode, schedules) trades responsiveness for battery, so the metrics are about how well a device does inside the envelope its owner picked, and fleet data tells us which defaults to ship

–

Targets

Metric Target
Battery life, default config ≥ 3 months
Standby draw, SOC asleep ≤ 100 µA
Motion → first frame < 1 s p95
Motion → notification < 5 s p95
False wakes (no person) < 20%
Crash-free wakes > 99.9%
OTA success, first try > 99.5%

Note: Assumptions: ~6000 mAh pack, 20 events/day, 10 s clips, ~400 mA while the SOC, Wi-Fi and IR are up Each event costs roughly 1.5 mAh, so events dominate and standby has to stay tiny Wake latency is the user-visible one: a late first frame means a clip of someone’s back False wakes are PIR triggers the radar doesn’t confirm, they cost battery for nothing A/B boot means a failed OTA rolls back rather than bricks, the target is about not needing to

–

Power Budget

Item mAh/day
Standby, 100 µA × 24 h 2.4
Events, 20 × 1.5 mAh 30
Heartbeat + telemetry ~0.5
Self-discharge, ~2%/month ~4
Total ~37
6000 mAh × 80% usable ~130 days

Note: Events are ~80% of the budget, so the false wake target and clip length matter more than standby 40 events/day halves it to ~65 days, cold weather takes another chunk off usable capacity This is the table the fleet data should confirm or correct

–

Slicing the Fleet

  • Firmware version
  • Motion / light / power mode
  • Battery vs solar vs external
  • Temperature and Wi-Fi signal

Note: Averages hide problems: a battery life drop on one firmware, or in cold climates, or on weak Wi-Fi These are the dimensions every metric gets broken down by Firmware cohorts gate staged OTA rollouts: a regression in one cohort halts the rollout


Instrumentation

What we measure, how it leaves the device, and how often

Note: Combines environmental and fuel gauge data with what each component already knows

–

Signals

Source Signals
powerctl voltage, current, charge
mcuctl wake reason, radar confirm
cameractl wake → frame latency
network connect time, RSSI
system fw, boot slot, crashes
environment temperature, light

Note: powerctl also reports time to empty, mcuctl how long the lights were on, cameractl clip length, network upload time, system the reboot reason Each component publishes its own metrics to the broker, so nothing new has to reach into another process Energy per wake comes from the fuel gauge before and after, which ties every event to its battery cost

–

Collection

  • Components publish metrics to the broker
  • A telemetry agent aggregates and buffers to flash
  • MCU logs hourly samples while the SOC sleeps
  • Uploads ride along when Wi-Fi is already up

Note: Never wake the radio just to report, telemetry should be well under 1% of the energy budget The MCU keeps a small ring buffer of sleep samples (battery, temperature, wake counts) that the SOC drains on its next wake Buffered to flash so a dead battery or lost network doesn’t lose history Upload is MQTT over TLS to the backend, the same connection the device already holds for events

–

Reporting Cadence

When What
Every event wake summary: reason, latency, energy
Daily heartbeat counters, battery state, sleep samples
After a crash or rollback coredump and reboot reason
On demand debug logs, per device

Note: The heartbeat goes out even with no events, so a silent device is a signal on its own Coredumps are symbolicated server side, the device only ships the raw dump On demand logs are for support cases, off by default to save power and bandwidth

–

Fleet Dashboards

  • Projected battery life per device vs target
  • Latency and false wake rate per cohort
  • Alerts: projected life below target, missed heartbeat, crash spikes after OTA

Note: Projected life comes from the measured drain rate, so we can flag a device months before it dies Missed heartbeat for 48 h means dead, offline or stuck, worth an owner notification A crash spike in a new firmware cohort pauses the rollout automatically


Risks

Risk Mitigation
SOC vendor BSP quality evaluate two SOCs early
Battery life misses target measure from the first prototype
Wake latency resume, don’t boot
Weak Wi-Fi local clip buffer, RSSI telemetry
RF certification pre-certified Wi-Fi module
Fleet regressions staged OTA, A/B rollback

Note: BSP quality is the biggest schedule risk for camera SOCs, kernel age and ISP blobs vary a lot between vendors Battery life is the product, so it’s measured on every build, not at the end

–

Trade-offs

Choice Gains Costs
PIR wakes radar fewer false alerts ~100 ms
Radar only catches still people standby draw
Lights on motion color night video battery
Longer clips more context battery, upload
Wi-Fi kept up faster live view standby draw
On-device inference smarter alerts NPU power, BOM

Note: Every row is a battery-life knob, which is why the metrics are per configuration The defaults are a product decision, fleet data tells us whether they were the right ones

–

Delivery Plan

Phase Outcome
EVT, ~2 mo dev kits, BSP up, power measured
DVT, ~3 mo custom board, all daemons, OTA
PVT, ~3 mo certification, ~100 device pilot
Launch staged rollout, dashboards live

Note: Rough durations, mostly gated by the board spins and certification Telemetry ships in EVT firmware, the pilot fleet is where the targets get validated


Appendix

Component details and types


Component : Broker

  • MQTT

Note: on unix socket for the ability to have granular security TODO: why a unix socket over TCP (file permissions / peer credentials per component) TODO: topic layout and which components publish/subscribe


Component : MCUctl

Owns the MCU link: motion sensing and lighting

Note: Talks to MCU and sets/gets the motion detection and light settings

–

Motion

Which sensors watch for motion

enum MotionDetectionMode {
    OnlyPIR,
    PIRWakesRadar,
    OnlyRadar,
    Off
}

–

Lighting

When the visible and IR spots come on

enum LightControlMode {
    DuskDawn,
    Motion{cooldown: u32},
    Off
}

Component: Powerctl

Power modes, schedules and PMIC telemetry

Note: Collects power usage data, rundown and fuel gauge from the PMIC

–

Power Modes

Awake on detection, or on a schedule

enum PowerCtlMode {
    Detection{cooldown: u32},
    Timer{configs: Vec<TimerConfig>},
}

struct TimerConfig {
    start_time: u64,
    end_time: u64,
    schedule_days: HashSet<Weekday>
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Weekday { M, T, W, R, F, S, U }

–

Power Readings

One sample from the PMIC

enum PowerSource { Battery, External }

struct PowerReading {
    source: PowerSource,
    timestamp: u64,
    voltage_mv: u32,
    current_ma: i32,              // + charge / - drain
    state_of_charge: Option<u8>,  // fuel gauge, %
    time_to_empty_s: Option<u32>, // rundown estimate
}

Component: Portalctl

First-boot setup, then a status portal

Note: Interactive wireless authentication and cloud configuration

–

Modes

Which portal is up, and setup progress

enum PortalMode {
    Setup { ap_ssid: String, ap_psk: String },
    Status,
    Off,
}

enum ProvisioningState {
    AwaitingCredentials,
    JoiningNetwork,
    Claiming,
    Provisioned,
    Failed { reason: String },
}

Note: Setup is a soft-AP on first boot / factory reset, Status once on the home network, Off once cloud-managed

–

Credentials

What setup collects from the user

enum WifiSecurity { Open, Wpa2Psk, Wpa3Sae }

struct WifiCredentials {
    ssid: String,
    security: WifiSecurity,
    passphrase: Option<String>,
}

struct CloudClaim {
    claim_token: String, // QR / app
    display_name: String,
}

Note: claim_token comes from a QR code or the app and is exchanged for device certs

–

Config Requests

Changes sent to configctl via the broker

enum ConfigRequest {
    Network(WifiCredentials),
    Cloud(CloudClaim),
    DisplayName(String),
}

Note: portalctl publishes these over the broker; configctl validates and applies them

–

Status Portal

The status portal’s read-only view

enum BootSlot { A, B }

struct DeviceStatus {
    display_name: String,
    firmware_slot: BootSlot,          // A+B boot
    state_of_charge: Option<u8>,      // powerctl
    motion_mode: MotionDetectionMode, // mcuctl
    cloud_connected: bool,
}

Note: Read-only view assembled from the other components via the broker


Component: Cameractl

Note: Reads frames from the camera and decides to do further processing depending on config


Component: Configctl

Note: Source of truth for various configurations set from the portal

  • Network configuration
  • Display Name
  • Cloud Configuration
  • On-Device Processing Configuration

–

Component: Infctl

Note: This one is – because it’s a bonus one that we may not get into Configures on-device inference using NPU hardware available in modern camera SOCs