extern crate i2cdev; extern crate i2cdev_bmp280; extern crate i2csensors; extern crate si7021; use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError}; use i2cdev_bmp280::*; use i2csensors::{Barometer, Hygrometer, Thermometer}; use si7021::{Si7021, SI7021_I2C_ADDRESS}; use std::env; static BMP280_I2C_ADDRESS: u16 = 0x76; fn main() -> Result<(), LinuxI2CError> { let mut verbose = false; let mut args = env::args().skip(1).peekable(); if let None = args.peek() { eprintln!("Usage: tiny-wetter [-v] "); return Ok(()); } if let Some(arg) = args.peek() { if arg == "-v" { verbose = true; args.next(); } } let i2c_path = args.next().expect("missing i2c device"); let altitude = args.next().expect("missing altitude").parse().expect("invalid altitude"); let weather = read_tiny_wetter(&i2c_path)?; if verbose { println!("temperature (bmp280): {:6.1} °C", weather.temperature_bmp280); println!("temperature (si7021): {:6.1} °C", weather.temperature_si7021); println!("corrected temperature: {:6.1} °C", weather.temperature()); println!("relative humidity: {:6.1} %", weather.relative_humidity); println!("real pressure: {:6.1} hPa", weather.pressure / 100.); println!("pressure at sea level: {:6.1} hPa", weather.sea_level_preassure(altitude) / 100.); } else { println!("{:.1} {:.1} {:.1}", weather.temperature(), weather.relative_humidity, weather.sea_level_preassure(altitude) / 100., ); } Ok(()) } struct TinyWetterReading { temperature_bmp280: f32, temperature_si7021: f32, pressure: f32, relative_humidity: f32, } impl TinyWetterReading { fn temperature(&self) -> f32 { (self.temperature_bmp280 + self.temperature_si7021) / 2. - 1.5 } fn sea_level_preassure(&self, altitude: f32) -> f32 { let coef = 13f32 / 2000.; let divisor = self.temperature() + coef * altitude + 273.15; self.pressure * (1f32 - coef * altitude / divisor).powf(-5.257) } } fn read_tiny_wetter(path: &str) -> Result { let bmp280_settings = BMP280Settings { compensation: BMP280CompensationAlgorithm::Float, t_sb: BMP280Timing::ms4000, iir_filter_coeff: BMP280FilterCoefficient::UltraHigh, osrs_t: BMP280TemperatureOversampling::x16, osrs_p: BMP280PressureOversampling::UltraHighResolution, power_mode: BMP280PowerMode::ForcedMode, }; let i2c_device = LinuxI2CDevice::new(path, BMP280_I2C_ADDRESS)?; let mut bmp280 = BMP280::new(i2c_device, bmp280_settings)?; let i2c_device = LinuxI2CDevice::new(path, SI7021_I2C_ADDRESS)?; let mut si7021 = Si7021::new(i2c_device); Ok(TinyWetterReading { temperature_bmp280: bmp280.temperature_celsius()?, temperature_si7021: si7021.temperature_celsius()?, pressure: bmp280.pressure_kpa()? * 1000., relative_humidity: si7021.relative_humidity()?, }) }