1. Article purpose[edit source]
The purpose of this article is to explain how to integrate the IKS01A2 expansion board with STM32MP157C-DK2, managed by Linux on Cortex-A7.
IKS01A2 board is an expansion board composed by several motion MEMS like HTS221 and LSM6DSL.
This article explains step by step:
- how to configure Linux software to support IKS01A2 expansion board,
- how to activate/use several motions MEMS such as HTS221 and LSM6DSL.
2. Prerequisites[edit source]
2.1. Hardware prerequisites[edit source]
- STM32MP157C-DK2
For more information about this STM32 discovery board and how to start with it, jump to this section Getting_started/STM32MP1_boards/STM32MP157C-DK2
- IKS01A2 expansion board
2.2. Software prerequisites[edit source]
The STM32MP157C-DK2 board must be populate with software to be able to customize it to support IKS01A2 expansion board. To know how to proceed please follow the step-by-step description starting with STM32MP157C-DK2 Let's start article.
3. Software customization to support IKS01A2 expansion board[edit source]
STM32MP157C-DK2 Linux software must be configured to activate IKS01A2 board connected on top of STM32MP157C-DK2 board.
Configuration is done by modifying the STM32MP157C-DK2 Linux kernel and by managing some new device tree elements.
3.1. Kernel configuration[edit source]
By default the motions MEMS drivers, present on IKS01A2 expansion board, are enabled in STM32MP1 kernel configuration: hts221, pressure(lp22hb) and lsm6dsl. The device tree must be updated to declare and activate them.
To check whether associated drivers are enabled inside the kernel, follow commands given below :
cat /proc/config.gz | gunzip | grep HTS221 CONFIG_HTS221=y CONFIG_HTS221_I2C=y CONFIG_HTS221_SPI=y
cat /proc/config.gz | gunzip | grep ST_PRESS CONFIG_IIO_ST_PRESS=m CONFIG_IIO_ST_PRESS_I2C=m CONFIG_IIO_ST_PRESS_SPI=m
cat /proc/config.gz | gunzip | grep ST_LSM6DS CONFIG_IIO_ST_LSM6DSX=m CONFIG_IIO_ST_LSM6DSX_I2C=m CONFIG_IIO_ST_LSM6DSX_SPI=m
3.2. Kernel device tree configuration[edit source]
3.2.1. Hardware / software interface[edit source]
Motions MEMS HTS221 and LSM6DSL, present on IKS01A2 expansion board are used in the use case explained in this article.
According to IKS01A2 user manual[1], both motion MEMS are controlled by I2C bus.
In schematics of IKS01A2 [2] and STM32MP157C-DK2[3] , presented below, are identified the pins which are connected together.
- IKS01A2 Schematic (Arduino connector) [2]
- Pins 10 and 9 of CN5 are used for I2C Bus (SDA and SCL) (I2C1 and I2C2 bus instances are mixed via the jumper JP7 and JP8)
- Pins 6 and 5 of CN9 are used to manage interruptions on LSM6DSL motion MEMS (indicated for information: not used on kernel configuration).
- STM32MP157C-DK2 Schematic (Arduino connector) [3]
- Pins 10 and 9 of CN5 are used for I2C Bus (I2C5_SDA and I2C5_SCL)
- Pins 6 and 5 of CN14 are used to manage interruptions on LSM6DSL motion MEMS (indicated for information: not used on kernel configuration)
3.2.2. Kernel device tree configuration[edit source]
As seen in previous chapter, IKS01A2 expansion board is controlled via IC2 bus. On STM32MP157C-DK2, the associated I2C bus is I2C5.
I2C5 bus must be activated into STM32MP157C-DK2 device tree and a node for each hardware to support must be added (see entry on device tree like hts221, below, on the following device tree content).
For that, add following content into stm32mp157c-dk2.dts file:
&i2c5 { pinctrl-names = "default", "sleep"; pinctrl-0 = <&i2c5_pins_a>; pinctrl-1 = <&i2c5_pins_sleep_a>; i2c-scl-rising-time-ns = <124>; i2c-scl-falling-time-ns = <3>; /delete-property/dmas; /delete-property/dma-names; status = "okay"; hts221@5f { compatible = "st,hts221"; reg = <0x5f>; }; lsm6dsl@6b { compatible = "st,lsm6dsl"; reg = <0x6b>; }; };
3.3. Activate the new configuration in the STM32MP157C-DK2 board[edit source]
- Prerequisites: Device tree and Linux kernel must have been regenerated. If not already done, please follow the indications given in Modify, rebuild and reload the Linux® kernel
- Add the two generated files on file system of board, more accurately in bootfs partition (/boot directory)
ls -1 /boot/stm32*dk2* /boot/stm32mp157c-dk2-a7-examples.dtb /boot/stm32mp157c-dk2-iks01a2.dtb /boot/stm32mp157c-dk2-m4-examples.dtb /boot/stm32mp157c-dk2.dtb
- Add an new entry in extlinux.conf file, here located in /boot/mmc0_stm32mp157c-dk2_extlinux/. If no directory mmc0_<something> is available, add the new entry in /boot/extlinux/extlinux.conf.
# Generic Distro Configuration file generated by OpenEmbedded menu title Select the boot mode MENU BACKGROUND ../splash.bmp TIMEOUT 20 DEFAULT stm32mp157c-dk2-iks01a2 LABEL stm32mp157c-dk2-sdcard KERNEL /uImage FDT /stm32mp157c-dk2.dtb APPEND root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200 LABEL stm32mp157c-dk2-a7-examples-sdcard KERNEL /uImage FDT /stm32mp157c-dk2-a7-examples.dtb APPEND root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200 LABEL stm32mp157c-dk2-m4-examples-sdcard KERNEL /uImage FDT /stm32mp157c-dk2-m4-examples.dtb APPEND root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200 LABEL stm32mp157c-dk2-iks01a2 KERNEL /uImage FDT /stm32mp157c-dk2-iks01a2.dtb APPEND root=/dev/mmcblk0p6 rootwait rw console=ttySTM0,115200
- Reboot the board
3.4. Verify the new configuration on board[edit source]
- Verify if i2c5 is enabled:
cat /proc/device-tree/soc/i2c\@40015000/status okay
- Verify if motions MEMS drivers are declared on device tree node:
ls -l /proc/device-tree/soc/i2c\@40015000/
total 0 -r--r--r-- 1 root root 4 Dec 19 11:01 #address-cells -r--r--r-- 1 root root 4 Dec 19 11:01 #size-cells -r--r--r-- 1 root root 8 Dec 19 11:01 clocks -r--r--r-- 1 root root 15 Dec 19 11:01 compatible -r--r--r-- 1 root root 6 Dec 19 11:01 dma-names -r--r--r-- 1 root root 32 Dec 19 11:01 dmas drwxr-xr-x 2 root root 0 Dec 19 10:54 hts221@5f -r--r--r-- 1 root root 4 Dec 19 11:01 i2c-scl-falling-time-ns -r--r--r-- 1 root root 4 Dec 19 11:01 i2c-scl-rising-time-ns -r--r--r-- 1 root root 19 Dec 19 11:01 interrupt-names -r--r--r-- 1 root root 44 Dec 19 11:01 interrupts-extended drwxr-xr-x 2 root root 0 Dec 19 10:54 lsm6dsl@6b -r--r--r-- 1 root root 4 Dec 19 11:01 name -r--r--r-- 1 root root 4 Dec 19 11:01 pinctrl-0 -r--r--r-- 1 root root 4 Dec 19 11:01 pinctrl-1 -r--r--r-- 1 root root 14 Dec 19 11:01 pinctrl-names -r--r--r-- 1 root root 4 Dec 19 11:01 power-domains -r--r--r-- 1 root root 8 Dec 19 11:01 reg -r--r--r-- 1 root root 8 Dec 19 11:01 resets -r--r--r-- 1 root root 12 Dec 19 11:01 st,syscfg-fmp -r--r--r-- 1 root root 5 Dec 19 11:01 status
- Verify if motions MEMS drivers are correctly probed and if the system provides access to associated hardware:
grep OF_NAME /sys/bus/iio/devices/iio\:device*/uevent /sys/bus/iio/devices/iio:device0/uevent:OF_NAME=adc /sys/bus/iio/devices/iio:device1/uevent:OF_NAME=adc /sys/bus/iio/devices/iio:device2/uevent:OF_NAME=hts221 /sys/bus/iio/devices/iio:device3/uevent:OF_NAME=temp /sys/bus/iio/devices/iio:device4/uevent:OF_NAME=lsm6dsl /sys/bus/iio/devices/iio:device5/uevent:OF_NAME=lsm6dsl
4. Read motion MEMS via bash script[edit source]
The goal of this section are to read the informations provided by Linux Kernel interface and process it on a bash script.
4.1. List of sensors entry[edit source]
IKS01A2 expansion board provides several MEMS like HTS221, LSM6DSL, LPS22HB. Hardware MEMS detected by Linux via the IIO framework can be listed by verifying the entries on sysfs.
grep OF_NAME /sys/bus/iio/devices/iio\:device*/uevent /sys/bus/iio/devices/iio:device0/uevent:OF_NAME=adc /sys/bus/iio/devices/iio:device1/uevent:OF_NAME=adc /sys/bus/iio/devices/iio:device2/uevent:OF_NAME=hts221 /sys/bus/iio/devices/iio:device3/uevent:OF_NAME=temp /sys/bus/iio/devices/iio:device4/uevent:OF_NAME=lsm6dsl /sys/bus/iio/devices/iio:device5/uevent:OF_NAME=lsm6dsl
This list of entries permits to know which entries are associated to a MEMS driver. In the rest of the article, this list is kept as reference list of entries.
4.2. HTS221: Temperature/Humidity[edit source]
HTS221 is a capacitive digital sensor for relative humidity and temperature.
In this example, hts221 entries are /sys/bus/iio/devices/iio:device2/, please adapt to your setup if it's not the case by changing the entry on the scripts described/explained in following chapters.
4.2.1. Temperature[edit source]
- Read IIO entries associated to temperature for HTS221 driver
cat /sys/bus/iio/devices/iio\:device2/in_temp_raw cat /sys/bus/iio/devices/iio\:device2/in_temp_offset cat /sys/bus/iio/devices/iio\:device2/in_temp_scale
- Calculate real temperature according following formula
Temperature = ( Raw value + Offset value) * Scale value)
- Calculate temperature by shell script : static IIO entries
Content of hts221_read_temperature_on_device2.sh:
#!/bin/sh raw=`cat /sys/bus/iio/devices/iio\:device2/in_temp_raw` offset=`cat /sys/bus/iio/devices/iio\:device2/in_temp_offset` scale=`cat /sys/bus/iio/devices/iio\:device2/in_temp_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale temperature=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Temperature $temperature" printf "Temperature %.01f\n" $temperature
- Calculate temperature by shell script: auto detection of IIO entries
Content of hts221_read_temperature_with_entry_detection.sh:
#!/bin/sh DRIVER_NAME=hts221 for d in `ls -d1 /sys/bus/iio/devices/*device*`; do if grep -q $DRIVER_NAME $d/name ; then raw=`cat $d/in_temp_raw` offset=`cat $d/in_temp_offset` scale=`cat $d/in_temp_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale temperature=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Temperature $temperature" printf "Temperature %.01f\n" $temperature break; fi done
- Test on board
./hts221_read_temperature_on_device2.sh Value read: raw 563.000000 Value read: offset 1036.674817 Value read: scale 0.019172 Temperature 30.668765624 Temperature 30.7
4.2.2. Humidity[edit source]
- Read IIO entries associated to humidity for HTS221 driver
cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_raw cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_offset cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_scale
- Calculate real humidity according following formula
Humidity = ( Raw value + Offset value) * Scale value)
- Calculate humidity by shell script: static IIO entries
Content of hts221_read_humidity_on_device2.sh:
#!/bin/sh raw=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_raw` offset=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_offset` scale=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale humidity=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Humidity $humidity" printf "Humidity %.01f\n" $humidity
- Calculate humidity by shell script: auto detection of IIO entries
Content of hts221_read_humidity_with_entry_detection.sh:
#!/bin/sh DRIVER_NAME=hts221 for d in `ls -d1 /sys/bus/iio/devices/*device*`; do if grep -q $DRIVER_NAME $d/name ; then raw=`cat $d/in_humidityrelative_raw` offset=`cat $d/in_humidityrelative_offset` scale=`cat $d/in_humidityrelative_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale humidity=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Humidity $humidity" printf "Humidity %.01f\n" $humidity break; fi done
- Test on board
./hts221_read_humidity_on_device2.sh Value read: raw 2669.000000 Value read: offset -10661.500000 Value read: scale -0.003000 Humidity 23.977500000 Humidity 24.0
4.3. LSM6DSL: accelerometer/gyroscope[edit source]
LSM6DSL is an inertial measurement unit (IMU), for smartphones and battery operated IoT, gaming, wearable and consumer electronics. ultra-low power and high accuracy.
In this example, lsm6dsl entries are /sys/bus/iio/devices/iio:device4/ and /sys/bus/iio/devices/iio:device4/.
Device4 entry is dedicated to accelerometer and device5 one to gyroscope.
4.3.1. Accelerometer[edit source]
- Read IIO entries associated to accelerometer for LSM6DSL driver
cat /sys/bus/iio/devices/iio\:device4/in_accel_x_raw cat /sys/bus/iio/devices/iio\:device4/in_accel_x_scale cat /sys/bus/iio/devices/iio\:device4/in_accel_y_raw cat /sys/bus/iio/devices/iio\:device4/in_accel_y_scale cat /sys/bus/iio/devices/iio\:device4/in_accel_z_raw cat /sys/bus/iio/devices/iio\:device4/in_accel_z_scale
- Calculate accelerometer values according following formula
X = Raw value * scale value * (256.0 / 9.81) Y = Raw value * scale value * (256.0 / 9.81) Z = Raw value * scale value * (256.0 / 9.81)
- Calculate accelerometer value by shell script: static IIO entries
Content of lsm6dsl_accel_read_on_device4.sh:
#!/bin/sh xraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_x_raw` xscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_x_scale` yraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_y_raw` yscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_y_scale` zraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_z_raw` zscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
- Calculate accel value by shell script: auto detection of IIO entries
Content of lsm6dsl_accel_read_with_entry_detection.sh:
#!/bin/sh DRIVER_NAME=lsm6dsl_accel for d in `ls -d1 /sys/bus/iio/devices/*device*`; do if grep -q $DRIVER_NAME $d/name ; then xraw=`cat $d/in_accel_x_raw` xscale=`cat $d/in_accel_x_scale` yraw=`cat $d/in_accel_y_raw` yscale=`cat $d/in_accel_y_scale` zraw=`cat $d/in_accel_z_raw` zscale=`cat $d/in_accel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval break; fi done
- Test on board
./lsm6dsl_accel_read_on_device4.sh Value read: X (raw/scale) 104 / 0.000598 Value read: Y (raw/scale) -16378 / 0.000598 Value read: Z (raw/scale) -1117 / 0.000598 Accelerometer value: [ 1.62, -255.53, -17.43 ]
4.3.2. Gyroscope[edit source]
- Read IIO entries associated to gyroscope for LSM6DSL driver
cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_raw cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_scale cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_raw cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_scale cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_raw cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_scale
- Calculate gyroscope values according following formula
X = Raw value * scale value * (256.0 / 9.81) Y = Raw value * scale value * (256.0 / 9.81) Z = Raw value * scale value * (256.0 / 9.81)
- Calculate gyroscope value by shell script: static IIO entries
Content of lsm6dsl_gyro_read_on_device5.sh:
#!/bin/sh xraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_raw` xscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_scale` yraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_raw` yscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_scale` zraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_raw` zscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
- Calculate gyroscope value by shell script: auto detection of IIO entries
Content of lsm6dsl_gyro_read_with_entry_detection.sh:
#!/bin/sh DRIVER_NAME=lsm6dsl_gyro for d in `ls -d1 /sys/bus/iio/devices/*device*`; do if grep -q $DRIVER_NAME $d/name ; then xraw=`cat $d/in_anglvel_x_raw` xscale=`cat $d/in_anglvel_x_scale` yraw=`cat $d/in_anglvel_y_raw` yscale=`cat $d/in_anglvel_y_scale` zraw=`cat $d/in_anglvel_z_raw` zscale=`cat $d/in_anglvel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval break; fi done
- Test on board
./lsm6dsl_gyro_read_on_device5.sh Value read: X (raw/scale) -2293 / 0.000153 Value read: Y (raw/scale) 150 / 0.000153 Value read: Z (raw/scale) -111 / 0.000153 Gyroscope value: [ -9.15, 0.60, -0.44 ]
4.4. BASH: script with all the measurements[edit source]
- Content of iks01a2.sh
#!/bin/sh echo "=============================" echo "=== HTS221 ===" echo "=== (temperature) ===" echo "=============================" raw=`cat /sys/bus/iio/devices/iio\:device2/in_temp_raw` offset=`cat /sys/bus/iio/devices/iio\:device2/in_temp_offset` scale=`cat /sys/bus/iio/devices/iio\:device2/in_temp_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale temperature=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Temperature $temperature" printf "Temperature %.02f\n" $temperature echo "=============================" echo "=== HTS221 ===" echo "=== (humidity) ===" echo "=============================" raw=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_raw` offset=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_offset` scale=`cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale humidity=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Humidity $humidity" printf "Humidity %.02f\n" $humidity echo "=============================" echo "=== LSM6DSL ===" echo "=== (accelerometer) ===" echo "=============================" xraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_x_raw` xscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_x_scale` yraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_y_raw` yscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_y_scale` zraw=`cat /sys/bus/iio/devices/iio\:device4/in_accel_z_raw` zscale=`cat /sys/bus/iio/devices/iio\:device4/in_accel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval echo "=============================" echo "=== LSM6DSL ===" echo "=== (gyroscope) ===" echo "=============================" xraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_raw` xscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_x_scale` yraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_raw` yscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_y_scale` zraw=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_raw` zscale=`cat /sys/bus/iio/devices/iio\:device5/in_anglvel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
- Content of iks01a2_with_auto_detection.sh
#!/bin/sh for d in `ls -d1 /sys/bus/iio/devices/*device*`; do # for hts221: Temperature + Humidity if grep -q hts221 $d/name ; then echo "=============================" echo "=== HTS221 ===" echo "=== (temperature) ===" echo "=============================" raw=`cat $d/in_temp_raw` offset=`cat $d/in_temp_offset` scale=`cat $d/in_temp_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale temperature=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Temperature $temperature" printf "Temperature %.02f\n" $temperature echo "=============================" echo "=== HTS221 ===" echo "=== (humidity) ===" echo "=============================" raw=`cat $d/in_humidityrelative_raw` offset=`cat $d/in_humidityrelative_offset` scale=`cat $d/in_humidityrelative_scale` printf "Value read: raw %0f\n" $raw printf "Value read: offset %0f\n" $offset printf "Value read: scale %0f\n" $scale humidity=`echo "scale=2;$raw*$scale + $offset*$scale" | bc` echo "Humidity $humidity" printf "Humidity %.02f\n" $humidity fi # for lsm6dsl: accelerometer if grep -q lsm6dsl_accel $d/name ; then echo "=============================" echo "=== LSM6DSL ===" echo "=== (accelerometer) ===" echo "=============================" xraw=`cat $d/in_accel_x_raw` xscale=`cat $d/in_accel_x_scale` yraw=`cat $d/in_accel_y_raw` yscale=`cat $d/in_accel_y_scale` zraw=`cat $d/in_accel_z_raw` zscale=`cat $d/in_accel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval fi # for lsm6dsl: gyroscope if grep -q lsm6dsl_gyro $d/name ; then echo "=============================" echo "=== LSM6DSL ===" echo "=== (gyroscope) ===" echo "=============================" xraw=`cat $d/in_anglvel_x_raw` xscale=`cat $d/in_anglvel_x_scale` yraw=`cat $d/in_anglvel_y_raw` yscale=`cat $d/in_anglvel_y_scale` zraw=`cat $d/in_anglvel_z_raw` zscale=`cat $d/in_anglvel_z_scale` printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $xscale printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $yscale printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $zscale factor=`echo "scale=2;256.0 / 9.81" | bc` xval=`echo "scale=2;$xraw*$xscale*$factor" | bc` yval=`echo "scale=2;$yraw*$yscale*$factor" | bc` zval=`echo "scale=2;$zraw*$zscale*$factor" | bc` printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval fi done
5. Read motion MEMS via Python script[edit source]
The goal of this section are to read the informations provided by Linux Kernel interface and process it on a python script.
The python will display the value calculated on a window UI.
5.1. Display a window with Python and weston/wayland[edit source]
#!/usr/bin/python3 import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GObject from gi.repository import Gdk from gi.repository import GLib from gi.repository import GdkPixbuf import cairo import random import math import os from time import sleep, time # ------------------------------------------------------------------- # ------------------------------------------------------------------- class MainUIWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Sensor usage") #self.set_decorated(False) self.maximize() self.screen_width = self.get_screen().get_width() self.screen_height = self.get_screen().get_height() self.set_default_size(self.screen_width, self.screen_height) print("[DEBUG] screen size: %dx%d" % (self.screen_width, self.screen_height)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('destroy', Gtk.main_quit) def destroy(self, widget, data=None): Gtk.main_quit() # ------------------------------------------------------------------- # ------------------------------------------------------------------- # Main if __name__ == "__main__": # add signal to catch CRTL+C import signal signal.signal(signal.SIGINT, signal.SIG_DFL) win = MainUIWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main()
5.2. Read temperature[edit source]
Part of code for reading temperature with HTS221 driver:
def found_iio_device_with_name(data, name): prefix = "/sys/bus/iio/devices/" of_name = 'OF_NAME=' + name try: for filefolder in os.listdir(prefix): with open(prefix + '/' + filefolder + '/uevent') as f: for line in f: if line.split('\n')[0] == of_name: ''' return directory which contains "data" ''' if os.path.exists(prefix + '/' + filefolder + '/' + data): return (prefix + '/' + filefolder + '/') except OSError: pass except Exception as exc: pass return None prefix_path = found_iio_device_with_name("in_temp_raw", "hts221") try: with open(prefix_path + "in_temp_" + 'raw', 'r') as f: raw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'raw', exc) raw = 0.0 try: with open(prefix_path + "in_temp_" + 'scale', 'r') as f: scale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'scale', exc) scale = 0.0 try: with open(prefix_path + "in_temp_" + 'offset', 'r') as f: offset = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'offset', exc) offset = 0.0 temp = (offset + raw) * scale
5.3. Read humidity[edit source]
Part of code for reading humidity with HTS221 driver:
def found_iio_device_with_name(data, name): prefix = "/sys/bus/iio/devices/" of_name = 'OF_NAME=' + name try: for filefolder in os.listdir(prefix): with open(prefix + '/' + filefolder + '/uevent') as f: for line in f: if line.split('\n')[0] == of_name: ''' return directory which contains "data" ''' if os.path.exists(prefix + '/' + filefolder + '/' + data): return (prefix + '/' + filefolder + '/') except OSError: pass except Exception as exc: pass return None prefix_path = found_iio_device_with_name("in_humidityrelative_raw", "hts221") try: with open(prefix_path + "in_humidityrelative_" + 'raw', 'r') as f: raw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'raw', exc) raw = 0.0 try: with open(prefix_path + "in_humidityrelative_" + 'scale', 'r') as f: scale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'scale', exc) scale = 0.0 try: with open(prefix_path + "in_humidityrelative_" + 'offset', 'r') as f: offset = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'offset', exc) offset = 0.0 humidity = (offset + raw) * scale
5.4. Read accelerometer[edit source]
Part of code for reading accelerometer with LSM6DSL driver:
def found_iio_device_with_name(data, name): prefix = "/sys/bus/iio/devices/" of_name = 'OF_NAME=' + name try: for filefolder in os.listdir(prefix): with open(prefix + '/' + filefolder + '/uevent') as f: for line in f: if line.split('\n')[0] == of_name: ''' return directory which contains "data" ''' if os.path.exists(prefix + '/' + filefolder + '/' + data): return (prefix + '/' + filefolder + '/') except OSError: pass except Exception as exc: pass return None prefix_path = found_iio_device_with_name("in_accel_x_raw", "lsm6dsl") try: with open(prefix_path + "in_accel_" + 'x_raw', 'r') as f: xraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'x_raw', exc) xraw = 0.0 try: with open(prefix_path + "in_accel_" + 'x_scale', 'r') as f: xscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'x_scale', exc) xscale = 0.0 accel_x = int(xraw * xscale * 256.0 / 9.81) try: with open(prefix_path + "in_accel_" + 'y_raw', 'r') as f: yraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'y_raw', exc) yraw = 0.0 try: with open(prefix_path + "in_accel_" + 'y_scale', 'r') as f: yscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'y_scale', exc) yscale = 0.0 accel_y = int(yraw * yscale * 256.0 / 9.81) try: with open(prefix_path + "in_accel_" + 'z_raw', 'r') as f: zraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'z_raw', exc) zraw = 0.0 try: with open(prefix_path + "in_accel_" + 'z_scale', 'r') as f: zscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'z_scale', exc) zscale = 0.0 accel_z = int(zraw * zscale * 256.0 / 9.81)
5.5. Read gyroscope[edit source]
Part of code for reading gyroscope with LSM6DSL driver:
def found_iio_device_with_name(data, name): prefix = "/sys/bus/iio/devices/" of_name = 'OF_NAME=' + name try: for filefolder in os.listdir(prefix): with open(prefix + '/' + filefolder + '/uevent') as f: for line in f: if line.split('\n')[0] == of_name: ''' return directory which contains "data" ''' if os.path.exists(prefix + '/' + filefolder + '/' + data): return (prefix + '/' + filefolder + '/') except OSError: pass except Exception as exc: pass return None prefix_path = found_iio_device_with_name("in_anglvel_x_raw", "lsm6dsl") try: with open(prefix_path + "in_anglvel_" + 'x_raw', 'r') as f: xraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'x_raw', exc) xraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'x_scale', 'r') as f: xscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'x_scale', exc) xscale = 0.0 gyro_x = int(xraw * xscale * 256.0 / 9.81) try: with open(prefix_path + "in_anglvel_" + 'y_raw', 'r') as f: yraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'y_raw', exc) yraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'y_scale', 'r') as f: yscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'y_scale', exc) yscale = 0.0 gyro_y = int(yraw * yscale * 256.0 / 9.81) try: with open(prefix_path + "in_anglvel_" + 'z_raw', 'r') as f: zraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'z_raw', exc) zraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'z_scale', 'r') as f: zscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'z_scale', exc) zscale = 0.0 gyro_z = int(zraw * zscale * 256.0 / 9.81)
5.6. Full script with information displayed on a windows[edit source]
#!/usr/bin/python3 import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk from gi.repository import GObject from gi.repository import Gdk from gi.repository import GLib from gi.repository import GdkPixbuf import cairo import random import math import os from time import sleep, time # time between each sensor mesearuement (1s) TIME_UPATE = 2000 class Sensors(): def __init__(self): ''' ''' self.sensor_dictionnary = {} def found_iio_device_with_name(self, data, name): prefix = "/sys/bus/iio/devices/" of_name = 'OF_NAME=' + name try: for filefolder in os.listdir(prefix): with open(prefix + '/' + filefolder + '/uevent') as f: for line in f: if line.split('\n')[0] == of_name: ''' return directory which contains "data" ''' if os.path.exists(prefix + '/' + filefolder + '/' + data): return (prefix + '/' + filefolder + '/') except OSError: pass except Exception as exc: pass return None def found_all_sensor_path(self): self.sensor_dictionnary['temperature'] = self.found_iio_device_with_name("in_temp_raw", "hts221") self.sensor_dictionnary['humidity'] = self.found_iio_device_with_name("in_humidityrelative_raw", "hts221") self.sensor_dictionnary['accelerometer'] = self.found_iio_device_with_name("in_accel_x_raw", "lsm6dsl") self.sensor_dictionnary['gyroscope'] = self.found_iio_device_with_name("in_anglvel_x_raw", "lsm6dsl") print("[DEBUG] temperature -> ", self.sensor_dictionnary['temperature'], "<") print("[DEBUG] humidity -> ", self.sensor_dictionnary['humidity'], "<") print("[DEBUG] accelerometer -> ", self.sensor_dictionnary['accelerometer'], "<") print("[DEBUG] gyroscope -> ", self.sensor_dictionnary['gyroscope'], "<") def temperature_read(self): prefix_path = self.sensor_dictionnary['temperature'] try: with open(prefix_path + "in_temp_" + 'raw', 'r') as f: raw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'raw', exc) raw = 0.0 try: with open(prefix_path + "in_temp_" + 'scale', 'r') as f: scale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'scale', exc) scale = 0.0 try: with open(prefix_path + "in_temp_" + 'offset', 'r') as f: offset = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_temp_" + 'offset', exc) offset = 0.0 return (offset + raw) * scale def humidity_read(self): prefix_path = self.sensor_dictionnary['humidity'] try: with open(prefix_path + "in_humidityrelative_" + 'raw', 'r') as f: raw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'raw', exc) raw = 0.0 try: with open(prefix_path + "in_humidityrelative_" + 'scale', 'r') as f: scale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'scale', exc) scale = 0.0 try: with open(prefix_path + "in_humidityrelative_" + 'offset', 'r') as f: offset = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_humidityrelative_" + 'offset', exc) offset = 0.0 return (offset + raw) * scale def accelerometer_read(self): prefix_path = self.sensor_dictionnary['accelerometer'] try: with open(prefix_path + "in_accel_" + 'x_raw', 'r') as f: xraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'x_raw', exc) xraw = 0.0 try: with open(prefix_path + "in_accel_" + 'x_scale', 'r') as f: xscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'x_scale', exc) xscale = 0.0 accel_x = int(xraw * xscale * 256.0 / 9.81) try: with open(prefix_path + "in_accel_" + 'y_raw', 'r') as f: yraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'y_raw', exc) yraw = 0.0 try: with open(prefix_path + "in_accel_" + 'y_scale', 'r') as f: yscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'y_scale', exc) yscale = 0.0 accel_y = int(yraw * yscale * 256.0 / 9.81) try: with open(prefix_path + "in_accel_" + 'z_raw', 'r') as f: zraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'z_raw', exc) zraw = 0.0 try: with open(prefix_path + "in_accel_" + 'z_scale', 'r') as f: zscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_accel_" + 'z_scale', exc) zscale = 0.0 accel_z = int(zraw * zscale * 256.0 / 9.81) return [ accel_x, accel_y, accel_z] def gyroscope_read(self): prefix_path = self.sensor_dictionnary['gyroscope'] try: with open(prefix_path + "in_anglvel_" + 'x_raw', 'r') as f: xraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'x_raw', exc) xraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'x_scale', 'r') as f: xscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'x_scale', exc) xscale = 0.0 gyro_x = int(xraw * xscale * 256.0 / 9.81) try: with open(prefix_path + "in_anglvel_" + 'y_raw', 'r') as f: yraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'y_raw', exc) yraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'y_scale', 'r') as f: yscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'y_scale', exc) yscale = 0.0 gyro_y = int(yraw * yscale * 256.0 / 9.81) try: with open(prefix_path + "in_anglvel_" + 'z_raw', 'r') as f: zraw = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'z_raw', exc) zraw = 0.0 try: with open(prefix_path + "in_anglvel_" + 'z_scale', 'r') as f: zscale = float(f.read()) except Exception as exc: print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'z_scale', exc) zscale = 0.0 gyro_z = int(zraw * zscale * 256.0 / 9.81) return [ gyro_x, gyro_y, gyro_z] # ------------------------------------------------------------------- # ------------------------------------------------------------------- class MainUIWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="Sensor usage") #self.set_decorated(False) self.maximize() self.screen_width = self.get_screen().get_width() self.screen_height = self.get_screen().get_height() self.set_default_size(self.screen_width, self.screen_height) print("[DEBUG] screen size: %dx%d" % (self.screen_width, self.screen_height)) self.set_position(Gtk.WindowPosition.CENTER) self.connect('destroy', Gtk.main_quit) # search sensor interface self.sensors = Sensors() self.sensors.found_all_sensor_path() sensor_box = Gtk.VBox(spacing=0) # temperature temp_label = Gtk.Label() temp_label.set_markup("<span font_desc='LiberationSans 25'>Temperature</span>") self.temp_value_label = Gtk.Label() self.temp_value_label.set_markup("<span font_desc='LiberationSans 25'>--.-- °C</span>") temp_box = Gtk.HBox(False, 0) temp_box.add(temp_label) temp_box.add(self.temp_value_label) sensor_box.add(temp_box) # humidity humidity_label = Gtk.Label() humidity_label.set_markup("<span font_desc='LiberationSans 25'>Humidity</span>") self.humidity_value_label = Gtk.Label() self.humidity_value_label.set_markup("<span font_desc='LiberationSans 25'>--.-- %c</span>" % '%') humidity_box = Gtk.HBox(False, 0) humidity_box.add(humidity_label) humidity_box.add(self.humidity_value_label) sensor_box.add(humidity_box) # Accel accel_label = Gtk.Label() accel_label.set_markup("<span font_desc='LiberationSans 25'>Accelerometer</span>") self.accel_value_label = Gtk.Label() self.accel_value_label.set_markup("<span font_desc='LiberationSans 25'> [ --.--, --.--, --.--]</span>") accel_box = Gtk.HBox(False, 0) accel_box.add(accel_label) accel_box.add(self.accel_value_label) sensor_box.add(accel_box) # Gyroscope gyro_label = Gtk.Label() gyro_label.set_markup("<span font_desc='LiberationSans 25'>Gyroscope</span>") self.gyro_value_label = Gtk.Label() self.gyro_value_label.set_markup("<span font_desc='LiberationSans 25'> [ --.--, --.--, --.--]</span>") gyro_box = Gtk.HBox(False, 0) gyro_box.add(gyro_label) gyro_box.add(self.gyro_value_label) sensor_box.add(gyro_box) self.add(sensor_box) # Add a timer callback to update # this takes 2 args: (how often to update in millisec, the method to run) self.timer = GObject.timeout_add(TIME_UPATE, self.update_ui, None) self.timer_enable = True def destroy(self, widget, data=None): Gtk.main_quit() def update_ui(self, user_data): if False == self.timer_enable: return False; # temperature temp = self.sensors.temperature_read() self.temp_value_label.set_markup("<span font_desc='LiberationSans 25'>%.02f °C</span>" % temp) # humidity hum = self.sensors.humidity_read() self.humidity_value_label.set_markup("<span font_desc='LiberationSans 25'>%.02f %c</span>" % (hum, '%')) # accel accel = self.sensors.accelerometer_read() self.accel_value_label.set_markup("<span font_desc='LiberationSans 25'>[ %.02f, %.02f, %.02f]</span>" % (accel[0], accel[1], accel[2])) # gyro gyro = self.sensors.gyroscope_read() self.gyro_value_label.set_markup("<span font_desc='LiberationSans 25'>[ %.02f, %.02f, %.02f]</span>" % (gyro[0], gyro[1], gyro[2])) # As this is a timeout function, return True so that it # continues to get called return True # ------------------------------------------------------------------- # ------------------------------------------------------------------- # Main if __name__ == "__main__": # add signal to catch CRTL+C import signal signal.signal(signal.SIGINT, signal.SIG_DFL) win = MainUIWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main()
- Screenshot
5.7. Example of screenshot for displaying information[edit source]