tinywetter/driver/src/main.rs

97 lines
3.1 KiB
Rust

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] <i2c device> <altitude>");
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<TinyWetterReading, LinuxI2CError> {
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()?,
})
}