Skip to content

Motion Detection API

Header: main/motion_detect.h

Detects scene changes by comparing consecutive JPEG file sizes. When the OV2640 compresses a different scene, the JPEG size changes significantly — no extra hardware or pixel-level comparison needed.

FieldTypeDefaultDescription
threshold_pctfloat15.0Percentage change to trigger motion
cooldown_msuint32_t5000Minimum time between triggers (ms)
require_debouncebooltrueRequire 2 consecutive changes to trigger
void motion_init(const motion_config_t *config);

Initialize motion detection. Pass NULL to use defaults (15% threshold, 5s cooldown, debounce on). Calling this enables detection.

bool motion_check(size_t jpeg_size);

Feed a new JPEG frame size. Returns true if motion is detected. Call after each camera capture with fb->len.

Detection logic:

  1. First call establishes the baseline — always returns false.
  2. Computes the percentage change from the previous frame size.
  3. If below threshold, resets the debounce state and returns false.
  4. If above threshold but within cooldown period, returns false.
  5. If debounce is enabled and this is the first change, marks it and returns false.
  6. Second consecutive above-threshold change → motion confirmed, returns true.
void motion_reset(void);

Clear baseline and debounce state. Call this after repositioning the camera.

motion_enable / motion_set_threshold / motion_set_cooldown

Section titled “motion_enable / motion_set_threshold / motion_set_cooldown”
void motion_enable(bool enable);
void motion_set_threshold(float pct);
void motion_set_cooldown(uint32_t ms);

Runtime configuration updates. These can be triggered remotely via the C:CONFIG command.

motion_get_trigger_count / motion_is_enabled

Section titled “motion_get_trigger_count / motion_is_enabled”
uint32_t motion_get_trigger_count(void);
bool motion_is_enabled(void);

A static scene produces consistent JPEG sizes (±2–3% variance from compression noise). When the scene changes — a person walks by, lighting shifts, an object moves — the JPEG encoder produces a significantly different file size.

Static scene: 8200, 8180, 8210, 8195 (< 1% variance)
Person enters: 8200, 8180, 9850, 10200 (> 20% change)
↑ ↑
debounce trigger!

Why debounce? Single-frame JPEG size spikes can happen from sensor noise or auto-exposure adjustments. Requiring two consecutive above-threshold changes eliminates most false positives.

Why cooldown? Prevents rapid-fire captures during continuous motion (e.g., swaying trees). The 5-second default ensures the LoRa transfer of the previous capture completes before starting a new one.