Sensor Interfaces
Overview
The CICERONE AirLink device integrates three primary sensors for comprehensive air quality monitoring. All sensors communicate via I2C protocol, sharing the same bus with different addresses.
I2C Bus Configuration
Bus: Wire (Arduino standard I2C library)
Speed: 100 kHz (standard mode)
Pull-ups: External 4.7kΩ resistors on PCB
Voltage: 5V logic level (with level shifters if needed)
I2C Address Map
| Device | Address | Conflict Resolution |
|---|---|---|
| SEN54 | 0x69 | Fixed by manufacturer |
| T6793 | 0x15 | Configurable (factory default) |
| DS3231M | 0x68 | Fixed by manufacturer |
No Address Conflicts
All I2C devices use different addresses, avoiding conflicts on the shared bus.
SEN54 Particulate Matter & VOC Sensor
Specifications
Manufacturer: Sensirion
Model: SEN54
Communication: I2C (address 0x69)
Supply Voltage: 4.5-5.5V
Power Consumption: ~60 mA typical
Warm-up Time: ~30 seconds for VOC accuracy
Measured Parameters
| Parameter | Range | Accuracy | Units |
|---|---|---|---|
| PM1.0 | 0-1000 | ±10 µg/m³ | µg/m³ |
| PM2.5 | 0-1000 | ±10 µg/m³ | µg/m³ |
| PM4.0 | 0-1000 | ±25 µg/m³ | µg/m³ |
| PM10 | 0-1000 | ±25 µg/m³ | µg/m³ |
| VOC Index | 1-500 | - | Index |
| Temperature | -10 to 50 | ±0.5°C | °C |
| Humidity | 0-100 | ±4.5% RH | % |
Library
Name: Sensirion I2C SEN5X
Version: 0.3.0 (official from Sensirion)
Installation:
Initialization Sequence
bool sen5x_inicializar() {
Wire.begin();
sen5x.begin(Wire);
// Soft reset
error = sen5x.deviceReset();
if (error) {
DEBUG_ERROR("SEN5X reset failed");
return false;
}
delay(100); // Wait for reset
// Start measurement
error = sen5x.startMeasurement();
if (error) {
DEBUG_ERROR("Failed to start measurement");
return false;
}
DEBUG_INFO("SEN5X initialized successfully");
return true;
}
Reading Data
bool sen5x_leer() {
uint16_t error;
error = sen5x.readMeasuredValues(
sen5x_mc_1p0,
sen5x_mc_2p5,
sen5x_mc_4p0,
sen5x_mc_10p0,
sen5x_hum,
sen5x_temp,
sen5x_voc_index,
sen5x_nox_index
);
if (error) {
DEBUG_WARN("SEN5X read error: %d", error);
return false;
}
DEBUG_VERBOSE("PM2.5: %.2f, VOC: %d, Temp: %.1f°C",
sen5x_mc_2p5, sen5x_voc_index, sen5x_temp);
return true;
}
VOC Index Explained
Scale: 1-500 (100 = neutral)
Interpretation:
- 1-100: Clean air
- 100-200: Moderate VOC levels
- 200-300: Elevated VOC levels
- 300-500: High VOC levels
Algorithm: Sensirion's proprietary VOC algorithm adapts to environment over 12-24 hours
Initial Values: May be unreliable for first ~30 seconds after power-on
Troubleshooting
Sensor Not Responding:
- Check I2C connections (SDA, SCL, GND, VCC)
- Verify 5V power supply
- Check I2C address with scanner
- Ensure sensor is properly seated
Incorrect Readings:
- Allow 30-second warm-up for VOC
- Check for physical obstructions blocking air inlet
- Verify sensor is not exposed to extreme temperatures
Communication Errors:
Common Error Codes:
1: I2C communication timeout2: Checksum error (data corruption)4: Sensor not ready (still warming up)
T6793-5K CO₂ Sensor
Specifications
Manufacturer: Amphenol Advanced Sensors (Telaire)
Model: T6793-5K
Communication: I2C (address 0x15)
Supply Voltage: 4.5-5.5V
Power Consumption: ~35 mA typical
Warm-up Time: <60 seconds
Measurement Range: 0-5000 ppm CO₂
Accuracy: ±(50 ppm + 5% of reading)
Technology
Method: Non-Dispersive Infrared (NDIR)
Calibration: ABC (Automatic Baseline Correction)
Expected Lifetime: >15 years
Custom Driver
Since there's no official Arduino library, we implement a custom driver:
Files: T67XX.h / T67XX.cpp and T6793_API.h / T6793_API.cpp
Features:
- Low-level I2C communication
- Command/response protocol
- Error detection
Initialization Sequence
bool t6793_inicializar() {
// Initialize sensor object
airSensor.begin(Wire);
// Verify communication
if (!airSensor.isConnected()) {
DEBUG_ERROR("T6793 not detected");
return false;
}
// Enable ABC algorithm
airSensor.setABC(true);
DEBUG_INFO("T6793 initialized successfully");
return true;
}
Reading Data
bool t6793_leer() {
t6793_co2 = airSensor.getCO2();
if (t6793_co2 < 0) {
DEBUG_WARN("T6793 read error");
return false;
}
DEBUG_VERBOSE("CO2: %.0f ppm", t6793_co2);
return true;
}
ABC Algorithm
Purpose: Automatic calibration to 400 ppm (outdoor CO₂ level)
Operation:
- Monitors minimum CO₂ values over 24-hour periods
- Assumes sensor is periodically exposed to fresh air
- Gradually adjusts baseline to account for sensor drift
Requirements:
- Device should see fresh air at least once per day
- Not suitable for continuously sealed environments
- Can be disabled if manual calibration preferred
Configuration:
airSensor.setABC(true); // Enable ABC (recommended)
airSensor.setABC(false); // Disable ABC (manual calibration)
Typical CO₂ Levels
| Environment | CO₂ Level | Air Quality |
|---|---|---|
| Outdoor | 400 ppm | Baseline |
| Well-ventilated room | 400-600 ppm | Excellent |
| Occupied room | 600-1000 ppm | Good |
| Poorly ventilated | 1000-2000 ppm | Poor |
| Very poor ventilation | >2000 ppm | Unhealthy |
Troubleshooting
Sensor Not Detected:
- Verify I2C address (0x15)
- Check power supply (5V)
- Ensure proper I2C connections
Unrealistic Readings:
- Allow 60-second warm-up after power-on
- Verify sensor is not in sealed enclosure
- Check for calibration issues
Calibration Issues:
If ABC is enabled but readings seem incorrect:
DS3231M Real-Time Clock
Specifications
Manufacturer: Maxim Integrated (Analog Devices)
Model: DS3231M
Communication: I2C (address 0x68)
Supply Voltage: 2.3-5.5V
Battery Backup: CR2032 coin cell
Accuracy: ±5ppm (±2 minutes per year)
Temperature Range: -40 to +85°C
Features
TCXO: Temperature-compensated crystal oscillator
Alarm Functions: Two programmable alarms
32kHz Output: Optional square wave output
Aging Offset: Software-adjustable for long-term accuracy
Library
Name: Custom implementation (DS3231M.h/cpp)
Based on: Maxim DS3231 datasheet
Initialization
bool rtc_inicializar() {
if (!rtc.begin()) {
DEBUG_ERROR("RTC not found");
while (1); // Halt (RTC is critical)
}
if (rtc.lostPower()) {
DEBUG_WARN("RTC lost power, setting time");
// Set time from compile time or user input
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
DEBUG_INFO("RTC initialized");
return true;
}
Setting Time
From Compile Time (during upload):
Manual (specific date/time):
Reading Time
DateTime now = rtc.getRTCTime();
Serial.print(now.year());
Serial.print("/");
Serial.print(now.month());
Serial.print("/");
Serial.print(now.day());
Serial.print(" ");
Serial.print(now.hour());
Serial.print(":");
Serial.print(now.minute());
Serial.print(":");
Serial.println(now.second());
Alarm Configuration
void rtc_alarma_inicializar() {
// Set alarm to trigger every 10 minutes
// (triggered when minute == 0, 10, 20, 30, 40, 50)
rtc.disableAlarm(1);
rtc.disableAlarm(2);
rtc.clearAlarm(1);
rtc.clearAlarm(2);
// Configure alarm 1 to match minutes
rtc.setAlarm(ALM1_MATCH_MINUTES, 0, 0, 0, 1);
DEBUG_INFO("RTC alarms configured");
}
Battery Backup
Purpose: Maintains time during power loss
Battery: CR2032 (3V, ~200mAh)
Expected Lifetime: 5-10 years (depending on temperature)
Replacement: When time is lost after power cycles
Temperature Reading
The DS3231M includes a temperature sensor for crystal compensation:
float rtc_temp = rtc.getTemperature();
Serial.print("RTC Temperature: ");
Serial.print(rtc_temp);
Serial.println("°C");
Accuracy: ±3°C (not calibrated for ambient measurement)
Update Rate: Every 64 seconds
Use Case: Monitoring RTC temperature, not air temperature
Troubleshooting
RTC Not Detected:
- Check I2C connections
- Verify power supply
- Ensure address is 0x68
Time Lost After Power Cycle:
- Replace CR2032 backup battery
- Check battery holder connections
- Re-set time after battery replacement
Incorrect Time:
- Verify timezone configuration in
Datetime_helper.h - Check if daylight saving time adjustment is needed
- Manually set time if necessary
I2C Bus Troubleshooting
I2C Scanner
Use this sketch to detect all I2C devices:
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin();
Serial.println("I2C Scanner");
Serial.println("Scanning...");
byte count = 0;
for (byte i = 1; i < 127; i++) {
Wire.beginTransmission(i);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("Device found at 0x");
if (i < 16) Serial.print("0");
Serial.println(i, HEX);
count++;
}
}
Serial.print("Found ");
Serial.print(count);
Serial.println(" device(s)");
}
void loop() {}
Expected Output:
Device found at 0x15 (T6793)
Device found at 0x68 (DS3231M)
Device found at 0x69 (SEN54)
Found 3 device(s)
Common I2C Issues
No Devices Found:
- Check SDA/SCL connections
- Verify pull-up resistors (4.7kΩ)
- Ensure 5V power to sensors
Communication Errors:
- Reduce I2C bus speed
- Shorten wire lengths
- Check for electromagnetic interference
Intermittent Failures:
- Verify power supply stability
- Check for loose connections
- Monitor for voltage drops during transmission
Related Documentation
- Program Flow - How sensors are read in main loop
- Architecture - System architecture overview
- Data Transmission - How sensor data is transmitted
- Firmware Configuration - Device configuration