Complete Environmental Monitoring System
Combine multiple sensor types for comprehensive environmental monitoring:#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_RTC_DS3231_V2
#define ENABLE_SENSOR_BME680_V2
#define ENABLE_SENSOR_GP2Y_DUST_V2
#define ENABLE_SENSOR_MQ_V2
#define ENABLE_SENSOR_UTILITY_V2
#include "Kinematrix.h"
SensorModuleV2 sensorModule;
void setup() {
Serial.begin(115200);
Serial.println("RTC and Environmental Sensors Example");
// Add multiple sensor types
sensorModule.addSensor("rtc", new RTCDS3231SensV2());
sensorModule.addSensor("bme680", new BME680SensV2());
sensorModule.addSensor("dust", new GP2YDustSensV2(GP2Y1010AU0F, 7, A3));
sensorModule.addSensor("mq2", new MQSensV2("Arduino", 5.0, 10, A2, "MQ-2"));
sensorModule.init();
// Enable RTC temperature reading
RTCDS3231SensV2* rtc = (RTCDS3231SensV2*)sensorModule.getSensorByName("rtc");
if (rtc) {
rtc->enableTemperature(true);
}
Serial.println("RTC and environmental monitoring started");
}
void loop() {
sensorModule.update();
if (sensorModule.isUpdated("rtc")) {
Serial.print("Time: ");
Serial.print((int)sensorModule["rtc"]["hour"]);
Serial.print(":");
Serial.print((int)sensorModule["rtc"]["minute"]);
Serial.print(":");
Serial.println((int)sensorModule["rtc"]["second"]);
}
if (sensorModule.isUpdated("bme680")) {
Serial.print("BME680 - Temp: ");
Serial.print((float)sensorModule["bme680"]["temperature"]);
Serial.print("°C, Humidity: ");
Serial.print((float)sensorModule["bme680"]["humidity"]);
Serial.println("%");
}
if (sensorModule.isUpdated("dust")) {
Serial.print("Dust: ");
Serial.print((float)sensorModule["dust"]["density"]);
Serial.println(" μg/m³");
}
delay(2000);
}
/home/daytona/workspace/source/example/sensors/SensorModuleV2/SensorModule/SensorModuleV2/RTCandEnvironmentalSensors/RTCandEnvironmentalSensors.ino:1
Multi-Sensor with Filters and Alerts
Combine different sensor types with advanced filtering:#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_FILTER_V2
#define ENABLE_SENSOR_DHT_V2
#define ENABLE_SENSOR_ANALOG_V2
#define ENABLE_SENSOR_BME680_V2
#define ENABLE_SENSOR_MQ_V2
#define ENABLE_SENSOR_UTILITY_V2
#include "Kinematrix.h"
SensorModuleV2 sensorModule;
void setup() {
Serial.begin(115200);
Serial.println("Multi Sensor with Filters Example");
// Add diverse sensor types
sensorModule.addSensor("dht", new DHTSensV2(2, DHT22));
sensorModule.addSensor("analog1", new AnalogSensV2(A0, 5.0, 1023));
sensorModule.addSensor("analog2", new AnalogSensV2(A1, 3.3, 1023));
sensorModule.addSensor("bme680", new BME680SensV2());
sensorModule.addSensor("mq135", new MQSensV2("Arduino", 5.0, 10, A2, "MQ-135"));
sensorModule.init();
// Apply moving average filter to analog sensor
FilterParams movingAvgParams;
movingAvgParams.movingAverage.windowSize = 5;
sensorModule.attachFilter("analog1", "volt", FILTER_MOVING_AVERAGE, movingAvgParams);
// Apply Kalman filter to temperature
FilterParams kalmanParams;
kalmanParams.kalman.processNoise = 0.01;
kalmanParams.kalman.measurementNoise = 0.1;
sensorModule.attachFilter("dht", "temperature", FILTER_KALMAN, kalmanParams);
Serial.println("Filters attached to sensors");
}
void loop() {
sensorModule.update();
if (sensorModule.isUpdated("dht")) {
float temp = sensorModule.getFilteredValue("dht", "temperature");
Serial.print("Filtered Temperature: ");
Serial.println(temp);
}
if (sensorModule.isUpdated("analog1")) {
float volt = sensorModule.getFilteredValue("analog1", "volt");
Serial.print("Filtered Voltage: ");
Serial.println(volt);
}
delay(2000);
}
/home/daytona/workspace/source/example/sensors/SensorModuleV2/SensorModule/SensorModuleV2/MultiSensorWithFilters/MultiSensorWithFilters.ino:1
Advanced Calibration System
Manage calibration across multiple sensor types:#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_CALIBRATION_MODULE_V2
#define ENABLE_SENSOR_ANALOG_V2
#define ENABLE_SENSOR_MLX90614_V2
#define ENABLE_SENSOR_INA219_V2
#include "Kinematrix.h"
SensorCalibrationModuleV2 calibrationModule;
void setup() {
Serial.begin(115200);
Serial.println("Multiple Calibration Types Example");
// Add different sensor types
calibrationModule.addSensor("analog1", new AnalogSensV2(A0, 5.0, 1023));
calibrationModule.addSensor("analog2", new AnalogSensV2(A1, 3.3, 1023));
calibrationModule.addSensor("analog3", new AnalogSensV2(A2, 5.0, 1023));
calibrationModule.addSensor("mlx90614", new MLX90614SensV2());
calibrationModule.addSensor("ina219", new INA219SensV2());
calibrationModule.init();
// Add calibration entries for each sensor value
calibrationModule.addCalibrationEntry("analog1", "volt");
calibrationModule.addCalibrationEntry("analog2", "volt");
calibrationModule.addCalibrationEntry("analog3", "volt");
calibrationModule.addCalibrationEntry("mlx90614", "objectTemp");
calibrationModule.addCalibrationEntry("mlx90614", "ambientTemp");
calibrationModule.addCalibrationEntry("ina219", "power");
// Apply different calibration methods
calibrationModule.calibrateOnePoint("analog1", "volt", 3.3);
calibrationModule.calibrateTwoPoint("analog2", "volt", 1.0, 0.95, 4.0, 4.08);
calibrationModule.calibrateOnePoint("analog3", "volt", 2.5);
calibrationModule.calibrateTwoPoint("mlx90614", "objectTemp", 25.0, 24.8, 80.0, 80.5);
calibrationModule.calibrateTwoPoint("mlx90614", "ambientTemp", 25.0, 24.8, 80.0, 80.5);
calibrationModule.calibrateOnePoint("ina219", "power", 5.0);
Serial.println("Multiple calibration types configured");
}
void loop() {
calibrationModule.update();
if (calibrationModule.isUpdated("analog1")) {
Serial.print("A1 Linear - Raw: ");
Serial.print((float)calibrationModule["analog1"]["volt"]);
Serial.print("V, Cal: ");
Serial.print((float)calibrationModule.getCalibratedValue("analog1", "volt"));
Serial.println("V");
}
if (calibrationModule.isUpdated("analog2")) {
Serial.print("A2 TwoPoint - Raw: ");
Serial.print((float)calibrationModule["analog2"]["volt"]);
Serial.print("V, Cal: ");
Serial.print((float)calibrationModule.getCalibratedValue("analog2", "volt"));
Serial.println("V");
}
if (calibrationModule.isUpdated("mlx90614")) {
Serial.print("MLX Temp - Raw: ");
Serial.print((float)calibrationModule["mlx90614"]["objectTemp"]);
Serial.print("°C, Cal: ");
Serial.print((float)calibrationModule.getCalibratedValue("mlx90614", "objectTemp"));
Serial.println("°C");
}
delay(2000);
}
/home/daytona/workspace/source/example/sensors/SensorModuleV2/SensorModule/SensorModuleCalibrationV2/MultipleCalibrationTypes/MultipleCalibrationTypes.ino:1
Multiple Abstract Sensors
Use abstract sensors for testing and simulation:#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_ABSTRACT_V2
#define ENABLE_SENSOR_UTILITY_V2
#include "Kinematrix.h"
SensorModuleV2 sensorModule;
void setup() {
Serial.begin(115200);
Serial.println("Multiple AbstractSensV2 Example");
// Different abstract sensor modes
sensorModule.addSensor("random", new AbstractSensV2(0)); // Random values
sensorModule.addSensor("fixed", new AbstractSensV2(1, 42.5)); // Fixed value
sensorModule.addSensor("range1", new AbstractSensV2(2, 100.0)); // Range 0-100
sensorModule.addSensor("range2", new AbstractSensV2(3, 20.0, 80.0)); // Range 20-80
sensorModule.init();
// Configure update intervals
AbstractSensV2* randomSensor = (AbstractSensV2*)sensorModule.getSensorByName("random");
if (randomSensor) randomSensor->setUpdateInterval(500);
AbstractSensV2* fixedSensor = (AbstractSensV2*)sensorModule.getSensorByName("fixed");
if (fixedSensor) fixedSensor->setUpdateInterval(1000);
Serial.println("Multiple abstract sensors with different modes initialized");
}
void loop() {
sensorModule.update();
if (sensorModule.isUpdated("random")) {
Serial.print("Random Mode - Value: ");
Serial.print((float)sensorModule["random"]["value"]);
Serial.print(", Sine: ");
Serial.println((float)sensorModule["random"]["sine"]);
}
if (sensorModule.isUpdated("fixed")) {
Serial.print("Fixed Mode - Value: ");
Serial.print((float)sensorModule["fixed"]["value"]);
Serial.print(", Triangle: ");
Serial.println((float)sensorModule["fixed"]["triangle"]);
}
if (sensorModule.isUpdated("range1")) {
Serial.print("Range1 (0-100) - Value: ");
Serial.println((float)sensorModule["range1"]["value"]);
}
if (sensorModule.isUpdated("range2")) {
Serial.print("Range2 (20-80) - Value: ");
Serial.println((float)sensorModule["range2"]["value"]);
}
delay(200);
}
/home/daytona/workspace/source/example/sensors/SensorModuleV2/SensorList/AbstractSensV2/MultipleAbstractSensors/MultipleAbstractSensors.ino:1
System Architecture Best Practices
Organize Sensors by Function
Group related sensors together:
// Environmental sensors
sensorModule.addSensor("temp_indoor", new DHTSensV2(2, DHT22));
sensorModule.addSensor("temp_outdoor", new BME680SensV2());
// Power monitoring
sensorModule.addSensor("power_main", new INA219SensV2());
sensorModule.addSensor("power_backup", new INA219SensV2(0x41));
// Analog inputs
sensorModule.addSensor("pressure", new AnalogSensV2(A0, 5.0, 1023));
sensorModule.addSensor("flow", new AnalogSensV2(A1, 5.0, 1023));
Apply Appropriate Filters
Choose filters based on sensor characteristics:
// Slow-changing values: Moving Average
FilterParams movingAvg;
movingAvg.movingAverage.windowSize = 10;
sensorModule.attachFilter("temp_indoor", "temperature", FILTER_MOVING_AVERAGE, movingAvg);
// Fast-changing values: Kalman
FilterParams kalman;
kalman.kalman.processNoise = 0.01;
kalman.kalman.measurementNoise = 0.1;
sensorModule.attachFilter("pressure", "volt", FILTER_KALMAN, kalman);
Set Up Alert Thresholds
Configure alerts for critical values:
// Temperature alerts (outside range)
sensorModule.setThreshold("temp_indoor", "temperature", 18.0, 26.0, ALERT_OUTSIDE);
// Pressure alerts (above threshold)
sensorModule.setThreshold("pressure", "volt", 4.5, 5.0, ALERT_ABOVE);
// Flow alerts (below threshold)
sensorModule.setThreshold("flow", "volt", 0.5, 1.0, ALERT_BELOW);
Performance Considerations
Update Intervals
Optimize sensor update rates based on requirements:// Fast sensors (100ms)
analogSensor->setUpdateInterval(100);
// Medium sensors (1s)
dhtSensor->setUpdateInterval(1000);
// Slow sensors (5s)
bme680Sensor->setUpdateInterval(5000);
Memory Management
// Use pointers for dynamic sensor creation
BME680SensV2* bme = new BME680SensV2();
sensorModule.addSensor("bme680", bme);
// SensorModule manages memory automatically
// No need to delete manually
Checking Updates Efficiently
void loop() {
sensorModule.update(); // Update all sensors once
// Only process sensors that have new data
if (sensorModule.isUpdated("sensor1")) {
// Process sensor1 data
}
if (sensorModule.isUpdated("sensor2")) {
// Process sensor2 data
}
}
Complete System Example
Hardware Setup
ESP32 Connections:
I2C Bus:
- BME680: SDA=21, SCL=22, Addr=0x76
- RTC DS3231: SDA=21, SCL=22, Addr=0x68
- MLX90614: SDA=21, SCL=22, Addr=0x5A
Digital:
- DHT22: GPIO 2 (with 10kΩ pull-up)
Analog:
- Pressure Sensor: A0 (0-5V)
- Flow Sensor: A1 (0-5V)
- Gas Sensor MQ-135: A2 (0-5V)
Software Integration
#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_CALIBRATION_MODULE_V2
#define ENABLE_SENSOR_FILTER_V2
#define ENABLE_SENSOR_ALERT_SYSTEM_V2
#define ENABLE_SENSOR_BME680_V2
#define ENABLE_SENSOR_DHT_V2
#define ENABLE_SENSOR_ANALOG_V2
#define ENABLE_SENSOR_RTC_DS3231_V2
#define ENABLE_SENSOR_UTILITY_V2
#include "Kinematrix.h"
SensorCalibrationModuleV2 sensorSystem;
void setup() {
Serial.begin(115200);
// Add all sensors
sensorSystem.addSensor("bme680", new BME680SensV2());
sensorSystem.addSensor("dht22", new DHTSensV2(2, DHT22));
sensorSystem.addSensor("rtc", new RTCDS3231SensV2());
sensorSystem.addSensor("pressure", new AnalogSensV2(A0, 5.0, 4095));
sensorSystem.addSensor("flow", new AnalogSensV2(A1, 5.0, 4095));
sensorSystem.init();
// Configure filters
FilterParams kalman;
kalman.kalman.processNoise = 0.01;
kalman.kalman.measurementNoise = 0.1;
sensorSystem.attachFilter("bme680", "temperature", FILTER_KALMAN, kalman);
sensorSystem.attachFilter("pressure", "volt", FILTER_KALMAN, kalman);
// Configure alerts
sensorSystem.setThreshold("bme680", "temperature", 18.0, 28.0, ALERT_OUTSIDE);
sensorSystem.setThreshold("pressure", "volt", 4.0, 5.0, ALERT_ABOVE);
// Apply calibration
sensorSystem.addCalibrationEntry("pressure", "volt");
sensorSystem.calibrateTwoPoint("pressure", "volt", 1.0, 0.95, 4.0, 4.08);
Serial.println("Multi-sensor system initialized");
}
void loop() {
sensorSystem.update();
// Process each sensor type
if (sensorSystem.isUpdated("bme680")) {
float temp = sensorSystem.getFilteredValue("bme680", "temperature");
bool alert = sensorSystem.isAlertActive("bme680", "temperature");
Serial.printf("BME680: %.2f°C [Alert: %s]\n", temp, alert ? "YES" : "NO");
}
if (sensorSystem.isUpdated("pressure")) {
float cal = sensorSystem.getCalibratedValue("pressure", "volt");
Serial.printf("Pressure: %.2fV (calibrated)\n", cal);
}
delay(1000);
}
Next Steps
Environmental Monitoring
Focus on environmental sensor applications
Analog Sensors
Deep dive into analog sensor processing
Digital Sensors
Master I2C and digital protocols