Using the BME680 sensor with nvidia jetson boards part I
Bosch’s BME680 is a very interesting component. It is a four in one sensor, which can measure temperature, humidity, pressure and air quality. Unfortunately there is no official support for using the sensor with arm64 linux. This article shows a kernel based approach to use this sensor with NVIDIA’s arm64 based Jetson boards.
Connecting the sensor
First of all the sensor has to be connected to an i2c port of the Jetson board. There is no difference whether we use a TX2, Nano or Xavier board for this. The pin Layout of the Raspberry based GPIO connector (for example J12 on Xavier NX, J42 on Nano and J21 on TX2)123 is the same with all these boards. After connecting the sensor to the pins 1-9-5-3, as shown above, we can check the connection using i2detect. If we can see a device with i2c address 0x77 or 0x76 everything is connected properly.
root@jetson:/usr/src# i2cdetect -ry 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1 using receive byte commands. I will probe address range 0x03-0x77. Continue? [Y/n] 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- 77
Building the kernel modules
During Google Sommer of Code 2018 Himanshu Jha has developed a kernel based driver for the bme680 sensor4. The kernel supplied by nvidia (4.9.140) does not support the BME680 sensor. Mainline kernel started supporting this sensor with version 4.19. Fortunately the required kernel module can also be built against the older NVIDIA supplied kernel. So we just have to get the kernel source of a kernel version supporting the sensor. This time we will use the most recent 4.19 kernel:
wget http://www.kernel.org/pub/linux/kernel/v4.x/linux-4.19.116.tar.gz
We just need to extract the drivers/iio/chemical subtree of the kernel source for building the bme680 sensors kernel module.
tar --strip-components=3 -xzf linux-4.19.116.tar.gz linux-4.19.116/drivers/iio/chemical
After extracting, we have to configure the build. To do so, prepend the following lines to the Makefile in this subtree:
CONFIG_BME680=m CONFIG_BME680_I2C=m
Afterwards build the kernel module5 and install the binaries to the modules folder:
make -C /lib/modules/`uname -r`/build M=$PWD make -C /lib/modules/`uname -r`/build M=$PWD modules_install
Once the kernel modules have been installed as shown above, we can load the the kernel module with modprobe bme680_i2c. This can be automated on startup by adding the module to /etc/modules-load.d/modules.conf.
Using the sensor via sysfs
To use the sensor we have to register it with the kernels i2c subsystem6. This could be added to a startup script, for example /etc/rc.local.
echo bme680 0x77 > /sys/bus/i2c/devices/i2c-1/new_device
Depending on sensor configuration the i2c address can be 0x76 or 0x77. Once the sensor is registered, the sensors readings can be acquired using the sysfs interface:
grep ^ /dev/null /sys/bus/i2c/devices/i2c-1/1-0077/iio_device/*input* /sys/bus/i2c/devices/i2c-1/1-0077/iio_device/in_humidityrelative_input:45.503000000 /sys/bus/i2c/devices/i2c-1/1-0077/iio_device/in_pressure_input:1005.830000000 /sys/bus/i2c/devices/i2c-1/1-0077/iio_device/in_resistance_input:60726 /sys/bus/i2c/devices/i2c-1/1-0077/iio_device/in_temp_input:25100
Unfortunately the kernel driver does not support the calibration of the sensor and just outputs the resistance value of the air quality sensor. So calculating CO2 equivalent or air quality from the sensors readings has to be done in userspace. Usually this calculation is being done using Bosch’s closed source BSEC library which cannot be used on arm64 architecture or within kernel context. A promising approach on self-calculating the air quality from the raw sensors readings has been shown in pimoronii forums7. According to this, the IAQ8 air quality index ranging from 0 to 500, can be calculated from the bme680 readings using the following formula:
iaq = log(gas_reading) + 0.04 * humidity_reading
For completeness, the bme680 device can be unregistered6 from the kernels i2c subsystem as follows:
echo 0x77 > /sys/bus/i2c/devices/i2c-1/delete_device
Jürgen
References:
1. jetsonhacks.com: jetson-tx2 pinout
2. jetsonhacks.com: jetson-nano pinout
3. jetsonhacks.com: jetson-xavier-nx pinout
4. himanshujha199640.wordpress.com: bme680 driver
5. kernel.org: external modules build
6. erlerobotics.gitbooks.io: i2c kernel devices
7. pimoronii forums: calculation air quality from bme680 readings
8. wikipedia.org: Air quality index