diff --git a/Cargo.toml b/Cargo.toml index 89f4a11..1f58d57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ name = "rust-sensor" version = "0.1.0" authors = ["Klemens Schölhorn "] +edition = "2018" [dependencies] i2csensors = "0.1" diff --git a/src/main.rs b/src/main.rs index 84f5486..ee13265 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,38 +3,94 @@ extern crate i2cdev_bmp280; extern crate i2csensors; extern crate si7021; -use i2cdev::linux::LinuxI2CDevice; +use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError}; use i2cdev_bmp280::*; -use si7021::*; use i2csensors::{Barometer, Hygrometer, Thermometer}; - +use si7021::{Si7021, SI7021_I2C_ADDRESS}; use std::env; -fn main() { - let i2c_path = env::args().skip(1).next().expect("i2c bus path (eg. /dev/i2c-1)"); +static BMP280_I2C_ADDRESS: u16 = 0x76; - i2c_sensors(&i2c_path); +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(()) } -fn i2c_sensors(path: &str) { - let i2c_device = LinuxI2CDevice::new(path, 0b1110110).unwrap(); +struct TinyWetterReading { + temperature_bmp280: f32, + temperature_si7021: f32, + pressure: f32, + relative_humidity: f32, +} - let settings = BMP280Settings { +impl TinyWetterReading { + fn temperature(&self) -> f32 { + (self.temperature_bmp280 + self.temperature_si7021) / 2. - 1. + } + + 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::x2, + osrs_t: BMP280TemperatureOversampling::x16, osrs_p: BMP280PressureOversampling::UltraHighResolution, - power_mode: BMP280PowerMode::NormalMode, + power_mode: BMP280PowerMode::ForcedMode, }; - let mut bmp280 = BMP280::new(i2c_device, settings).unwrap(); + let i2c_device = LinuxI2CDevice::new(path, BMP280_I2C_ADDRESS)?; + let mut bmp280 = BMP280::new(i2c_device, bmp280_settings)?; - println!("pressure: {:6.2} kPa", bmp280.pressure_kpa().unwrap()); - println!("temp1: {:6.2} °C", bmp280.temperature_celsius().unwrap()); + let i2c_device = LinuxI2CDevice::new(path, SI7021_I2C_ADDRESS)?; + let mut si7021 = Si7021::new(i2c_device); - let device = LinuxI2CDevice::new(path, SI7021_I2C_ADDRESS).unwrap(); - let mut si7021 = Si7021::new(device); - println!("humidity: {:6.2} %", si7021.relative_humidity().unwrap()); - println!("temp2: {:6.2} °C", si7021.temperature_celsius().unwrap()); + + Ok(TinyWetterReading { + temperature_bmp280: bmp280.temperature_celsius()?, + temperature_si7021: si7021.temperature_celsius()?, + pressure: bmp280.pressure_kpa()? * 1000., + relative_humidity: si7021.relative_humidity()?, + }) }