The Sensing Principle: Edge Vision vs. Thermal Deltas
The Useful Sensors Person Sensor is a smart optical module that pairs a low-resolution CMOS imaging array with an onboard microcontroller running a pre-trained Convolutional Neural Network (CNN). Unlike passive infrared (PIR) sensors that merely detect thermal deltas in a room, or mmWave radar that bounces radio waves off physical mass, this module captures actual visual data and performs edge inference to identify human faces and calculate their precise bounding boxes.
Because the inference happens entirely on the module's internal silicon—typically leveraging an Edge Impulse-optimized model—your host microcontroller only receives structured, post-processed data over the I2C bus. It outputs the number of detected faces, confidence scores, and normalized coordinate boxes, completely offloading the heavy computational burden of computer vision from your ESP32 or Raspberry Pi and reducing your code to simple byte-parsing.
Wiring and I2C Pinout Specifications
The module operates strictly as an I2C slave device. The default I2C address is 0x62. Because the onboard logic runs at 3.3V, you must ensure your host microcontroller's I2C bus is also operating at 3.3V logic levels. If you are using a 5V Arduino Uno, you will need a logic level converter on the SDA and SCL lines to avoid degrading the sensor's internal pull-ups or damaging the I/O pads.
| Module Pin | Function | ESP32 Connection | Hardware Notes & Supply Range |
|---|---|---|---|
| VCC | Power Supply | 3V3 | Strictly 3.3V to 3.6V. 5V will destroy the onboard LDO. |
| GND | Ground Reference | GND | Must share a common ground with the host MCU. |
| SDA | I2C Data Line | GPIO 21 | Requires 4.7kΩ pull-up to 3.3V if trace/wire length > 10cm. |
| SCL | I2C Clock Line | GPIO 22 | Max I2C clock speed is 400 kHz (Fast Mode). |
Decoding the Output: Raw Bytes to Physical Coordinates
The output of the Person Sensor is strictly digital. It does not output a raw camera frame; it outputs a structured byte array representing the inference results. When you initiate an I2C read from address 0x62, the sensor returns a payload containing a header, the number of detected faces, and an array of face structures.
The Raw-to-Unit Math
The bounding box coordinates (box_left, box_top, box_width, box_height) are returned as 8-bit unsigned integers ranging from 0 to 255. These do not represent pixels; they represent a normalized percentage of the sensor's Field of View (FOV). To convert these raw bytes into physical angles or real-world dimensions, you must apply scaling math based on the lens optics.
For the standard Useful Sensors module, the horizontal FOV is approximately 110° and the vertical FOV is roughly 90°.
// Raw to Angle Conversion
float horizontal_angle_deg = (raw_box_left / 255.0) * 110.0;
float vertical_angle_deg = (raw_box_top / 255.0) * 90.0;
// Angle to Physical Offset (if distance is known via separate ToF sensor)
float distance_cm = 150.0; // Example: 1.5 meters away
float horizontal_offset_cm = distance_cm * tan(horizontal_angle_deg * PI / 180.0);
Calibration and Scaling Requirements
There are no hardware potentiometers or physical calibration registers on this module. Calibration is entirely software-defined. If you are mounting the sensor behind a custom 3D-printed bezel that restricts the lens view, you must empirically map the 0-255 output to your restricted physical FOV by placing a target at the extreme left and right edges of your bezel and logging the raw byte values to establish your custom multiplier.
Common Interference Sources and Edge Cases
Because the Person Sensor relies on optical CNN inference, it is subject to environmental factors that do not affect RF or thermal sensors. Expect degraded performance or false negatives in the following scenarios:
- Severe Backlighting: If a subject is standing directly in front of a bright, sunlit window, the CMOS sensor will auto-adjust exposure, rendering the subject's face as a dark silhouette. The CNN will fail to detect facial landmarks.
- Glass and Mirror Reflections: Pointing the sensor toward a mirror or highly reflective glass will cause the model to detect the reflection as a second person, resulting in phantom bounding boxes and skewed coordinate averaging.
- Low Lux Environments: The standard visible-light module requires a minimum of ~50 lux to form a usable image. In pitch-black rooms, the sensor will output a face count of zero. (For dark environments, you must switch to an IR-illuminated variant or use a PIR/mmWave fallback).
- IR Interference: If you are using the IR-illuminated version of the sensor, direct sunlight contains massive amounts of IR noise that will wash out the active illumination, blinding the sensor outdoors.
Decision Matrix: Person Sensor vs. PIR vs. mmWave
Choosing the right presence sensor is the most common point of failure in smart home DIY projects. Use this decision tree to select the correct hardware for your specific application.
| Criteria | HC-SR501 (PIR) | HLK-LD2410 (mmWave) | Useful Sensors Person Sensor |
|---|---|---|---|
| Detects Static Presence? | No (Motion only) | Yes (Micro-movements) | Yes (Visual confirmation) |
| Detects Face Direction? | No | No | Yes (Bounding box centering) |
| Works Through Drywall? | No | Yes | No (Line of sight required) |
| Typical Cost (2026) | ~$2.00 | ~$6.00 | ~$12.00 - $15.00 |
| Host CPU Load | Negligible (GPIO) | Low (UART parsing) | Low (I2C byte reading) |
ESP32 Implementation: Numbered Integration Steps
Below is the practical workflow for reading face data on an ESP32 using the Arduino core. For deeper protocol details, always refer to the Useful Sensors Official GitHub Documentation and the NXP I2C Bus Specification.
- Initialize I2C: Set the ESP32 Wire clock to 400,000 Hz. Standard 100 kHz mode often results in buffer timeouts with this specific sensor payload size.
- Ping the Address: Verify the sensor is present at
0x62before attempting to parse structs. - Read the Header: Request the first few bytes to determine how many faces are currently in the frame.
- Parse the Structs: Iterate through the payload and map the raw 0-255 bytes to your application logic.
#include <Wire.h>
#define SENSOR_ADDRESS 0x62
#define SENSOR_FOV_H 110.0
typedef struct {
uint8_t box_left;
uint8_t box_top;
uint8_t box_width;
uint8_t box_height;
uint8_t confidence;
} person_sensor_face_t;
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
Wire.setClock(400000); // Force 400kHz Fast Mode
delay(1000); // Allow sensor CNN to boot and stabilize
}
void loop() {
Wire.requestFrom(SENSOR_ADDRESS, 1); // Request face count
if (Wire.available()) {
uint8_t face_count = Wire.read();
if (face_count > 0) {
// Request the specific payload size for the detected faces
int payload_size = face_count * sizeof(person_sensor_face_t);
Wire.requestFrom(SENSOR_ADDRESS, payload_size);
for (int i = 0; i < face_count; i++) {
person_sensor_face_t face;
Wire.readBytes((uint8_t*)&face, sizeof(face));
// Apply Raw-to-Unit Math
float angle_h = (face.box_left / 255.0) * SENSOR_FOV_H;
Serial.printf("Face %d: Conf %d%%, H-Angle: %.1f deg\n",
i, face.confidence, angle_h);
}
}
}
delay(250); // ~4 FPS read rate is sufficient for presence tracking
}
By handling the optical inference on the edge, the Person Sensor allows you to build highly responsive, vision-aware embedded systems without needing to attach bulky camera modules or manage complex Python-based OpenCV pipelines on your host controller.






