1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
//! This is a platform agnostic Rust driver for the VEML6040 RGBW color light //! sensor, based on the [`embedded-hal`] traits. //! //! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal //! //! This driver allows you to: //! - Enable/disable the sensor. //! - Set the integration time. //! - Set the measurement mode. //! - Trigger a measurement when on manual mode. //! - Read the red channel measurement. //! - Read the green channel measurement. //! - Read the blue channel measurement. //! - Read the white channel measurement. //! - Read measurement of all channels at once. //! //! ## The device //! //! VEML6040 color sensor senses red, green, blue, and white light and //! incorporates photodiodes, amplifiers, and analog / digital circuits into a //! single chip using CMOS process. With the color sensor applied, the //! brightness, and color temperature of backlight can be adjusted base on //! ambient light source that makes panel looks more comfortable for end //! user's eyes. VEML6040's adoption of Filtron TM technology achieves the //! closest ambient light spectral sensitivity to real human eye responses. //! VEML6040 provides excellent temperature compensation capability for keeping //! the output stable under changing temperature. VEML6040's function are //! easily operated via the simple command format of I2C (SMBus compatible) //! interface protocol. VEML6040's operating voltage ranges from 2.5 V to 3.6 V. //! //! Datasheet: [VEML6040](https://www.vishay.com/docs/84276/veml6040.pdf) //! //! Application note: [VEML6040 AN](https://www.vishay.com/docs/84331/designingveml6040.pdf) //! //! ## Usage examples (see also examples folder) //! //! To use this driver, import this crate and an `embedded_hal` implementation, //! then instantiate the device. //! //! Please find additional examples using hardware in this repository: [driver-examples] //! //! [driver-examples]: https://github.com/eldruin/driver-examples //! //! ### Enable and read the color measurement //! //! ```no_run //! use linux_embedded_hal::I2cdev; //! use veml6040::Veml6040; //! //! let dev = I2cdev::new("/dev/i2c-1").unwrap(); //! let mut sensor = Veml6040::new(dev); //! sensor.enable().unwrap(); //! //! let red = sensor.read_red_channel().unwrap(); //! let green = sensor.read_green_channel().unwrap(); //! let blue = sensor.read_blue_channel().unwrap(); //! let white = sensor.read_white_channel().unwrap(); //! //! println!("Measurements: red = {}, green = {}, blue = {}, white = {}", //! red, green, blue, white); //! ``` //! //! ### Read all the channels at once //! //! ```no_run //! use linux_embedded_hal::I2cdev; //! use veml6040::Veml6040; //! //! let dev = I2cdev::new("/dev/i2c-1").unwrap(); //! let mut sensor = Veml6040::new(dev); //! sensor.enable().unwrap(); //! //! let measurement = sensor.read_all_channels().unwrap(); //! //! println!("Measurements: red = {}, green = {}, blue = {}, white = {}", //! measurement.red, measurement.green, measurement.blue, //! measurement.white); //! ``` //! //! ### Set the integration time to 320ms //! //! ```no_run //! use linux_embedded_hal::I2cdev; //! use veml6040::{ Veml6040, IntegrationTime }; //! //! let dev = I2cdev::new("/dev/i2c-1").unwrap(); //! let mut sensor = Veml6040::new(dev); //! sensor.enable().unwrap(); //! sensor.set_integration_time(IntegrationTime::_320ms).unwrap(); //! ``` //! //! ### Set the measurement mode to manual and trigger a measurement //! //! ```no_run //! use linux_embedded_hal::I2cdev; //! use veml6040::{ Veml6040, MeasurementMode }; //! //! let dev = I2cdev::new("/dev/i2c-1").unwrap(); //! let mut sensor = Veml6040::new(dev); //! sensor.enable().unwrap(); //! sensor.set_measurement_mode(MeasurementMode::Manual).unwrap(); //! sensor.trigger_measurement().unwrap(); //! ``` #![deny(unsafe_code)] #![deny(missing_docs)] #![doc(html_root_url = "https://docs.rs/veml6040/0.1.1")] #![no_std] use embedded_hal::blocking::i2c; /// All possible errors in this crate #[derive(Debug)] pub enum Error<E> { /// I²C bus error I2C(E), } /// Possible measurement modes #[derive(Debug, Clone, Copy, PartialEq)] pub enum MeasurementMode { /// Automatic mode. /// /// Measurements are made continuously. The actual cadence depends on /// the integration time. Auto, /// Manual mode. /// /// Measurements are only triggered manually. See `trigger_measurement()`. /// This is also called "force mode" or "ActiveForce" mode. Manual, } /// Integration time #[derive(Debug, Clone, Copy, PartialEq)] pub enum IntegrationTime { /// 40 ms _40ms, /// 80 ms _80ms, /// 160 ms _160ms, /// 320 ms _320ms, /// 640 ms _640ms, /// 1280 ms _1280ms, } /// Result of measurement of all channels #[derive(Debug, Clone, Copy, PartialEq)] pub struct AllChannelMeasurement { /// Red channel measurement. pub red: u16, /// Green channel measurement. pub green: u16, /// Blue channel measurement. pub blue: u16, /// White channel measurement. pub white: u16, } const DEVICE_ADDRESS: u8 = 0x10; struct Register; impl Register { const CONFIG: u8 = 0x00; const R_DATA: u8 = 0x08; const G_DATA: u8 = 0x09; const B_DATA: u8 = 0x0A; const W_DATA: u8 = 0x0B; } struct BitFlags; impl BitFlags { const SHUTDOWN: u8 = 0b0000_0001; const AF: u8 = 0b0000_0010; const TRIG: u8 = 0b0000_0100; } /// VEML6040 device driver. #[derive(Debug, Default)] pub struct Veml6040<I2C> { /// The concrete I²C device implementation. i2c: I2C, /// Configuration register status. config: u8, } impl<I2C, E> Veml6040<I2C> where I2C: i2c::Write<Error = E>, { /// Create new instance of the VEML6040 device. pub fn new(i2c: I2C) -> Self { Veml6040 { i2c, config: 0 } } /// Destroy driver instance, return I²C bus instance. pub fn destroy(self) -> I2C { self.i2c } } mod configuration; mod reading;