Skip to content

Embedded Rust IIoT environmental monitoring node on STM32F401RE + BME680 sensor. Real-time IAQ calculation from temperature, humidity, pressure & VOC data. Features shared I2C architecture, adaptive gas baseline calibration, SSD1306 display, and power-optimized forced-mode acquisition cycle.

Notifications You must be signed in to change notification settings

mapfumo/bme680-basic

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌡️ BME680 IIoT Environmental Node (NUCLEO-F446RE / Rust)

Nucleo Board, BME680, OLED A bare-metal embedded Rust application for the NUCLEO-F446RE board that implements an Industrial Internet of Things (IIoT) environmental monitoring node. The system integrates a Bosch BME680 multi-sensor with an SSD1306 OLED display over a shared I2C bus to provide real-time environmental data and calculated Indoor Air Quality (IAQ) metrics.

🛠️ Hardware Stack

Component Model/Part Interface Address/Pins
Microcontroller STM32F401RE (NUCLEO-F446RE) - -
Environmental Sensor Bosch BME680 I2C 0x77 (Secondary)
Display SSD1306 128x32 OLED I2C 0x3C
Status LED Built-in LED GPIO PA5
I2C Bus I2C1 SCL/SDA PB8/PB9

BME680 Sensor Capabilities

  • Temperature: -40°C to +85°C (±1°C accuracy)
  • Humidity: 0-100% RH (±3% accuracy)
  • Pressure: 300-1100 hPa (±1 hPa accuracy)
  • Gas Resistance: 0-500 kΩ (Metal Oxide VOC sensor)

📦 Software & Toolchain

Dependencies

stm32f4xx-hal = "0.23.0"      # STM32F4 Hardware Abstraction Layer
bme680 = "0.6"                 # BME680 sensor driver
ssd1306 = "0.8"                # SSD1306 OLED driver
shared-bus = "0.3"             # Shared I2C bus manager
embedded-graphics = "0.8"      # Graphics primitives
heapless = "0.8"               # Stack-allocated data structures
cortex-m-rt = "0.7"            # Cortex-M runtime
libm = "0.2"                   # Math functions for no_std

Development Tools

  • Language: Rust - [1.91.1]
  • Build System: Cargo with embedded targets
  • Target: thumbv7em-none-eabihf
  • Debugger: probe-run / VS Code + Cortex-Debug
  • Flash Tool: cargo-embed / ST-LINK

⚙️ Key IIoT Concepts Implemented

1. Shared Bus Architecture

  • Pattern: shared-bus::BusManagerSimple enables safe concurrent access to I2C1
  • Benefit: Prevents bus conflicts between BME680 and SSD1306 without complex state machines
  • Implementation: Each peripheral acquires the bus using bus.acquire_i2c() for transactions

2. Synchronous Data Acquisition Cycle

Trigger (ForcedMode) → Wait (2s) → Read → Process → Display → Sleep
  • Power Mode: PowerMode::ForcedMode for single-shot measurements
  • Advantage: Minimizes sensor power consumption vs. continuous mode
  • IIoT Relevance: Suitable for battery-powered edge nodes with periodic reporting

3. Indoor Air Quality (IAQ) Calculation

The system implements a custom IAQ algorithm combining:

  • Gas Score (75%): Ratio of baseline gas resistance to current reading
    • High resistance = clean air, low resistance = VOC presence
  • Humidity Score (25%): Deviation from optimal humidity (40% RH)
    • Outside 40% affects perceived air quality and mold risk

IAQ Scale:

  • 0-50: Excellent
  • 51-100: Good
  • 101-150: Fair
  • 151-200: Poor
  • 201-300: Bad
  • 301-500: Worst

4. Adaptive Baseline Calibration

  • Initial Baseline: 2 MΩ (conservative high value)
  • Auto-Calibration: System continuously updates baseline to highest observed resistance
  • Burn-in Period: 48 hours recommended for stable baseline convergence
  • Real-world Behavior: Tracks environmental changes (seasons, ventilation patterns)

📊 Sensor Data Display

The 128x32 OLED displays three lines of real-time metrics, updated every 2 seconds:

Line 1: [Temp]°C | [Hum]% | [IAQ Status]
Line 2: [Pressure]hPa | IAQ: [Score]
Line 3: Gas: [Resistance]kΩ

Display Metrics

Line Metric Unit Range Description
1 Temperature °C -40 to +85 Ambient temperature with ±1°C accuracy
1 Humidity % RH 0-100 Relative humidity with ±3% accuracy
1 IAQ Status Text EXCELLENT to WORST Qualitative air quality assessment
2 Pressure hPa 300-1100 Barometric pressure (altitude compensated)
2 IAQ Score 0-500 0-500 Numerical air quality index
3 Gas Resistance 0-500+ Raw VOC sensor resistance

Status Indicators

  • LED Behavior:
    • Rapid blink (100ms): Initialization error
    • 3 quick blinks: System ready
    • Brief pulse: Measurement in progress

🚀 Building & Flashing

Prerequisites

# Install Rust nightly
rustup toolchain install nightly
rustup default nightly

# Add embedded target
rustup target add thumbv7em-none-eabihf

# Install cargo tools
cargo install probe-run cargo-embed

Build

cargo build --release

Flash & Debug

# Using probe-run
cargo run --release

# Or using cargo-embed
cargo embed --release

🔧 Configuration

Clock Configuration

// System Clock: 84 MHz (max for STM32F401RE)
let rcc_config = Config::default().sysclk(84.MHz());

BME680 Settings

SettingsBuilder::new()
    .with_humidity_oversampling(OversamplingSetting::OS2x)
    .with_pressure_oversampling(OversamplingSetting::OS4x)
    .with_temperature_oversampling(OversamplingSetting::OS2x)
    .with_temperature_filter(IIRFilterSize::Size3)
    .with_gas_measurement(Duration::from_millis(150), 300, 25)
    .with_run_gas(true)

I2C Bus Speed

// 100 kHz for reliable communication with both peripherals
I2c::new(dp.I2C1, (scl, sda), 100.kHz(), &mut rcc)

📈 Performance Characteristics

  • Update Rate: 2 seconds per measurement cycle
  • Power Consumption: ~40mA active (BME680 heater on), ~10mA idle
  • I2C Speed: 100 kHz (standard mode)
  • Flash Usage: ~35 KB
  • RAM Usage: ~8 KB
  • Measurement Accuracy: Sensor-limited (see BME680 datasheet)

🐛 Troubleshooting

Sensor Not Detected

  1. Verify I2C address (use I2C scanner if available)
  2. Check wiring: SCL→PB8, SDA→PB9, VCC→3.3V, GND→GND
  3. Ensure pull-up resistors on I2C lines (often on-board)
  4. Try reducing I2C speed to 50 kHz

Invalid Readings

  1. Humidity at 100%: Wait 48 hours for sensor burn-in
  2. Gas resistance at 0: Heater warming up, wait ~5 minutes
  3. IAQ shows "...Wait": Normal during initial measurements

Compilation Issues

  1. Ensure correct HAL version: stm32f4xx-hal = "=0.23.0" (note the =)
  2. Clear build cache: cargo clean
  3. Update dependencies: cargo update

📚 Further Development

Potential Enhancements

  • UART data logging for long-term trend analysis
  • LoRaWAN integration for remote monitoring
  • Sleep mode implementation for battery operation
  • SD card logging of historical data
  • Web server with ESP8266/ESP32 co-processor
  • MQTT publishing to cloud platforms
  • Altitude compensation for pressure readings
  • CO₂ equivalent calculation from TVOC

Calibration Improvements

  • Store gas baseline in EEPROM/Flash for persistence
  • Implement exponential moving average for noise reduction
  • Add temperature compensation for gas readings
  • Multi-point humidity calibration

📖 References

📄 License

This project is open-source and available under the MIT License.

🤝 Contributing

Contributions are welcome! Please feel free to submit issues or pull requests for:

  • Bug fixes
  • Documentation improvements
  • New features
  • Performance optimizations

About

Embedded Rust IIoT environmental monitoring node on STM32F401RE + BME680 sensor. Real-time IAQ calculation from temperature, humidity, pressure & VOC data. Features shared I2C architecture, adaptive gas baseline calibration, SSD1306 display, and power-optimized forced-mode acquisition cycle.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published