mprls 0.1.0

Rust driver for Honeywell MPR pressure sensor
Documentation
// ------------------------------------------------------------------------------
// Copyright 2021 Uwe Arzt, mail@uwe-arzt.de
// SPDX-License-Identifier: Apache-2.0
// ------------------------------------------------------------------------------

//! Driver for Honeywell MPR pressure sensor

#![no_std]

use embedded_hal as hal;

use crate::hal::blocking::delay::DelayMs;
use crate::hal::blocking::i2c::{Read, Write, WriteRead};

/// Errors
#[derive(Debug)]
pub enum Error<E> {
    /// I2C bus error
    I2c(E),
}

/// I²C address
#[derive(Copy, Clone)]
pub enum Address {
    Standard = 0x18,
    Alt1 = 0x08,
    Alt2 = 0x28,
    Alt3 = 0x38,
    Alt4 = 0x48,
    Alt5 = 0x58,
    Alt6 = 0x68,
    Alt7 = 0x78,
}

/// Pressure Units
pub enum PressureUnit {
    // PSI
    PSI,
    // Pa (Pascal)
    PA,
    // kPa (kilopascal)
    KPA,
    // torr (mmHg)
    TORR,
    // inHg (inch of mercury)
    INHG,
    // atm (atmosphere)
    ATM,
    // bar
    BAR,
}

const MAXIMUM_PSI: f32 = 25.0;
const MINIMUM_PSI: f32 = 0.0;

const OUTPUT_MAX: f32 = 0xE66666 as f32;
const OUTPUT_MIN: f32 = 0x19999A as f32;

// const BUSY_FLAG: u8 = 0x20;
// const INTEGRITY_FLAG: u8 = 0x04;
// const MATH_SAT_FLAG: u8 = 0x01;

#[allow(dead_code)]
pub struct MPR<I2C, D> {
    i2c: I2C,
    delay: D,
    address: Address,
}

impl<I2C, D, E> MPR<I2C, D>
where
    I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
    D: DelayMs<u8>,
{
    /// Creates a new driver
    pub fn new(i2c: I2C, delay: D, address: Address) -> Self {
        MPR {
            i2c,
            delay,
            address,
        }
    }

    /// Get raw pressure from sensor, polling until
    /// result is available.
    // pub fn get_pressure_poll(&mut self) -> Result<f32, Error<E>> {
    // }

    /// Get raw pressure from sensor, waitung 50 mS before
    /// reading the result.
    pub fn get_pressure_wait(&mut self, pu: PressureUnit) -> Result<f32, Error<E>> {
        self.start_measurement();
        self.delay.delay_ms(50);
        self.read_pressure(pu)
    }

    fn start_measurement(&mut self) -> Result<(), Error<E>> {
        let cmd = [0xaa, 0x00, 0x00];
        self.i2c
            .write(self.address as u8, &cmd)
            .map_err(Error::I2c)?;
        Ok(())
    }

    fn read_pressure(&mut self, pu: PressureUnit) -> Result<f32, Error<E>> {
        let mut buffer = [0, 0, 0, 0];
        self.i2c
            .read(self.address as u8, &mut buffer)
            .map_err(Error::I2c)?;
        let reading = ((buffer[1] as u32) << 16) + ((buffer[2] as u32) << 8) + buffer[3] as u32;

        let mut pressure = (reading as f32 - OUTPUT_MIN) * (MAXIMUM_PSI - MINIMUM_PSI);
        pressure = (pressure / (OUTPUT_MAX - OUTPUT_MIN)) + MINIMUM_PSI;

        match pu {
            PressureUnit::PSI => Ok(pressure),
            PressureUnit::PA => Ok(pressure * 6894.7573),
            PressureUnit::KPA => Ok(pressure * 6.89476),
            PressureUnit::TORR => Ok(pressure * 51.7149),
            PressureUnit::INHG => Ok(pressure * 2.03602),
            PressureUnit::ATM => Ok(pressure * 0.06805),
            PressureUnit::BAR => Ok(pressure * 0.06895),
        }
    }
}