From ESP32-CAM rookie to PRO

All the ESP32-CAM features exposed in in less than 10 lines of code.. Pictures, videos, Telegram notifications, motion detection, artificial intelligence... You name it!

This book is for you if:

You are a beginner and...

  • you want to start learning from the basics. You are not comfortable with complex, convoluted code that makes you wonder which line is doing what
  • you like to learn by doing. You want to see the code in action and see how it works
  • you want features out-of-the-box (sd storage, cloud storage, Telegram notifications, motion detection...)

You are an expert and...

  • you want to kickstart your projects by abstracting repetitive code
  • you want to access advanced features like AI, multithreading, MQTT...

What's inside?

Quickstart

Configure the image sensor and take your first picture

Live streaming

View the camera feed in real-time from any web browser

Save pictures to SD

Save pictures on the SD card, with timestamps and nested folders

Save pictures in cloud

Save pictures in the cloud, without setting up your own server

Telegram notifications

Send text and images to your Telegram bot without complex setups

Email notifications

Send images to your email inbox without complex setups

Motion detection

Detect moving objects from the camera frames, without any external PIR sensor

Motion detection streaming

Debug the motion detection algorithm in real-time using a web browser

Face detection

Find faces in pictures, including landmarks for eyes, nose and mouth

Object detection

Train a neural network to recognize any kind of object in real-time

Face detection streaming

Debug the face detection algorithm in real-time using a web browser

Face recognition

Enroll and recognize faces for smart access control

Example: How to take picture

/** * Get started with the EloquentEsp32Cam library. * Configure camera and grab frames. * Turn on INFO logging in the Tools menu to see * debug messages. */ #include <eloquent_esp32cam3.h> eloquent::camera::Camera camera; void setup() { Serial.begin(115200); Serial.println("Take picture"); // configure hardware parts camera.hardware.brownout.disable(); camera.hardware.clock.fast(); camera.hardware.pinout.ask(); // configure frame camera.frame.pixformat.jpeg(); camera.frame.resolution.vga(); camera.frame.quality.high(); // you can still access the camera_config_t instance directly camera.config.fb_count = 2; camera.config.grab_mode = CAMERA_GRAB_LATEST; // initialize camera camera.begin(); // raise() will throw a std::runtime_error // only if something went wrong // useful for debugging // in production you should handle the exception // (see image.failed() later) camera.raise(); Serial.println("Init OK"); } void loop() { // grab a new frame auto image = camera.grab(); // frame grabbing may fail sometimes // since it is a recoverable error, // handle it instead of raising if (image.failed()) { Serial.println(image.error); delay(1000); return; } ESP_LOGI("App", "Frame size: %d bytes", image.size()); delay(1000); }

Example: Motion detection

/** * Motion detection example, simple case. * Includes events throttling. * * All configurations in the setup() method * for the motion detection are optional. * Feel free to delete the ones you don't need. * * Requires the JPEGDEC library * (https://github.com/bitbank2/JPEGDEC) */ #include <JPEGDEC.h> #include <eloquent_esp32cam3.h> #include <eloquent_esp32cam3/modules/motion.h> using eloquent::camera::Camera; using eloquent::camera::helpers::Throttle; using eloquent::camera::motion::Motion; using eloquent::camera::motion::dtypes::Result; Camera camera; Motion motion; Throttle throttle("3 seconds"); void setup() { Serial.begin(115200); delay(3000); Serial.println("Motion detection: simple case"); // see "GetStarted.ino" for more comments camera.hardware.brownout.disable(); camera.hardware.clock.fast(); camera.hardware.pinout.ask(); camera.frame.pixformat.jpeg(); camera.frame.resolution.vga(); camera.frame.quality.high(); // run motion detection on a 1/16th version // of the frame to make it faster and // use less resources // must be a power of 2 or a multiple of 8 motion.config.stride(16); // how much should two pixels differ // to be included into the motion count? motion.config.differBy(20); // how much to smooth pixels when updating // previous state. // 0 means no smooth at all (use latest frame as is) // 1 means no update al all (use first frame only) // 0.5 is the mean between current and prev motion.config.smoothBy(0.2); // while training, the background model is updated // but no motion detection is performed. // also, skip the first few frames while the camera stabilizes motion.config.trainFor(10); // decide which pixels to consider motion.config.consider([](size_t x, size_t y, uint8_t pixel) { // only consider pixels whose x is > 80 and y < 320 return x <= 160 && y <= 320; }); // you can register a function to call when // moving ratio is above a certain value motion.callbacks.onMotion(0.3, [](Result &result) { // ignore throttle, always print Serial.printf( "[callback] %.0f%% of the image changed (%d/%d)\n", result.ratio * 100, result.moving, result.total ); }); // init camera and discard first 2 frames camera.begin(); camera.raise(); camera.discard(2); // motion doesn't require init } void loop() { auto image = camera.grab(); if (image.failed()) { Serial.print("Camera error: "); Serial.println(image.error); return; } motion.update(image); if (motion.failed()) { Serial.print("Motion error: "); Serial.println(motion.error); return; } // check how much of the image changed // also, don't fire too many events (throttle) if (motion.result.ratio > 0.3 && throttle) { Serial.printf( "%.0f%% of the image changed (%d/%d)\n", motion.result.ratio * 100, motion.result.moving, motion.result.total ); Serial.printf( "Center of mass at x=%d, y=%d\n", motion.result.centerOfMass.x, motion.result.centerOfMass.y ); // start counting time from now // no event will trigger for the next 3 seconds throttle.touch(); } delay(100); }