Skip to content

Overview

This project captures JPEG images on an ESP32-CAM module and transmits them over LoRa using RYLR896/RYLR998 AT-command modules. A Python base station receives, reassembles, and saves the images.

  • Reliable image transfer — windowed ACK protocol with Base64 encoding and CRC16 verification.
  • Multiple capture triggers — periodic, on-demand via LoRa command, and motion detection (JPEG size heuristic).
  • Remote control — send commands from the base station: capture, status, ping, configuration changes.
  • OTA updates — HTTP OTA over WiFi, with hardware button trigger. Dual app partition slots for safe rollback.
  • BLE WiFi provisioning — configure WiFi credentials from a phone app.
  • QEMU testing — full pipeline runs in emulation with a fake camera and LoRa loopback queue.
ComponentDescription
ESP32-CAM (AI-Thinker)OV2640 camera, 8MB PSRAM, onboard flash LED
RYLR896 or RYLR998LoRa module with AT command interface
ESP32-CAM-MBUSB carrier board (optional, simplifies flashing)
Second RYLR moduleConnected to the base station PC via USB-to-serial
  • ESP-IDF v5.x (build toolchain)
  • Python 3.10+ with pyserial (base station)
  • Espressif’s QEMU fork (optional, for emulation testing)
  1. Build for QEMU (no hardware needed):

    Terminal window
    cp sdkconfig.defaults.qemu sdkconfig.defaults
    idf.py build
  2. Run the loopback test — see QEMU Testing guide.

  3. Flash to real hardware — see Flashing guide.

  4. Set up the base station — see Base Station guide.

esp32-cam/
├── main/
│ ├── main.c # Entry point and startup sequence
│ ├── cam_lora.h # Camera-to-LoRa pipeline task
│ ├── lora_rylr.h # RYLR AT command driver
│ ├── lora_transfer.h # Fragmentation and transfer protocol
│ ├── motion_detect.h # JPEG size heuristic motion detector
│ ├── ota_example.h # HTTP OTA update framework
│ ├── ota_trigger.h # GPIO0 button OTA trigger
│ ├── ble_prov.h # BLE WiFi provisioning
│ ├── wifi_manager.h # WiFi connection management
│ ├── remote_log.h # Syslog over UDP
│ ├── uart_dio_example.h # UART on custom GPIO pins
│ └── test_image.h # Embedded 64x64 JPEG test image
├── components/
│ └── fake_camera/ # Camera emulation for QEMU
├── tools/
│ ├── lora_receiver.py # Python base station
│ └── img2cam.py # Image conversion utility
├── partitions_ota.csv # OTA partition table
├── sdkconfig.defaults # Hardware build config
└── sdkconfig.defaults.qemu # QEMU build config