Skip to content

Camera Pipeline API

Header: main/cam_lora.h

A FreeRTOS task that manages camera capture, LoRa transfer, motion detection, and remote command handling. This is the main application pipeline.

FieldTypeDefaultDescription
lora_destuint16_t0Base station LoRa address
periodic_msuint32_t0Periodic capture interval in ms (0 = disabled)
motion_enabledboolfalseEnable motion detection trigger
jpeg_qualityuint8_t12OV2640 JPEG quality (0–63, lower = better)
esp_err_t cam_lora_start(const cam_lora_config_t *config);

Initialize and start the camera-to-LoRa pipeline. Creates a FreeRTOS task (cam_lora, 8KB stack, priority 5) that:

  1. Initializes the camera (fake or real)
  2. Polls for LoRa commands every 100ms
  3. Checks periodic and motion triggers
  4. Captures and transfers JPEG images

Returns: ESP_OK on success, ESP_ERR_NO_MEM if task creation fails.

void cam_lora_stop(void);

Signal the pipeline task to stop. The task self-deletes on its next iteration.

void cam_lora_trigger_capture(void);

Request an immediate capture from outside the pipeline task. Sets an internal flag that the task checks on its next poll cycle.

uint32_t cam_lora_get_capture_count(void);

Returns the total number of successful captures since pipeline start.

bool cam_lora_is_running(void);

Check if the pipeline task is currently running.

The task supports three capture triggers, evaluated in priority order:

A remote C:CAPTURE command or call to cam_lora_trigger_capture() sets the capture_pending flag. The task processes this immediately on its next poll cycle.

When periodic_ms > 0, the task captures at fixed intervals. An on-demand capture resets the periodic timer.

When motion_enabled is true, the task grabs a camera frame every 2 seconds and feeds the JPEG size to motion_check(). If motion is detected (>15% size change with debounce), it triggers a capture.

The task listens for LoRa packets and handles these commands:

CommandAction
C:CAPTURESet capture pending flag
C:STATUSReply with S:HEAP=N:UP=N:RSSI=N:CAP=N:VER=X
C:PINGReply with S:PONG
C:CONFIG:period=NSet periodic interval (ms)
C:CONFIG:motion=0|1Enable/disable motion detection
C:CONFIG:threshold=NSet motion threshold percentage
flowchart TD
    A["cam_lora_capture_and_send()"] --> B["fake_camera_fb_get()<br/>Get JPEG framebuffer"]
    B --> C["Copy JPEG to PSRAM<br/>Free camera buffer early"]
    C --> D["fake_camera_fb_return()"]
    D --> E["motion_check(jpeg_len)<br/>Feed motion detector"]
    E --> F["xfer_send_image()<br/>Fragment + send over LoRa"]
    F --> G["free(jpeg_copy)"]

The camera framebuffer is released as soon as the JPEG is copied to a PSRAM-backed buffer. This allows the camera to continue capturing while the LoRa transfer proceeds (transfers can take 10+ seconds).