DEV Community

Beck_Moulton
Beck_Moulton

Posted on

AI-Powered Smart Pillbox: Deploying TinyML on ESP32-CAM with TensorFlow Lite Micro

Forget expensive cloud subscriptions and privacy-invading cameras. Today, we are bringing Edge AI straight to your bedside.

Medication non-compliance is a billion-dollar problem, but building a solution doesn't have to cost a fortune. In this tutorial, we’re building Smart Pillbox 2.0, an offline, low-power monitoring system. By leveraging TensorFlow Lite Micro and the $10 ESP32-CAM, we will deploy a custom computer vision model to detect whether a patient has taken their meds in real-time. This is TinyML at its finest—high-performance intelligence on a device with less RAM than a single tab of Chrome.

If you are looking to master embedded machine learning, computer vision on the edge, and ESP32 programming, you’re in the right place.


The Architecture: Intelligence at the Edge

Traditional IoT systems send video streams to the cloud, causing latency and privacy concerns. Our "Smart Pillbox" architecture processes everything locally.

The ESP32-CAM captures a frame, crops the Region of Interest (ROI) where the pills are stored, runs it through a quantized TensorFlow Lite model, and triggers an alert if the pill is still there after the scheduled time.

graph TD
    A[ESP32-CAM Wake-up] --> B[Capture Image]
    B --> C[Image Preprocessing / Resizing]
    C --> D{TFLite Micro Inference}
    D -->|Pill Detected| E[Compliance Log: Taken]
    D -->|Pill Missing| F[Compliance Log: Missing/Error]
    E --> G[Deep Sleep Mode]
    F --> H[Trigger Alert/LED]
    H --> G

    subgraph "On-Device Processing"
    C
    D
    end
Enter fullscreen mode Exit fullscreen mode

Prerequisites

To follow this advanced guide, you’ll need:

  • Hardware: ESP32-CAM (AI-Thinker module) + FTDI Programmer.
  • Tech Stack:
    • TensorFlow Lite Micro (TFLM) for inference.
    • Edge Impulse for dataset management and DSP.
    • C++ (Arduino IDE or ESP-IDF).
    • Python (for initial data augmentation).

Step 1: Dataset Engineering & Training

You can't just throw a 50MB ResNet model at an ESP32. We need a MobileNetV1 0.1 or a custom FOMO (Faster Objects, More Objects) model.

  1. Capture: Use the ESP32-CAM itself to take 100 photos of your pillbox (Empty vs. Full).
  2. Labeling: Use Edge Impulse to draw bounding boxes.
  3. Optimization: Quantize the model from float32 to int8. This reduces the model size by 4x and increases inference speed drastically on the ESP32's Xtensa processor.

Step 2: Setting Up the TFLite Micro Inference Loop

The "magic" happens in the tensor_arena. Since the ESP32 has limited internal RAM, we often have to utilize the PSRAM for our model weights.

The Inference Code (C++)

Here is how you initialize the model and run a prediction on the captured frame:

#include <TensorFlowLite.h>
#include "model_data.h" // Your exported TFLite model as a byte array
#include "esp_camera.h"

// Define the size of the memory pool for the model
const int kTensorArenaSize = 128 * 1024; 
uint8_t tensor_arena[kTensorArenaSize];

void setup() {
    Serial.begin(115200);

    // Load the TFLite model
    model = tflite::GetModel(g_pill_detection_model_data);

    // Pull in the operations needed (optimizes flash usage)
    static tflite::MicroMutableOpResolver<5> resolver;
    resolver.AddConv2D();
    resolver.AddMaxPool2D();
    resolver.AddFullyConnected();
    resolver.AddSoftmax();
    resolver.AddReshape();

    // Build the interpreter
    static tflite::MicroInterpreter static_interpreter(
        model, resolver, tensor_arena, kTensorArenaSize);
    interpreter = &static_interpreter;

    // Allocate tensors
    interpreter->AllocateTensors();
}

void loop() {
    camera_fb_t * fb = esp_camera_fb_get();
    if (!fb) return;

    // 1. Pre-process: Resize 160x160 and normalize
    // 2. Fill input tensor
    uint8_t* input_data = interpreter->input(0)->data.uint8;
    memcpy(input_data, fb->buf, fb->len);

    // 3. Run Inference
    TfLiteStatus invoke_status = interpreter->Invoke();

    // 4. Analyze Results
    float score = interpreter->output(0)->data.f[0];
    if (score > 0.8) {
        Serial.println("✅ Pill Detected! Compliance confirmed.");
    } else {
        Serial.println("⚠️ Pill Missing! Sending Alert...");
    }

    esp_camera_fb_return(fb);
    delay(10000); // Check every 10 seconds or use deep sleep
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Overcoming Hardware Limitations

The ESP32-CAM is notorious for brownouts. To ensure "Smart Pillbox 2.0" is production-ready, you must:

  • Disable WiFi during inference to save power and prevent voltage drops.
  • Use PSRAM: If your model is larger than 200KB, use heap_caps_malloc(kTensorArenaSize, MALLOC_CAP_SPIRAM).
  • Lighting Matters: Use the onboard flash LED (GPIO 4) to normalize lighting conditions before taking the photo.

The "Official" Way: Professional Edge AI Patterns

While this DIY approach is great for prototyping, scaling a computer vision product requires robust MLOps and cloud-to-edge synchronization. For more production-ready examples and advanced patterns on deploying AI to constrained environments, I highly recommend checking out the technical deep-dives at WellAlly Blog. They cover the intersection of healthcare tech and robust software architecture that goes far beyond a weekend project.


Conclusion: TinyML is the Future 🥑

We just turned a $10 piece of silicon into a life-saving medical monitor. By moving the "brain" to the device, we've created a system that is:

  1. Private: No images ever leave the device.
  2. Cheap: No monthly cloud processing fees.
  3. Reliable: Works even if the WiFi goes down.

What are you building next? Drop a comment below if you want the full schematics for the low-power battery circuit! 🚀

Top comments (0)