fs1027_dg_hal/
lib.rs

1//! # fs1027-dg-hal sensor driver
2//!
3//! The crate provides a basic sensor driver based on the I²C interface provided.
4//!
5//! The sensor's sheet can be found [here](https://www.renesas.com/us/en/document/dst/fs1027-dg-datasheet?language=en&r=1488711)
6//!
7//! Other versions of this sensor might work, but are not supported.
8
9#![deny(unsafe_code, warnings)]
10#![no_std]
11
12extern crate embedded_hal as hal;
13use core::marker::PhantomData;
14
15use embedded_hal::blocking::i2c::Read;
16
17///An instance of the driver that does not *own* the I²C bus.
18pub struct Fs1027DgBusless<I2C: Read>{
19    i2c: PhantomData<I2C>,
20    addr: u8,
21    read_buffer: [u8; 5],
22}
23
24///Driver definition that owns the I²C bus. Saver, since it can ensure that the
25/// BUS is always the same.
26pub struct Fs1027Dg<I2C: Read> {
27    i2c: I2C,
28    busless: Fs1027DgBusless<I2C>,
29}
30
31impl<I2C: Read> Fs1027DgBusless<I2C> {
32    ///Creates the driver for the given I²C ports. Assumes that the I²C port is configured as master.
33    ///
34    /// Tries to initialize the driver on the given address, returns an error if this failed.
35    ///
36    /// If you are sure that the driver is at the given address and it still fails, make sure that you
37    /// configured the SDA/SCL connection correctly. The recommend pull-up resistors are between 2.2k Ohm and 10k Ohm. Have a look at the [documentation](https://www.renesas.com/us/en/document/dst/fs1027-dg-datasheet?language=en&r=1488711) for further information.
38    pub fn new(_i2c: &I2C, addr: u8) -> Self {
39        let dev = Fs1027DgBusless {
40            i2c: PhantomData,
41            addr,
42            read_buffer: [0; 5],
43        };
44
45        dev
46    }
47
48    ///Initializes the driver assuming the sensors address is the default one. If this fails, consider searching for the driver. Note that the driver only supports 7bit addresses.
49    ///
50    /// Have a look at [new](Self::new) for further documentation.
51    pub fn new_default(i2c: &I2C) -> Self {
52        Self::new(i2c, 0x50)
53    }
54
55    ///Reads a single 12bit value from the sensor. Returns 0 if the reading failed. Note that the default lowest value is 409 (per documentation).
56    pub fn read(&mut self, i2c: &mut I2C) -> u16 {
57        self.try_read(i2c).unwrap_or(0)
58    }
59
60    ///Tries to read a value, verifies it, and if this succeeds, returns the 12bit value.
61    pub fn try_read(&mut self, i2c: &mut I2C) -> Option<u16> {
62        //Per documentation: read 5 bytes, the first is the checksum, 1..2 is the data
63        // and 3..4 is the generic checksum.
64        //
65        match i2c.read(self.addr, &mut self.read_buffer) {
66            Ok(_) => {}
67            Err(_e) => return None,
68        }
69
70        //Calculate validity
71        let value = u16::from_be_bytes([self.read_buffer[1], self.read_buffer[2]]);
72        let sum = self.read_buffer[1]
73            .wrapping_add(self.read_buffer[2])
74            .wrapping_add(self.read_buffer[3])
75            .wrapping_add(self.read_buffer[4]);
76
77        if self.read_buffer[0].wrapping_add(sum) == 0 {
78            return Some(value);
79        } else {
80            None
81        }
82    }
83
84    ///Reads the current flow rate in liters/min. Returns 0 if reading failed
85    pub fn read_flow_rate(&mut self, i2c: &mut I2C) -> f32 {
86        if let Some(rate) = self.try_read(i2c) {
87            Self::bit_to_flow_rate(rate)
88        } else {
89            0.0
90        }
91    }
92
93    ///Converts the raw bits to a flow rate in liters/min
94    pub fn bit_to_flow_rate(bit: u16) -> f32 {
95        ((bit - 409) as f32 / 33277.0) * 200.0
96    }
97}
98
99
100impl<I2C: Read> Fs1027Dg<I2C>{
101    ///Creates the driver for the given I²C ports. Assumes that the I²C port is configured as master.
102    ///
103    /// Tries to initialize the driver on the given address, returns an error if this failed.
104    ///
105    /// If you are sure that the driver is at the given address and it still fails, make sure that you
106    /// configured the SDA/SCL connection correctly. The recommend pull-up resistors are between 2.2k Ohm and 10k Ohm. Have a look at the [documentation](https://www.renesas.com/us/en/document/dst/fs1027-dg-datasheet?language=en&r=1488711) for further information.
107    pub fn new(i2c: I2C, addr: u8) -> Self {
108        let busless = Fs1027DgBusless::new(&i2c, addr);
109        let dev = Fs1027Dg {
110            i2c,
111            busless
112        };
113
114        dev
115    }
116
117    ///Initializes the driver assuming the sensors address is the default one. If this fails, consider searching for the driver. Note that the driver only supports 7bit addresses.
118    ///
119    /// Have a look at [new](Self::new) for further documentation.
120    pub fn new_default(i2c: I2C) -> Self {
121        Self::new(i2c, 0x50)
122    }
123
124    ///Reads a single 12bit value from the sensor. Returns 0 if the reading failed. Note that the default lowest value is 409 (per documentation).
125    pub fn read(&mut self) -> u16 {
126        self.busless.read(&mut self.i2c)
127    }
128
129    ///Tries to read a value, verifies it, and if this succeeds, returns the 12bit value.
130    pub fn try_read(&mut self) -> Option<u16> {
131        self.busless.try_read(&mut self.i2c)
132    }
133
134    ///Reads the current flow rate in liters/min. Returns 0 if reading failed
135    pub fn read_flow_rate(&mut self) -> f32 {
136        self.busless.read_flow_rate(&mut self.i2c)
137    }
138
139    ///Releases the I²C interface by consuming `self`.
140    pub fn release(self) -> I2C {
141        self.i2c
142    }
143}