——
#DonLucElectronics #DonLuc #C4002 #BME280 #ENS160 #Environment #FireBeetle2ESP32E #ESP32 #Display #IoT #Project #Fritzing #Programming #Electronics #Microcontrollers #Consultant
——
——
——
——
C4002 – BME280 – ENS160 Air Quality
Capable of detecting individuals who are sitting, sleeping, or standing completely still. Ideal for bedrooms, offices, and bathrooms.
Motion Detection: Up to 11m (Walking / Running).
Static Detection: Up to 10m (Reading / Typing / Sleeping).
Smart Lighting Automation: Maintains lighting based on true presence (breathing/micro-motion) rather than large movements, solving the problem of lights turning off while reading or working.
Privacy-Friendly Elderly Care: Detects presence or prolonged inactivity in bedrooms or bathrooms without the need for invasive cameras or wearable devices.
Plug-and-Play Smart Home Integration: BME280 Environmental Compensation. Integrated barometric sensor automatically corrects ENS160 readings for altitude and weather effects, improving accuracy by 30% versus standalone sensors.
To prevent false triggers common in radar technology (e.g., swaying plants, moving curtains), the C4002 incorporates adaptive background noise learning. The module automatically establishes a noise model of the environment, filtering out non-human interference to ensure triggers occur only upon actual human presence.
DL2609Mk02
1 x DFRobot FireBeetle 2 ESP32-E
1 x Fermion: 3.5” 480×320 TFT LCD Capacitive
1 x GDL Line 10 CM
1 x Fermion: C4002 mmWave Human Presence Sensor
1 x Fermion: ENS160+BME280 Envirotal Sensor
1 x Gravity: IO Shield for FireBeetle 2
1 x Terminal Block Board for FireBeetle 2 ESP32-E IoT
1 x Lithium Ion Battery – 1000mAh
1 x USB 3.0 to Type-C Cable
DL2609Mk02p
DL2609Mk02p.ino
/****** Don Luc Electronics © ******
Software Version Information
Project #15: Environment – C4002 - BME280 - ENS160 Air Quality – Mk49
15-49
DL2609Mk02p.ino
DL2609Mk02
1 x DFRobot FireBeetle 2 ESP32-E
1 x Fermion: 3.5” 480x320 TFT LCD Capacitive
1 x GDL Line 10 CM
1 x Fermion: C4002 mmWave Human Presence Sensor
1 x Fermion: ENS160+BME280 Envirotal Sensor
1 x Gravity: IO Shield for FireBeetle 2
1 x Terminal Block Board for FireBeetle 2 ESP32-E IoT
1 x Lithium Ion Battery - 1000mAh
1 x USB 3.0 to Type-C Cable
*/
// Include the Library Code
// DFRobot Display GDL API
#include <DFRobot_GDL.h>
// C4002 mmWave Human Presence
#include "DFRobot_C4002.h"
// BME280 Environmental
#include <DFRobot_BME280.h>
// ENS160 Air Quality Sensor
#include <DFRobot_ENS160.h>
// ENS160 Air Quality Sensor
// I2C communication.
#define I2C_COMMUNICATION
// I2C address is 0x53
DFRobot_ENS160_I2C ENS160(&Wire, 0x53);
// Status
uint8_t Status;
// AQI
uint8_t AQI;
// TVOC
uint16_t TVOC;
// ECO2
uint16_t ECO2;
// BME280 Environmental
typedef DFRobot_BME280_IIC BME;
// Wire
BME bme(&Wire, 0x76);
// Sea Level Pressure
#define SEA_LEVEL_PRESSURE 1015.0f
// Temperature
float temp = bme.getTemperature();
// Pressure
uint32_t press = bme.getPressure();
// Altitude
float alti;
// Humidity
float humi;
// C4002 mmWave Human Presence
DFRobot_C4002 c4002(&Serial1, 115200, /*D0*/ D11, /*D1*/ D10);
//float light;
String sLight;
// Get Target State
String sTarget;
// Get Presence distance gate target info
String sPreDis;
// Get motion distance gate index
String sMot;
// Defined ESP32
#define TFT_DC D2
#define TFT_CS D6
#define TFT_RST D3
/*dc=*/ /*cs=*/ /*rst=*/
// DFRobot Display 320x480
DFRobot_ILI9488_320x480_HW_SPI screen(TFT_DC, TFT_CS, TFT_RST);
// Software Version Information
String sver = "15-49";
void loop() {
// isBME280
isBME280();
// isENS160
isENS160();
// isC4002
isC4002();
// isDisplay C4002
isDisplayC4002();
// Delay 0.1 Second
delay( 100 );
}
getBME280.ino
// BME280 Environmental
// isBME280
void isBME280(){
// Temperature
temp = bme.getTemperature();
// Pressure
press = bme.getPressure();
// Altitude
alti = bme.calAltitude(SEA_LEVEL_PRESSURE, press);
// Humidity
humi = bme.getHumidity();
}
getC4002.ino
// C4002 mmWave Human Presence
// isSetupC4002
void isSetupC4002(){
// C4002 mmWave Human Presence
// Initialize the C4002 sensor
while (c4002.begin() != true) {
Serial.println("C4002 begin failed!");
delay(1000);
}
//Serial.println("C4002 begin success!");
delay(50);
// Set the run led to On
if (c4002.setRunLedState(eLedOn)) {
//Serial.println("Set run led success!");
} else {
Serial.println("Set run led failed!");
}
delay(50);
// Set the out led to On
if (c4002.setOutLedState(eLedOn)) {
//Serial.println("Set out led success!");
} else {
Serial.println("Set out led failed!");
}
delay(50);
// Set the Resolution mode to 20cm.
// eResolution20Cm: This indicates that the resolution of the "distance gate"
// is 20cm. With a resolution of 20 cm, it supports up to 25 distance gates,
//with a maximum distance of 4.9 meters
//c4002.setResolutionMode(eResolution20Cm);
if (c4002.setResolutionMode(eResolution20Cm)) {
//Serial.println("Set resolution mode success!");
} else {
Serial.println("Set resolution mode failed!");
}
delay(50);
// Set the detect range to 0-200 cm
uint16_t clostRange = 0;
uint16_t farRange = 200;
if (c4002.setDetectRange(clostRange, farRange)) { // Max detect range(0-1100cm)
//Serial.println("Set detect range success!");
} else {
Serial.println("Set detect range failed!");
}
// Set the light threshold to 0 lux.range: 0-50 lux
if (c4002.setLightThresh(0)) {
//Serial.println("Set light threshold success!");
} else {
Serial.println("Set light threshold failed!");
}
delay(50);
// Resolution mode:eResolution20Cm
// Enable the 'distance gate'
// Resolution mode:eResolution20Cm,This means that the number of 'distance gates'
// we can operate is 25
//disable : C4002_DISABLE, enable: C4002_ENABLE
uint8_t gateState[25] = { C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE,
C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE, C4002_ENABLE };
// Operation motion distance gate
if (c4002.configureGate(eMotionDistGate, gateState)) {
//Serial.println("Enable motion distance gate success!");
}
// Delay
delay(50);
// Operation presence distance gate
if (c4002.configureGate(ePresenceDistGate, gateState)) {
//Serial.println("Enable presence distance gate success!");
}
// Delay
delay(50);
// Set the target disappear delay time to 1s,range: 0-65535s
if (c4002.setTargetDisappearDelay(1)) {
//Serial.println("Set target disappear delay time success!");
} else {
Serial.println("Set target disappear delay time failed!");
}
// Delay
delay(50);
// Set the report period to 10 * 0.1s = 1s
if (c4002.setReportPeriod(10)) {
//Serial.println("Set report period success!");
} else {
Serial.println("Set report period failed!");
}
}
// isC4002
void isC4002(){
// Get all the results of the C4002 sensor
sRetResult_t retResult = c4002.getNoteInfo();
if (retResult.noteType == eResult) {
//Serial.println("------- Get all results --------");
// get the light intensity
float light = c4002.getLightIntensity();
//Serial.print("Light: ");
//Serial.print(light);
//Serial.println(" lux");
sLight = light;
// get Target state
eTargetState_t targetState = c4002.getTargetState();
//Serial.print("Target state: ");
if (targetState == eNoTarget) {
//Serial.println("No Target");
sTarget = "No Target";
} else if (targetState == ePresence) {
//Serial.println("Static Presence");
sTarget = "Static Presence";
} else if (targetState == eMotion) {
//Serial.println("Motion");
sTarget = "Motion";
}
// Get Presence distance gate target info
sPresenceTarget_t presenceTarget = c4002.getPresenceTargetInfo();
//Serial.print("Presence distance: ");
//Serial.print(presenceTarget.distance);
sPreDis = presenceTarget.distance;
//Serial.println(" m");
// Get motion distance gate index
sMotionTarget_t motionTarget = c4002.getMotionTargetInfo();
//Serial.print("Motion direction: ");
if (motionTarget.direction == eAway) {
//Serial.println("Away!");
sMot = "Away!";
} else if (motionTarget.direction == eNoDirection) {
//Serial.println("No Direction!");
sMot = "No Direction!";
} else if (motionTarget.direction == eApproaching) {
//Serial.println("Approaching!");
sMot = "Approaching!";
}
}
}
getDisplay.ino
// DFRobot Display 320x480
// DFRobot Display 320x480 - UID
void isDisplayUID(){
// DFRobot Display 240x320
// Text Display
// Text Wrap
screen.setTextWrap(false);
// Rotation
screen.setRotation(3);
// Fill Screen => black
screen.fillScreen(0x0000);
// Text Color => white
screen.setTextColor(0xffff);
// Font => Free Sans Bold 12pt
screen.setFont(&FreeSansBold12pt7b);
// TextSize => 1.5
screen.setTextSize(1.5);
// Don Luc Electronics
screen.setCursor(0, 30);
screen.println("Don Luc Electronics");
// BME280 Environmental
screen.setCursor(0, 60);
screen.println("C4002 - BME280 - ENS160 Air Quality");
// Version
screen.setCursor(0, 90);
screen.println("Version");
screen.setCursor(0, 120);
screen.println( sver );
}
// isDisplay C4002
void isDisplayC4002(){
// DFRobot Display 320x480
// Text Display
// Text Wrap
screen.setTextWrap(false);
// Rotation
screen.setRotation(3);
// Fill Screen => white
screen.fillScreen(0xffff);
// Text Color => blue
screen.setTextColor(0x001F);
// Font => Free Sans Bold 12pt
screen.setFont(&FreeSansBold12pt7b);
// TextSize => 1.5
screen.setTextSize(1.5);
// ENS160 Air Quality Sensor
screen.setCursor(0, 30);
screen.println("C4002 - BME280 - ENS160 Air Quality");
// Status
screen.setCursor(0, 60);
screen.print("Light ");
screen.setCursor(70, 60);
screen.print( sLight );
screen.setCursor(250, 60);
screen.println("lux");
// Target
screen.setCursor(0, 90);
screen.print("Target ");
screen.setCursor(90, 90);
screen.println( sTarget );
// Presence
screen.setCursor(0, 120);
screen.print("Presence: ");
screen.setCursor(130, 120);
screen.println( sPreDis );
screen.setCursor(250, 120);
screen.println( "CM" );
// Motion
screen.setCursor(0, 150);
screen.print("Motion: ");
screen.setCursor(110, 150);
screen.println( sMot );
// Temperature
screen.setCursor(0, 180);
screen.print("Temperature: ");
screen.setCursor(170, 180);
screen.println( temp );
screen.setCursor(250, 180);
screen.println( "C" );
// Humidity
screen.setCursor(0, 210);
screen.print("Humidity: ");
screen.setCursor(170, 210);
screen.println( humi );
screen.setCursor(250, 210);
screen.println( "%" );
// TVOC - Return value range: 0–65000, unit: ppb
screen.setCursor(0, 240);
screen.print("TVOC: ");
screen.setCursor(140, 240);
screen.println( TVOC );
screen.setCursor(250, 240);
screen.println( "ppb" );
// ECO2 = Return value range: 400–65000, unit: ppm
// Five levels: Excellent(400 - 600), Good(600 - 800), Moderate(800 - 1000),
// Poor(1000 - 1500), Unhealthy(> 1500)
screen.setCursor(0, 270);
screen.print("ECO2: ");
screen.setCursor(140, 270);
screen.println( ECO2 );
screen.setCursor(250, 270);
screen.println( "ppb" );
}
getENS160.ino
// ENS160 Air Quality Sensor
// isENS160
void isENS160(){
// Status - Return value: 0-Normal operation 1-Warm-Up phase
// 2-Initial Start-Up phase
Status = ENS160.getENS160Status();
// AQI - Return value: 1-Excellent, 2-Good, 3-Moderate, 4-Poor, 5-Unhealthy
AQI = ENS160.getAQI();
// TVOC - Return value range: 0–65000, unit: ppb
TVOC = ENS160.getTVOC();
// ECO2 = Return value range: 400–65000, unit: ppm
// Five levels: Excellent(400 - 600), Good(600 - 800), Moderate(800 - 1000),
// Poor(1000 - 1500), Unhealthy(> 1500)
ECO2 = ENS160.getECO2();
}
setup.ino
// Setup
void setup()
{
// Delay
delay(100);
Serial.begin(115200);
// Delay
delay( 100 );
// C4002 mmWave Human Presence
isSetupC4002();
// Delay
delay(100);
// BME280 Environmental
bme.begin();
// Delay
delay(100);
// ENS160 Air Quality Sensor
ENS160.begin();
/**
* Set power mode
* mode Configurable power mode:
* ENS160_SLEEP_MODE: DEEP SLEEP mode (low power standby)
* ENS160_IDLE_MODE: IDLE mode (low-power)
* ENS160_STANDARD_MODE: STANDARD Gas Sensing Modes
*/
ENS160.setPWRMode(ENS160_STANDARD_MODE);
/**
* Users write ambient temperature and relative humidity into ENS160 for
* calibration and compensation of the measured gas data.
* ambientTemp Compensate the current ambient temperature, float type, unit: C
* relativeHumidity Compensate the current ambient humidity, float type, unit: %rH
* Temperature
* Humidity=
*/
ENS160.setTempAndHum(temp, humi);
// Delay
delay( 100 );
// DFRobot Display 320x480
screen.begin();
// Delay
delay( 100 );
// DFRobot Display 320x480 - UID
// Don Luc Electronics
// Versioc
isDisplayUID();
// Delay
delay( 5000 );
}
——
People can contact us: https://www.donluc.com/?page_id=1927
Consultant, R&D, Electronics, IoT, Teacher and Instructor
- Programming Language
- Single-Board Microcontrollers (PIC, Arduino, Raspberry Pi, Arm, Silicon Labs, Espressif, Etc…)
- IoT
- Wireless (Radio Frequency, Bluetooth, WiFi, Etc…)
- Robotics
- Automation
- Camera and Video Capture Receiver Stationary, Wheel/Tank , Underwater and UAV Vehicle
- Unmanned Vehicles Terrestrial, Marine and UAV
- Machine Learning
- Artificial Intelligence (AI)
- RTOS
- Sensors, eHealth Sensors, Biosensor, and Biometric
- Research & Development (R & D)
- Consulting
Follow Us
Luc Paquin – Curriculum Vitae – 2026
https://www.donluc.com/luc/LucPaquinCVEng2026Mk01.pdf
https://www.donluc.com/luc/
Web: https://www.donluc.com/
Web: https://www.jlpconsultants.com/
Facebook: https://www.facebook.com/neosteam.labs.9/
YouTube: https://www.youtube.com/@thesass2063
DFRobot: https://learn.dfrobot.com/user-10186.html
TikTok: https://www.tiktok.com/@luc.paquin8
Hackster: https://www.hackster.io/luc-paquin
LinkedIn: https://www.linkedin.com/in/jlucpaquin/
Don Luc





























