Bosch SMI240 IIO driver
1. Overview
The driver is intended to work on Bosch SMI240 Inertial Measurement Unit for Non-Safety Automotive Applications. The SMI240 is a combined three axis angular rate and three axis acceleration sensor module with a measurement range of +/-300°/s and up to 16g. SMI240 is a 6 DoF (Degrees of Freedom) sensor module providing acceleration and angular rate signals via a digital interface (SPI). The sensor consists of two Micro Electro Mechanical System (MEMS) elements and a sensor readoutASIC. The ASIC contains analogue front ends and a digital structure for signal processing and communication interface. The sensor module is available in a LGA (Land Grid Array) housing.
2. Hardware Setup
Important
This Hardware Setup serves as a quick startup kit, to help the user to run and understand the driver. It is for demonstration purposes, not supposed to be used in a production environment.
2.1 Hardware Components:
Linux Host Board
SMI240 sensor + Shuttleboard + Motherboard (acquirable from Bosch)
connection cable (female to female)
A micro SD card (if required by the host board)
2.2 Jumpers on the mother board
We need to change the default Jumpers.
Remove the jumper “Connection VDDIO” and put this jumper to connect “VDD” and “VDDIO”
Make sure that
Both BUS_ID_0 and BUS_ID_1 are connected to GND
2.3 Cable Connection
................................. .................................
.?^^^^^^^^^^~~~~~~~~^^^^^^^^^^^^^~? VDD !!^^^^^^^^^~~~~~~~~~~~~~~^^^^^^^^7~
:? Host Board Y~~~~~~~~~~~~~~~~~~~~J~ 1 SMI240 Mother Board !!
:? .J VDDIO ?^ !~
:? .Y~~~~~~~~~~~~~~~~~~~~J^ 2 !~
:? .J 7^ !~
:? .J GND 7^ !~
:? .Y~~~~~~~~~~~~~~~~~~~~J~ 3 !~
:? .J MISO ?^ !~
:? .Y~~~~~~~~~~~~~~~~~~~~J~ 4 !~
:? .Y MOSI J~ !~
:? .J~~~~~~~~~~~~~~~~~~~~?~ 5 !~
:? .Y SLK J~ !~
:? .Y~~~~~~~~~~~~~~~~~~~~J~ 6 !~
:? .J CSB 7^ !~
:? .J~~~~~~~~~~~~~~~~~~~~7^ 7 !~
:? .J 7^ !~
:? .J 7^ !~
:? .J 7^ BUS_ID_0 !~~GND
:? .Y J^ !~
:? .J ?^ BUS_ID_1 !~~GND
:? Y J^ !~
:J...............................:J 7~...............................7~
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^.
SMI240 Shuttle Pin |
Function |
---|---|
1 |
VDD |
2 |
VDD IO |
3 |
GND |
4 |
MISO |
5 |
MOSI |
6 |
SCLK |
7 |
CSB |
2.4 First Startup
Write Linux Image (32 bit) to SD Card
Insert SD Card Host Board and power on
Enable SSH on Host Board
3. Software Setup
This example is based on a Raspberry Pi 3. If you are using a different host board, the steps are slightly different.
3.1 Required Software
Raspberry Pi 3 as host board (tested Linux kernel versions 6.1.21 and 6.6)
SMI240 IIO Linux driver https://github.com/boschmemssolutions/SMI240-Linux-Driver-IIO
Linux development environment (native or as VM)
Hint
Most board manufacturer provides customized Linux distribution for their boards. Consult with your board manufacturer. And download the Linux distribution for your board, if available.
Note
We do not recommend to build the driver with Linux kernel directly on host board. This takes too long. Build it on PC is much faster. Since the toolchain is Linux based, a Linux environment is required. We use Ubuntu 22.04.5 LTS
Install Toolchain and dependences
sudo apt install crossbuild-essential-armhf
sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev
Clone Linux kernel
git clone --depth=1 --branch <branch_name> https://github.com/raspberrypi/linux
We use kernel v6.6, replace <branch_name> with “rpi-6.6.y”
Clone SMI240 IIO Linux driver
git clone --depth=1 https://github.com/boschmemssolutions/SMI240-Linux-Driver-IIO.git
3.2 Build SMI240 IIO Linux driver
Integrate Linux driver into Linux kernel
Copy source code into Linux kernel
cp /smi240-linux-driver-iio/drivers/iio/imu/smi240 linux/drivers/iio/imu
Add entry in imu Kconfig
Open linux/drivers/iio/imu/Kconfig and add the SMI240 entry at bottom
source "drivers/iio/imu/.../Kconfig"
source "drivers/iio/imu/smi240/Kconfig"
source "drivers/iio/imu/.../Kconfig"
Add entry in imu Makefile
Open linux/drivers/iio/accel/Makefile and add the SMI240 entry at bottom
obj-y += smi240/
obj-y += s.../
Add devicetree overlay
Create a devicetree overlay file “smi240-spi-overlay.dts” with the following content, and put it under “linux/arch/arm/boot/dts/overlays”
Note
Dependent on your hardware plattform and pin layout, the settings may be diffrent and an adaption to your target system may be required.
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835";
fragment@0 {
target = <&spidev0>;
__dormant__ {
status = "disabled";
};
};
fragment@1 {
target = <&spidev1>;
__dormant__ {
status = "disabled";
};
};
fragment@2 {
target = <&spi0>;
__dormant__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
smi240@0 {
compatible = "bosch,smi240";
spi-max-frequency = <10000000>;
reg = <0>;
};
};
};
__overrides__ {
smi240 = <0>, "=0=2";
};
};
Add entry in devicetree overlay Makefile
dtbo-$(CONFIG_ARCH_BCM2835) += \
... \
smi240-spi.dtbo \
... \
Build SMI240 Linux driver with the kernel
Config SMI240 Linux driver
cd linux
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Activate the options as following
Hint
To activate an option, press “y” on the option. A * appears, which means this option is activated as part of the kernel. Alternatively we can press “m” on the option. A “M” appears, which means this option is activated as kernel module (not as part of the kernel). Therefore we need to manually install the kernel module by ourself.
Device Drivers -->
<*>Industrial I/O support --->
Inertial measurement units --->
<*> Bosch Sensor SMI240 Inertial Measurement Unit
Build SMI240 Linux driver
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
Note
Build process takes quite long on the first time. To reduce the build time, we use the option “-j4”. This is the option to enable the build process to be executed parallelly in 4 threads. To improve the parallel execution, just give a big number e.g. “-j6”. How many parallel thread to use is dependent on your processor core number.
Install the kernel with SMI240 Linux driver in SD card
insert the SD card (created in 2.3). A “bootfs” partition and a “rootfs” partition will be mounted. Find out the mount point. In Ubuntu the mount point looks like that
/media/username/bootfs
/media/username/rootfs
write the kernel with SMI240 Linux driver in SD card
export KERNEL=kernel7
export SD_BOOT_PATH=/media/username/bootfs
export SD_ROOTFS_PATH=/media/username/rootfs
sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=$SD_ROOTFS_PATH modules_install
sudo cp $SD_BOOT_PATH/$KERNEL.img $SD_BOOT_PATH/$KERNEL-backup.img
sudo cp arch/arm/boot/zImage $SD_BOOT_PATH/$KERNEL.img
sudo cp arch/arm/boot/dts/*.dtb $SD_BOOT_PATH
sudo cp arch/arm/boot/dts/overlays/*.dtb* $SD_BOOT_PATH/overlays/
sudo cp arch/arm/boot/dts/overlays/README $SD_BOOT_PATH/overlays/
adapt the boot configuraion
open the “config.txt” in “bootfs” partition, and add the following entries
# Uncomment some or all of these to enable the optional hardware interfaces
dtparam=spi=on
dtoverlay=smi240-spi,smi240
Take the SD card out and put it back in board.
4. Work with SMI240 Linux driver
4.1 Preparation
Power on the board. If the driver was installed properly, a folder will be created. A number of devicefiles are created in the folders, which we can use to read/write data from/to the sensor
/sys/bus/iio/devices/iio:device0
Note
Folder name is assigned automatically by the system, therefore does not reflect the sensor type. There is a “name” file in the devicefolder, that we can read to find out the sensor type
cd /sys/bus/iio/devices/iio:device0
cat name
smi240
Work with driver using command line
Note
To change sensor settings we need root access. It is not sufficient just using “sudo …” .
sudo su
4.2 Read data from sensor
$ cat in_accel_x_raw
37
$ cat in_accel_y_raw
4
$ cat in_accel_z_raw
2030
$ cat in_anglvel_x_raw
-16
$ cat in_anglvel_y_raw
33
$ cat in_anglvel_z_raw
35
$ cat in_temp_object_raw
610
To convert raw data to physical values, we can read scale and offset values
$ cat in_accel_scale
0.000500
$ cat in_anglvel_scale
0.010000
$ cat in_temp_object_scale
0.003906250
$ cat in_temp_object_offset
6400
4.3 Change sensor settings
Set the -3dB cut-off frequency for the accelerometer
$ echo 50 > in_accel_filter_low_pass_3db_frequency
Note
50 = 50 hz, 400 = 400 Hz
Set the -3dB cut-off frequency for the gyroscope
$ echo 50 > in_anglvel_filter_low_pass_3db_frequency
Note
50 = 50 hz, 400 = 400 Hz
4.4 Read synchronized data from IIO buffer
The driver uses IIO buffer to push the synchronized sensor data to the user space application. To read the data from user space, the Linux kernel provides a C program under tools/iio. We need to compile and upload it to the target board first.
$ cd tools
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- iio
$ scp tools/iio/iio_generic_buffer to your board
We also need to create a trigger (e.g. sysfs trigger):
$ echo 0 > /sys/devices/iio_sysfs_trigger/add_trigger
Hint
Maybe you need to modprobe iio-trig-sysfs
In one terminal we can trigger events:
$ echo 1 > /sys/bus/iio/devices/trigger0/trigger_now
In another terminal we can execute the iio_generic_buffer program:
$ sudo ./iio_generic_buffer -n smi240 -a -l 256 -c -1 -T 0
iio device number being used is 0
iio trigger number being used is 0
Enabling all channels
Enabling: in_accel_y_en
Enabling: in_temp_object_en
Enabling: in_anglvel_z_en
Enabling: in_accel_x_en
Enabling: in_timestamp_en
Enabling: in_anglvel_y_en
Enabling: in_accel_z_en
Enabling: in_anglvel_x_en
/sys/bus/iio/devices/iio:device0 sysfstrig0
27.453125 0.022000 0.001500 1.012000 -0.240000 0.330000 0.130000 1723918279362596240
27.480469 0.027500 0.003500 1.013500 0.060000 0.530000 0.140000 1723918280416508114
27.503906 0.020000 0.004000 1.015000 0.210000 0.610000 0.090000 1723918283157345249
27.476562 0.023000 0.002000 1.017500 -0.120000 0.090000 -0.100000 1723918283626415613
27.453125 0.021000 0.002500 1.014000 -0.080000 0.670000 0.250000 1723918284054354467
27.464844 0.020000 0.001500 1.013000 0.400000 0.500000 0.190000 1723918284499537905
27.492188 0.022000 0.002500 1.014500 -0.110000 0.400000 0.080000 1723918284874394675
^CCaught signal 2
Disabling: in_accel_y_en
Disabling: in_temp_object_en
Disabling: in_anglvel_z_en
Disabling: in_accel_x_en
Disabling: in_timestamp_en
Disabling: in_anglvel_y_en
Disabling: in_accel_z_en
Disabling: in_anglvel_x_en
The first value represents the temperature in °C. The next three values are x, y and z of the accelerometer in g. The next three values are x, y and z of the gyroscope in °/s. The last value is the timestamp in ns.
Instead of auto-activate all channels, we can de-/activate the channels manually
$ echo 0 > buffer0/in_anglvel_x_en
$ echo 0 > buffer0/in_anglvel_y_en
$ echo 0 > buffer0/in_anglvel_z_en
$ echo 1 > buffer0/in_accel_x_en
$ echo 1 > buffer0/in_accel_y_en
$ echo 1 > buffer0/in_accel_z_en
$ echo 1 > buffer0/in_timestamp_en
$ echo 0 > buffer0/in_temp_object_en