——
#DonLucElectronics #DonLuc #RTC #C4002 #BME280 #ENS160 #Environment #FireBeetle2ESP32E #ESP32 #Display #IoT #Project #Fritzing #Programming #Electronics #Microcontrollers #Consultant
——
——
—
——
Gravity: I2C SD2405 RTC Module
The I2C SD2405 RTC module features accurate real-time clock, dual power supply, low power consumption, periodic interrupts, and a high precision time trimming circuit. The SD2405AL is dual power supply system. When the primary power supply goes down to an assigned value or resumes from low power, the system can switch between the primary power supply and battery automatically. Even there is no external power, it can still work for 5~8 years, 1uA ultra-low power consumption.
DL2609Mk03
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 Gravity: I2C SD2405 RTC Module
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
DL2609Mk03p
DL2609Mk03p.ino
/****** Don Luc Electronics © ******
Software Version Information
Project #15: Environment – RTC – Mk50
15-50
DL2609Mk03p.ino
DL2609Mk03
1 x DFRobot FireBeetle 2 ESP32-E
1 x Fermion: 3.5” 480x320 TFT LCD Capacitive
1 x GDL Line 10 CM
1 x Gravity: I2C SD2405 RTC Module
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>
// RTC (Real-Time Clock)
#include "GravityRtc.h"
// RTC Initialization
GravityRtc rtc;
// Date and Time
String dateRTC = "";
String timeRTC = "";
// 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-50";
void loop() {
// isBME280
isBME280();
// isENS160
isENS160();
// isC4002
isC4002();
// RTC (Real-Time Clock)
isRTC();
// 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("Real-Time Clock");
// 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("Real-Time Clock");
// 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" );
// Real-Time Clock
screen.setCursor(0, 300);
screen.print( dateRTC );
screen.setCursor(250, 300);
screen.println( timeRTC );
//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();
}
getRTC.ino
// Real-Time Clock
// Date and Time RTC
void isRTC () {
// Date and Time
dateRTC = "";
timeRTC = "";
rtc.read();
// Date
dateRTC = rtc.year;
dateRTC = dateRTC + "/";
dateRTC = dateRTC + rtc.month;
dateRTC = dateRTC + "/";
dateRTC = dateRTC + rtc.day;
// Time
timeRTC = rtc.hour;
timeRTC = timeRTC + ":";
timeRTC = timeRTC + rtc.minute;
timeRTC = timeRTC + ":";
timeRTC = timeRTC + rtc.second;
}
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 );
// Setup RTC
rtc.setup();
//Set the RTC time automatically: Calibrate RTC time by your computer time
rtc.adjustRtc(F(__DATE__), F(__TIME__));
// 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


