Skip to main content

Overview

Sensor Module V2 is a modern, type-safe sensor management framework providing advanced features including real-time filtering, comprehensive alert systems, interactive calibration, and extensive debugging capabilities. Built with template-based APIs and optimized memory management.

Core Architecture

class BaseSensV2 {
public:
    virtual bool init() = 0;
    virtual bool update() = 0;
    virtual bool isUpdated() const { return false; }
    
    template<typename T> T getValue(const char *key) const;
    void updateValue(const char *key, float value);
    void addValueInfo(const char *key, const char *label, 
                     const char *unit, uint8_t precision, bool calibrable);
};

class SensorModuleV2 {
public:
    void addSensor(const char *name, BaseSensV2 *sensor);
    void init();
    void update();
    
    template<typename T> T getValue(const char *sensorName, const char *valueKey) const;
    bool isUpdated(const char *sensorName) const;
    
    // Alert system
    bool setThreshold(const char *sensorName, const char *valueKey,
                     float lowThreshold, float highThreshold, AlertType type);
    
    // Filter system
    bool attachFilter(const char *sensorName, const char *valueKey,
                     FilterType type, FilterParams params);
};

Supported Sensors (14+)

Environmental Sensors

Supports DHT11, DHT22, and DHT21 sensors.
#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_DHT_V2
#include "Kinematrix.h"

DHTSensV2 dht(2, DHT22);  // Pin 2, DHT22 type
dht.setUpdateInterval(2000);

void setup() {
    sensors.addSensor("dht", &dht);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("dht")) {
        float temp = sensors.getValue<float>("dht", "temperature");
        float humidity = sensors.getValue<float>("dht", "humidity");
        float heatIndex = sensors.getValue<float>("dht", "heatIndex");
    }
}
Available Values:
  • temperature - Temperature in Celsius
  • humidity - Relative humidity percentage
  • heatIndex - Calculated heat index
Methods:
void setUpdateInterval(uint32_t interval);
void setPins(uint8_t pin);
void reinitializeSensor();
Comprehensive environmental monitoring with temperature, humidity, pressure, altitude, and gas resistance.
#define ENABLE_SENSOR_BME680_V2
#include "Kinematrix.h"

BME680SensV2 bme680;  // I2C by default
// OR
BME680SensV2 bme680(10);  // SPI with CS pin 10

void setup() {
    bme680.setUpdateInterval(5000);
    sensors.addSensor("environment", &bme680);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("environment")) {
        float temp = sensors.getValue<float>("environment", "temperature");
        float humidity = sensors.getValue<float>("environment", "humidity");
        float pressure = sensors.getValue<float>("environment", "pressure");
        float altitude = sensors.getValue<float>("environment", "altitude");
        float gas = sensors.getValue<float>("environment", "gas");
    }
}
Available Values:
  • temperature - Temperature in °C
  • humidity - Relative humidity %
  • pressure - Barometric pressure in hPa
  • altitude - Calculated altitude in meters
  • gas - Gas resistance in Ohms (air quality)
Constructors:
BME680SensV2(TwoWire *theWire = &Wire);  // I2C
BME680SensV2(int8_t cspin, SPIClass *theSPI = &SPI);  // Hardware SPI
BME680SensV2(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin);  // Software SPI
Sharp GP2Y1010AU0F dust/particle sensor for air quality monitoring.
#define ENABLE_SENSOR_GP2YDUST_V2
#include "Kinematrix.h"

GP2YDustSensV2 dust(A0, 7);  // Analog pin, LED pin

void setup() {
    dust.setUpdateInterval(1000);
    sensors.addSensor("airQuality", &dust);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("airQuality")) {
        float density = sensors.getValue<float>("airQuality", "dustDensity");
        int raw = sensors.getValue<int>("airQuality", "raw");
        float voltage = sensors.getValue<float>("airQuality", "voltage");
    }
}
Available Values:
  • dustDensity - Particle density in μg/m³
  • voltage - Sensor voltage output
  • raw - Raw ADC value

Industrial Sensors

Precision current, voltage, and power measurement.
#define ENABLE_SENSOR_INA219_V2
#include "Kinematrix.h"

INA219SensV2 ina219;

void setup() {
    ina219.setUpdateInterval(500);
    sensors.addSensor("power", &ina219);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("power")) {
        float voltage = sensors.getValue<float>("power", "voltage");
        float current = sensors.getValue<float>("power", "current");
        float power = sensors.getValue<float>("power", "power");
        float shuntVoltage = sensors.getValue<float>("power", "shuntVoltage");
    }
}
Available Values:
  • voltage - Bus voltage in V
  • current - Current in mA
  • power - Power in mW
  • shuntVoltage - Shunt voltage in mV
Non-contact infrared temperature sensor.
#define ENABLE_SENSOR_MLX90614_V2
#include "Kinematrix.h"

MLX90614SensV2 mlx;

void setup() {
    mlx.setUpdateInterval(1000);
    sensors.addSensor("irTemp", &mlx);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("irTemp")) {
        float ambient = sensors.getValue<float>("irTemp", "ambient");
        float object = sensors.getValue<float>("irTemp", "object");
    }
}
Available Values:
  • ambient - Ambient temperature in °C
  • object - Object temperature in °C
Comprehensive MQ series gas sensor support with multi-gas detection.
#define ENABLE_SENSOR_MQ_V2
#include "Kinematrix.h"

MQSensV2 mq("ESP32", 3.3, 12, A0, "MQ-135");

void setup() {
    // Configure sensor
    mq.setRL(1.0);        // Load resistance in kOhms
    mq.setR0(9.83);       // Sensor resistance in clean air
    mq.enableMultipleGases(true);
    
    // Add custom gas profiles
    mq.addCustomGas("CO2", 110.47, -2.862, 1, "ppm", 2);
    mq.addCustomGas("NH3", 102.2, -2.473, 1, "ppm", 2);
    
    mq.setUpdateInterval(2000);
    sensors.addSensor("gas", &mq);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("gas")) {
        float ppm = sensors.getValue<float>("gas", "ppm");
        float ratio = sensors.getValue<float>("gas", "ratio");
        float co2 = sensors.getValue<float>("gas", "CO2");
        float nh3 = sensors.getValue<float>("gas", "NH3");
    }
}
Configuration:
void setRL(float RL_kOhms);                    // Load resistance
void setR0(float R0_kOhms);                    // Base resistance
void calibrateInCleanAir(float cleanAirRatio); // Calibration
void enableMultipleGases(bool enable);         // Multi-gas mode
void addCustomGas(const char *name, float a, float b, 
                  uint8_t type, const char *unit, uint8_t precision);

Time & Clock Sensors

Supports multiple RTC modules: DS1307, DS3231, PCF8523, PCF8563.
#define ENABLE_SENSOR_RTC_DS3231_V2
#include "Kinematrix.h"

RTCDS3231SensV2 rtc;

void setup() {
    rtc.setUpdateInterval(1000);
    sensors.addSensor("clock", &rtc);
    sensors.init();
    
    // Set time (year, month, day, hour, minute, second)
    rtc.adjust(DateTime(2024, 1, 1, 12, 0, 0));
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("clock")) {
        int year = sensors.getValue<int>("clock", "year");
        int month = sensors.getValue<int>("clock", "month");
        int day = sensors.getValue<int>("clock", "day");
        int hour = sensors.getValue<int>("clock", "hour");
        int minute = sensors.getValue<int>("clock", "minute");
        int second = sensors.getValue<int>("clock", "second");
        int dayOfWeek = sensors.getValue<int>("clock", "dayOfWeek");
    }
}
Available RTC Classes:
  • RTCDS1307SensV2 - Basic RTC
  • RTCDS3231SensV2 - High-precision temperature-compensated RTC
  • RTCPCF8523SensV2 - Low-power RTC
  • RTCPCF8563SensV2 - Ultra-low-power RTC
Available Values:
  • year, month, day
  • hour, minute, second
  • dayOfWeek (0-6, Sunday=0)
Software-based RTC using millis() with time persistence.
#define ENABLE_SENSOR_MHRTC_V2
#include "Kinematrix.h"

MHRTCSensV2 mhrtc;

void setup() {
    mhrtc.setUpdateInterval(1000);
    mhrtc.setDateTime(2024, 1, 1, 12, 0, 0);  // Initialize time
    sensors.addSensor("time", &mhrtc);
    sensors.init();
}

General Purpose Sensors

General-purpose analog sensor with custom data processing callbacks.
#define ENABLE_SENSOR_ANALOG_V2
#include "Kinematrix.h"

// Basic analog sensor
AnalogSensV2 light(A0, 3.3, 4095);  // Pin, max voltage, ADC resolution

// With custom processing callback
AnalogSensV2 temp(A0, 5.0, 1023, [](BaseSensV2* s, int raw, float volt) {
    // LM35 temperature sensor conversion
    float celsius = (volt - 0.5) * 100.0;
    float fahrenheit = celsius * 9.0/5.0 + 32.0;
    
    s->updateValue("celsius", celsius);
    s->updateValue("fahrenheit", fahrenheit);
});

void setup() {
    // Add custom values for callback-processed data
    temp.addCustomValue("celsius", "Temperature", "°C", 1, true);
    temp.addCustomValue("fahrenheit", "Temperature", "°F", 1, true);
    
    temp.setUpdateInterval(1000);
    sensors.addSensor("temperature", &temp);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("temperature")) {
        // Default values available for all analog sensors
        int raw = sensors.getValue<int>("temperature", "raw");
        float volt = sensors.getValue<float>("temperature", "volt");
        
        // Custom values from callback
        float celsius = sensors.getValue<float>("temperature", "celsius");
        float fahrenheit = sensors.getValue<float>("temperature", "fahrenheit");
    }
}
Default Values:
  • raw - Raw ADC reading (0-1023/4095)
  • volt - Calculated voltage
Methods:
void addCustomValue(const char *key, const char *label, 
                   const char *unit, uint8_t precision, bool calibrable);
void setUpdateInterval(uint32_t interval);
Virtual sensor for testing and development with multiple signal patterns.
#define ENABLE_SENSOR_ABSTRACT_V2
#include "Kinematrix.h"

AbstractSensV2 test(0);  // Mode: 0=random signals

void setup() {
    test.setUpdateInterval(500);
    test.setDummyValues(100.0, 50.0);  // Range parameters
    sensors.addSensor("test", &test);
    sensors.init();
}

void loop() {
    sensors.update();
    
    if (sensors.isUpdated("test")) {
        float value = sensors.getValue<float>("test", "value");
        float random = sensors.getValue<float>("test", "random");
        float sine = sensors.getValue<float>("test", "sine");
        float cosine = sensors.getValue<float>("test", "cosine");
        int square = sensors.getValue<int>("test", "square");
        float triangle = sensors.getValue<float>("test", "triangle");
        int counter = sensors.getValue<int>("test", "counter");
    }
}
Available Test Signals:
  • value - Main test value
  • random - Random values
  • sine - Sine wave pattern
  • cosine - Cosine wave pattern
  • square - Square wave (0/1)
  • triangle - Triangle wave
  • counter - Incrementing counter

Advanced Features

Type-Safe Data Access

V2 provides compile-time type safety:
// Type-safe retrieval
float temp = sensors.getValue<float>("dht", "temperature");
int raw = sensors.getValue<int>("analog", "raw");
String data = sensors.getValue<String>("sensor", "data");

// Helper methods
float value = sensor.getFloatValue("temperature");
int count = sensor.getIntValue("count");
const char* status = sensor.getStringValue("status");

Update Status Tracking

void loop() {
    sensors.update();
    
    // Only process when sensor has new data
    if (sensors.isUpdated("dht")) {
        float temp = sensors.getValue<float>("dht", "temperature");
        processTemperature(temp);
    }
}

Value Metadata

Sensors can provide metadata about their values:
// In sensor initialization
void initCustomValue() {
    addValueInfo("temperature", "Temperature", "°C", 1, true);
    //           key            label         unit  precision  calibrable
    addValueInfo("humidity", "Humidity", "%", 1, true);
}

// Query value information
const SensorValueInfo* info = sensor.getValueInfoByKey("temperature");
Serial.print("Label: "); Serial.println(info->label);
Serial.print("Unit: "); Serial.println(info->unit);
Serial.print("Precision: "); Serial.println(info->precision);

Sensor Proxy Access

// Direct access using proxy
auto temp = sensors["dht"];
float temperature = temp.getValue<float>("temperature");
float humidity = temp.getValue<float>("humidity");

Debugging and Monitoring

Debug Methods

// Debug single sensor value
sensors.debug("dht", "temperature", true);  // Show heap memory

// Debug all sensors
sensors.debugAll(true);

// Horizontal format (compact)
sensors.debugHorizontal();

// Horizontal with timestamp
sensors.debugHorizontalWithTime(1000);

// Pretty formatted output
sensors.debugPretty(1000);  // Update every 1000ms

Example Debug Output

=== Sensor Debug ===
Sensor: dht
  temperature: 23.5 °C
  humidity: 45.2 %
  heatIndex: 22.8 °C
Heap: 245678 bytes

Sensor: bme680
  temperature: 23.8 °C
  humidity: 46.1 %
  pressure: 1013.25 hPa
  altitude: 120.5 m
  gas: 45231 Ohms
Heap: 244890 bytes

Complete Example

#define ENABLE_SENSOR_MODULE_V2
#define ENABLE_SENSOR_DHT_V2
#define ENABLE_SENSOR_BME680_V2
#define ENABLE_SENSOR_ANALOG_V2
#define ENABLE_SENSOR_FILTER_V2
#define ENABLE_SENSOR_ALERT_SYSTEM_V2

#include "Kinematrix.h"

SensorModuleV2 sensors;
DHTSensV2 dht(2, DHT22);
BME680SensV2 bme680;
AnalogSensV2 light(A0, 3.3, 4095);

void alertCallback(AlertInfo info) {
    Serial.print("ALERT: ");
    Serial.print(info.sensorName);
    Serial.print(".");
    Serial.print(info.valueKey);
    Serial.print(" = ");
    Serial.println(info.currentValue);
}

void setup() {
    Serial.begin(115200);
    
    // Configure sensors
    dht.setUpdateInterval(2000);
    bme680.setUpdateInterval(5000);
    light.setUpdateInterval(1000);
    
    // Add sensors
    sensors.addSensor("dht", &dht);
    sensors.addSensor("bme680", &bme680);
    sensors.addSensor("light", &light);
    
    // Initialize
    sensors.init();
    
    // Add filtering
    FilterParams params;
    params.movingAverage.windowSize = 10;
    sensors.attachFilter("dht", "temperature", FILTER_MOVING_AVERAGE, params);
    sensors.attachFilter("light", "volt", FILTER_MEDIAN, params);
    
    // Set alerts
    sensors.setThreshold("dht", "temperature", 18.0, 28.0, ALERT_OUTSIDE);
    sensors.setThreshold("bme680", "pressure", 980.0, 1050.0, ALERT_OUTSIDE);
    sensors.setGlobalAlertCallback(alertCallback);
    
    Serial.println("Sensor system initialized");
}

void loop() {
    sensors.update();
    
    // DHT sensor
    if (sensors.isUpdated("dht")) {
        float temp = sensors.getValue<float>("dht", "temperature");
        float tempFiltered = sensors.getFilteredValue("dht", "temperature");
        float humidity = sensors.getValue<float>("dht", "humidity");
        
        Serial.print("DHT: T=");
        Serial.print(temp);
        Serial.print(" (filtered=");
        Serial.print(tempFiltered);
        Serial.print("), H=");
        Serial.println(humidity);
    }
    
    // BME680 sensor
    if (sensors.isUpdated("bme680")) {
        float temp = sensors.getValue<float>("bme680", "temperature");
        float humidity = sensors.getValue<float>("bme680", "humidity");
        float pressure = sensors.getValue<float>("bme680", "pressure");
        float gas = sensors.getValue<float>("bme680", "gas");
        
        Serial.print("BME680: T=");
        Serial.print(temp);
        Serial.print(" H=");
        Serial.print(humidity);
        Serial.print(" P=");
        Serial.print(pressure);
        Serial.print(" G=");
        Serial.println(gas);
    }
    
    // Light sensor
    if (sensors.isUpdated("light")) {
        float volt = sensors.getValue<float>("light", "volt");
        float voltFiltered = sensors.getFilteredValue("light", "volt");
        
        Serial.print("Light: ");
        Serial.print(volt);
        Serial.print("V (filtered=");
        Serial.print(voltFiltered);
        Serial.println("V)");
    }
    
    delay(100);
}

Best Practices

Use Callbacks: For complex sensor processing, use callbacks instead of modifying sensor classes:
sensors.addSensor("custom", []() -> BaseSensV2* {
    return new AnalogSensV2(A0, 5.0, 1023, customProcessing);
});
Update Intervals: Set appropriate intervals to avoid overwhelming the system:
  • Fast analog: 100-500ms
  • I2C sensors: 1000-2000ms
  • Environmental: 2000-5000ms
Type Safety: Always use the correct type when calling getValue<T>():
float temp = sensors.getValue<float>("dht", "temperature");  // Correct
int temp = sensors.getValue<int>("dht", "temperature");      // Wrong - will truncate

Next Steps

Filtering

Learn about real-time signal filtering

Alerts

Configure threshold-based alerts

Calibration

Interactive sensor calibration

Sensor Module V1

View legacy sensor framework

Build docs developers (and LLMs) love