VEML6030/VEML7700 Ambient Light Sensor Driver in Rust

VEML6030 in a PCB of a product by SDCSystems

Detail of the VEML6030 in a PCB of a product by SDCSystems
Vishay's VEML6030 reference hardware module
3D model of PCB of a product by SDCSystems


SDC Systems contacted me about their need for a Rust driver for Vishay’s VEML6030 ambient light sensor as they had seen that I have written drivers for the VEML6075, VEML6070 and VEML6040 devices.

Happy to see Rust being used commercially in an embedded application, I accepted the offer and here is the result.

The devices

Vishay’s VEML6030 and VEML7700 are high accuracy ambient light digital 16-bit resolution sensors in a miniature transparent package. They include a high sensitive photodiode, a low noise amplifier, a 16-bit A/D converter and support an easy to use I2C bus communication interface and additional interrupt feature.
The ambient light result is as digital value available.

Datasheets: VEML6030 - VEML7700
Application Notes:

Using the driver

To use the device from Rust, you have to add the veml6030 crate to your project as well as a concrete implementation of the embedded-hal traits. For example if you are using the Raspberry Pi running Linux:

# Cargo.toml
veml6030 = "0.1"
linux-embedded-hal = "0.3"

Be sure to use version 0.3 or newer of linux-embedded-hal. During development we discovered an issue with the I2C WriteRead implementation there for which I then contributed a solution.

Here is an example program which will measure the ambient light in lux (source):

extern crate linux_embedded_hal as hal;
extern crate veml6030;
use veml6030::{SlaveAddr, Veml6030};

fn main() {
let dev = hal::I2cdev::new("/dev/i2c-1").unwrap();
let address = SlaveAddr::default();
let mut sensor = Veml6030::new(dev, address);
loop {
let lux = sensor.read_lux().unwrap();
println!("lux: {:2}", lux);

I also created a bare-metal example program that runs on the STM32F3Discovery board which continuously reads the measurement and prints it on an OLED display. You can find the source code of that program here.

In the driver-examples repository you can find further bare-metal examples which you can adapt to do other things with this device.

Originally I wrote this driver for the VEML6030 but the VEML7700 expose exactly the same interface over I2C so it is possible to use it to communicate with them as well. If doing so, you can also rename the driver struct on import with:

use veml6030::Veml6030 as Veml7700;

Where to go from here?

There is much more information and example programs in the crate documentation.
If you encounter any issues, please report them in the issue tracker.
Feedback, suggestions and improvements are gladly welcome.


Special thanks to SDC Systems for sponsoring the development of this driver and contributing the title pictures.
Thanks to my friend Dr. Daniel Cazacu for helping me with some of the math.
The pictures in this post are under Copyright (C) 2019 by SDC Systems (reproduced here with permission).

What’s next?

I have been writing many other platform-agnostic Rust drivers although I am slow to announce them here. If you want to know what I am currently working on you can follow me on github.

Thanks for reading and stay tuned!

Links: Source code - Crate - Documentation