============================== 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 https://github.com/raspberrypi/linux We use kernel v6.6, replace 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 .. code-block:: kconfig 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 .. code-block:: makefile 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 .. code-block:: 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 | Accel[g] = accel_raw * accel_scale | Anglvel[°/s] = anglvel_raw * anglvel_scale | T[°C] = (temp_raw + temp_offset) * temp_scale 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