diff --git a/Cargo.toml b/Cargo.toml index d876e20..7502d99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,18 @@ [package] name = "ms5611" version = "1.0.0" -authors = ["Ken Elkabany "] +authors = ["Ken Elkabany ", "Marius Knaust "] license = "MIT" description = "Library for the MS5611 barometric pressure sensor." repository = "https://github.com/braincore/ms5611-rs" -keywords = ["ms5611"] +categories = ["embedded", "no-std", "hardware-support"] +keywords = ["ms5611", "embedded-hal"] +edition = "2018" readme = "README.md" [dependencies] -byteorder = "1.1.0" -i2cdev = "0.3.1" +embedded-hal = "0.2.2" +byteorder = { version = "1.1.0", default-features = false } + +[dev-dependencies] +linux-embedded-hal = "0.2.2" diff --git a/README.md b/README.md index 3d041e6..d734162 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# MS5611 Library for Rust [![Latest Version]][crates.io] [![Documentation]][docs.rs] +# MS5611 Library for Rust [![Latest Version]][crates.io] [![Documentation]][docs.rs] [Latest Version]: https://img.shields.io/crates/v/ms5611.svg [crates.io]: https://crates.io/crates/ms5611 @@ -15,7 +15,7 @@ interface (no SPI). ## Usage -See basic test in `lib.rs`. +See basic test in `tests/basic.rs`. ## Testing diff --git a/src/lib.rs b/src/lib.rs index 7a2d7a3..109524b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,16 +1,11 @@ //! A library for the MS5611 barometric pressure sensor. -extern crate byteorder; +#![no_std] + use byteorder::{ByteOrder, BigEndian}; -extern crate i2cdev; -use i2cdev::core::*; -use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError}; -use std::time; -use std::thread; - -fn get_i2c_bus_path(i2c_bus: i32) -> String { - format!("/dev/i2c-{}", i2c_bus) -} + +use embedded_hal::blocking::delay::DelayMs; +use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; /// Oversampling ratio /// See datasheet for more information. @@ -23,7 +18,7 @@ pub enum Osr { } impl Osr { - fn get_delay(&self) -> u64 { + fn get_delay(&self) -> u8 { match *self { Osr::Opt256 => 1, Osr::Opt512 => 2, @@ -45,9 +40,10 @@ impl Osr { } /// Pressure sensor -pub struct Ms5611 { - i2c_dev: LinuxI2CDevice, - prom: Prom, +pub struct Ms5611 { + i2c: I, + address : u8, + prom: Prom } enum Ms5611Reg { @@ -101,35 +97,40 @@ struct Prom { pub temp_coef_temp: u16, } -impl Ms5611 { +impl Ms5611 +where + I: Read + Write + WriteRead, +{ /// If i2c_addr is unspecified, 0x77 is used. /// The addr of the device is 0x77 if CSB is low / 0x76 if CSB is high. - pub fn new(i2c_bus: i32, i2c_addr: Option) - -> Result { - let mut i2c_dev = LinuxI2CDevice::new( - get_i2c_bus_path(i2c_bus), i2c_addr.unwrap_or(0x77))?; + pub fn new(mut i2c: I, i2c_addr: Option) + -> Result { + let address = i2c_addr.unwrap_or(0x77); - let prom = Self::read_prom(&mut i2c_dev)?; + let prom = Self::read_prom(&mut i2c, address)?; let ms = Ms5611 { - i2c_dev, - prom, + i2c, + address: address, + prom }; Ok(ms) } /// Triggers a hardware reset of the device. - pub fn reset(&mut self) -> Result<(), LinuxI2CError> { - self.i2c_dev.write(&[Ms5611Reg::Reset.addr()])?; + pub fn reset(&mut self, delay: &mut D) -> Result<(), E> + where D: DelayMs + { + self.i2c.write(self.address, &[Ms5611Reg::Reset.addr()])?; // Haven't tested for the lower time bound necessary for the chip to // start functioning again. But, it does require some amount of sleep. - thread::sleep(time::Duration::from_millis(50)); + delay.delay_ms(50); Ok(()) } - fn read_prom(i2c_dev: &mut LinuxI2CDevice) -> Result { + fn read_prom(i2c: &mut I, address : u8) -> Result { let mut crc_check = 0u16; // This is the CRC scheme in the MS5611 AN520 (Application Note) @@ -151,42 +152,34 @@ impl Ms5611 { let mut buf: [u8; 2] = [0u8; 2]; // Address reserved for manufacturer. We need it for the CRC. - i2c_dev.write(&[Ms5611Reg::Prom.addr()])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr()], &mut buf)?; crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 2])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 2], &mut buf)?; let pressure_sensitivity = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 4])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 4], &mut buf)?; let pressure_offset = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 6])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 6], &mut buf)?; let temp_coef_pressure_sensitivity = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 8])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 8], &mut buf)?; let temp_coef_pressure_offset = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 10])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 10], &mut buf)?; let temp_ref = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 12])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 12], &mut buf)?; let temp_coef_temp = BigEndian::read_u16(&mut buf); crc_accumulate_buf2(&mut crc_check, &buf); - i2c_dev.write(&[Ms5611Reg::Prom.addr() + 14])?; - i2c_dev.read(&mut buf)?; + i2c.write_read(address, &[Ms5611Reg::Prom.addr() + 14], &mut buf)?; // CRC is only last 4 bits let crc = BigEndian::read_u16(&mut buf) & 0x000f; crc_accumulate_byte(&mut crc_check, buf[0]); @@ -211,24 +204,24 @@ impl Ms5611 { /// Based on oversampling ratio, function may block between 1ms (OSR=256) /// to 18ms (OSR=4096). To avoid blocking, consider invoking this function /// in a separate thread. - pub fn read_sample(&mut self, osr: Osr) -> Result { + pub fn read_sample(&mut self, osr: Osr, delay: &mut D) -> Result + where D: DelayMs + { // Note: Variable names aren't pretty, but they're consistent with the // MS5611 datasheet. let mut buf = [0u8; 4]; - self.i2c_dev.write(&[Ms5611Reg::D1.addr() + osr.addr_modifier()])?; + self.i2c.write(self.address, &[Ms5611Reg::D1.addr() + osr.addr_modifier()])?; // If we don't delay, the read is all 0s. - thread::sleep(time::Duration::from_millis(osr.get_delay())); - self.i2c_dev.write(&[Ms5611Reg::AdcRead.addr()])?; - self.i2c_dev.read(&mut buf[1 .. 4])?; + delay.delay_ms(osr.get_delay()); + self.i2c.write_read(self.address, &[Ms5611Reg::AdcRead.addr()], &mut buf[1 .. 4])?; // Raw digital pressure let d1 = BigEndian::read_i32(&mut buf); - self.i2c_dev.write(&[Ms5611Reg::D2.addr() + osr.addr_modifier()])?; - thread::sleep(time::Duration::from_millis(osr.get_delay())); - self.i2c_dev.write(&[Ms5611Reg::AdcRead.addr()])?; - self.i2c_dev.read(&mut buf[1 .. 4])?; + self.i2c.write(self.address, &[Ms5611Reg::D2.addr() + osr.addr_modifier()])?; + delay.delay_ms(osr.get_delay()); + self.i2c.write_read(self.address, &[Ms5611Reg::AdcRead.addr()], &mut buf[1 .. 4])?; // Raw digital temperature let d2 = BigEndian::read_i32(&mut buf) as i64; @@ -279,37 +272,3 @@ impl Ms5611 { }) } } - -#[cfg(test)] -mod tests { - use super::{Ms5611, Osr}; - use std::env; - - fn get_i2c_bus() -> i32 { - match env::var("MS5611_I2C_BUS") { - Ok(bus_string) => { - bus_string.parse().expect( - "Could not convert MS5611_I2C_BUS env var to i32.") - }, - Err(_) => 1, - } - } - - fn get_i2c_addr() -> Option { - match env::var("MS5611_I2C_ADDR") { - Ok(addr_string) => { - Some(addr_string.parse().expect( - "Could not convert MS5611_I2C_ADDR env var to u16.")) - }, - Err(_) => None, - } - } - - #[test] - fn basic() { - let mut ms5611 = Ms5611::new( - get_i2c_bus(), get_i2c_addr()).unwrap(); - ms5611.read_sample(Osr::Opt256).unwrap(); - ms5611.reset().unwrap(); - } -} diff --git a/tests/basic.rs b/tests/basic.rs new file mode 100644 index 0000000..e56b60c --- /dev/null +++ b/tests/basic.rs @@ -0,0 +1,41 @@ +use linux_embedded_hal::{Delay, I2cdev}; +use ms5611::{Ms5611, Osr}; +use std::env; + +fn get_i2c_bus() -> i32 { + match env::var("MS5611_I2C_BUS") { + Ok(bus_string) => { + bus_string.parse().expect( + "Could not convert MS5611_I2C_BUS env var to i32.") + }, + Err(_) => 1, + } +} + +fn get_i2c_addr() -> Option { + match env::var("MS5611_I2C_ADDR") { + Ok(addr_string) => { + Some(addr_string.parse().expect( + "Could not convert MS5611_I2C_ADDR env var to u16.")) + }, + Err(_) => None, + } +} + + +fn get_i2c_bus_path(i2c_bus: i32) -> String { + format!("/dev/i2c-{}", i2c_bus) +} + + +#[test] +fn basic() { + let dev = I2cdev::new(get_i2c_bus_path(get_i2c_bus())).unwrap(); + + let mut ms5611 = Ms5611::new(dev, get_i2c_addr()).unwrap(); + + let mut delay = Delay; + + ms5611.read_sample(Osr::Opt256, &mut delay).unwrap(); + ms5611.reset(&mut delay).unwrap(); +}