Registered User m (Clarify DT creation) |
Registered User |
||
(7 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
<br> | <br> | ||
The IKS01Ax boards are expansion boards that | The IKS01Ax boards are expansion boards that include several motion MEMS such as, HTS221 and LSM6DSx. | ||
Sensors available on IKS01A2 expansion board: | Sensors available on IKS01A2 expansion board: | ||
Line 20: | Line 20: | ||
This article provides step-by-step instructions to: | This article provides step-by-step instructions to: | ||
* configure Linux software to support IKS01Ax expansion board | * configure the Linux software to support IKS01Ax expansion board | ||
* activate/use several motion MEMS such as HTS221 and LSM6DSx | * activate/use several motion MEMS such as HTS221 and LSM6DSx | ||
==Prerequisites== | ==Prerequisites== | ||
Line 29: | Line 29: | ||
[[File: STM32MP157C-DK2_angle2.jpg|thumb|upright=2|center|link=|STM32MP157C-DK2]] | [[File: STM32MP157C-DK2_angle2.jpg|thumb|upright=2|center|link=|STM32MP157C-DK2]] | ||
For more information about the STM32 discovery board and how to start it up, | For more information about the STM32 discovery board and how to start it up, see section: [[Getting_started/STM32MP1_boards/STM32MP157x-DK2]] | ||
* IKS01Ax expansion boards | * IKS01Ax expansion boards | ||
{| class="st-table" style="text-align:center; margin: auto" | {| class="st-table" style="text-align:center; margin:auto; width:90%" | ||
| style="border-style: hidden;" | [[Image:en.x-nucleo-iks01a2_image.jpg | 200px]] | | style="width: 50%; border-style: hidden;" | [[Image:en.x-nucleo-iks01a2_image.jpg | 200px]] | ||
| style="border-style: hidden;" | [[Image:en.x-nucleo-iks01a3_image.jpg | 300px]] | | style="width: 50%; border-style: hidden;" | [[Image:en.x-nucleo-iks01a3_image.jpg | 300px]] | ||
|- | |- | ||
| style="border-style: hidden | | style="border-style: hidden;" | '''IKS01A2 expansion board'''</span> | ||
| style="border-style: hidden | | style="border-style: hidden;" | '''IKS01A3 expansion board'''</span> | ||
|} | |} | ||
===Software prerequisites=== | ===Software prerequisites=== | ||
The STM32MP157C-DK2 board must be downloaded with appropriate software in order to support IKS01Ax expansion board. For proceeding, follow the step-by-step instructions provided at [[Getting_started/STM32MP1_boards/STM32MP157x-DK2/Let%27s_start|STM32MP157C-DK2 Let's start]]. | The STM32MP157C-DK2 board must be downloaded with the appropriate software in order to support IKS01Ax expansion board. For proceeding, follow the step-by-step instructions provided at [[Getting_started/STM32MP1_boards/STM32MP157x-DK2/Let%27s_start|STM32MP157C-DK2 Let's start]]. | ||
==Software customization to support IKS01Ax expansion board == | ==Software customization to support IKS01Ax expansion board == | ||
Line 51: | Line 51: | ||
By default, the motion MEMS drivers present on IKS01Ax expansion board are enabled in STM32MP1 kernel configuration: HTS221, pressure(LP22HB) and LSM6DSx. The device tree must be updated to declare and activate them. | By default, the motion MEMS drivers present on IKS01Ax expansion board are enabled in STM32MP1 kernel configuration: HTS221, pressure(LP22HB) and LSM6DSx. The device tree must be updated to declare and activate them. | ||
To check whether associated drivers are enabled inside the kernel, type the commands provided | To check whether associated drivers are enabled inside the kernel, type the commands provided below: | ||
{{Board$}} cat /proc/config.gz | gunzip | grep HTS221 | {{Board$}} cat /proc/config.gz | gunzip | grep HTS221 | ||
Line 77: | Line 77: | ||
====Hardware / software interface==== | ====Hardware / software interface==== | ||
The HTS221 and LSM6DSx motion MEMS present on IKS01Ax expansion board are involved in | The HTS221 and LSM6DSx motion MEMS present on IKS01Ax expansion board are involved in use cases, such as, measurement of temperature, measurement of humidity, read Accelerometer / Gyroscope data.<br> | ||
According to IKS01A2 user manual<ref name="User Manual of IKS01A2"> IKS01A2 User Manual | According to IKS01A2 user manual<ref name="User Manual of IKS01A2"> IKS01A2 User Manual | ||
[https://www.st.com/resource/en/user_manual/dm00333132.pdf]</ref> and IKS01A3 user manual<ref name="User Manual of | [https://www.st.com/resource/en/user_manual/dm00333132.pdf]</ref> and IKS01A3 user manual<ref name="User Manual of IKS01A3"> IKS01A3 User Manual [https://www.st.com/resource/en/user_manual/dm00601501.pdf]</ref>, both motion MEMS are controlled by I<sup>2</sup>C bus. | ||
In the schematics of IKS01A2 <ref name="Schematics of IKS01A2"> IKS01A2 Schematics [https://www.st.com/resource/en/schematic_pack/x-nucleo-iks01a2_schematic.pdf]</ref> and STM32MP157C-DK2<ref name="Schematics of STM32MP157C-DK2">STM32MP157C-DK2 Schematics | In the schematics of IKS01A2 <ref name="Schematics of IKS01A2"> IKS01A2 Schematics [https://www.st.com/resource/en/schematic_pack/x-nucleo-iks01a2_schematic.pdf]</ref> and STM32MP157C-DK2<ref name="Schematics of STM32MP157C-DK2"> [[STM32 MPU resources#MB1272 schematics|STM32MP157C-DK2 Schematics]]</ref> presented below, the pins that are interconnected are highlighted. | ||
* IKS01A2 schematic (Arduino connector) <ref name="Schematics of IKS01A2"/> | * IKS01A2 schematic (Arduino connector) <ref name="Schematics of IKS01A2"/> | ||
** Pins 10 and 9 of CN5 are used for I<sup>2</sup>C Bus (SDA and SCL) (I2C1 and I2C2 bus instances are mixed via JP7 and JP8 jumpers) | ** Pins 10 and 9 of CN5 are used for I<sup>2</sup>C Bus (SDA and SCL) (I2C1 and I2C2 bus instances are mixed via JP7 and JP8 jumpers). | ||
** Pins 6 and 5 of CN9 are used to manage interruptions on LSM6DSL motion MEMS (indicated for information: not used on kernel configuration). | ** Pins 6 and 5 of CN9 are used to manage interruptions on LSM6DSL motion MEMS (indicated for information: not used on kernel configuration). | ||
Line 91: | Line 91: | ||
*STM32MP157C-DK2 schematic (Arduino connector) <ref name="Schematics of STM32MP157C-DK2"/> | *STM32MP157C-DK2 schematic (Arduino connector) <ref name="Schematics of STM32MP157C-DK2"/> | ||
** Pins 10 and 9 of CN5 are used for I<sup>2</sup>C Bus (I2C5_SDA and I2C5_SCL) | ** Pins 10 and 9 of CN5 are used for I<sup>2</sup>C 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) | ** Pins 6 and 5 of CN14 are used to manage interruptions on LSM6DSL motion MEMS (indicated for information: not used on kernel configuration). | ||
[[File:Arduino_stm32mp157c-dk2_schematic.png|thumb|center|800px|alt=Screenshot stm32mp157c-dk2|stm32mp157c-dk2 schematics extract]] | [[File:Arduino_stm32mp157c-dk2_schematic.png|thumb|center|800px|alt=Screenshot stm32mp157c-dk2|stm32mp157c-dk2 schematics extract]] | ||
{{Warning|I2C5''' bus instance MUST be enabled by software in order to access the motion MEMS present on IKS01A2}} | {{Warning|I2C5''' bus instance MUST be enabled by the software in order to access the motion MEMS present on IKS01A2}} | ||
====Kernel device tree configuration==== | ====Kernel device tree configuration==== | ||
As indicated in previous section, the IKS01Ax expansion board is controlled via I<sup>2</sup>C bus. On STM32MP157C-DK2, the associated I<sup>2</sup>C bus is '''I2C5'''. | As indicated in the previous section, the IKS01Ax expansion board is controlled via I<sup>2</sup>C bus. On STM32MP157C-DK2, the associated I<sup>2</sup>C bus is '''I2C5'''. | ||
The I2C5 bus must be activated into STM32MP157C-DK2 device tree and a node must be added for each hardware to be supported (see entries | The I2C5 bus must be activated into STM32MP157C-DK2 device tree and a node must be added for each hardware to be supported (see entries such as '''hts221''', as shown in the device tree content example below). | ||
To perform this, create stm32mp157c-dk2-iks01ax.dtb file with the following content: | |||
{| class="st-table" style="text-align:left; margin: auto" | {| class="st-table" style="text-align: left; margin: auto" | ||
| style="width:400px;" | '''IKS01A2 expansion board'''</span> | | style="width:400px;" | '''IKS01A2 expansion board'''</span> | ||
| style="width:400px;" | '''IKS01A3 expansion board'''</span> | | style="width:400px;" | '''IKS01A3 expansion board'''</span> | ||
Line 139: | Line 139: | ||
reg = <0x5f>; | reg = <0x5f>; | ||
}; | }; | ||
lsm6dso@6b { | |||
compatible = "st,lsm6dso"; | compatible = "st,lsm6dso"; | ||
reg = <0x6b>; | reg = <0x6b>; | ||
Line 147: | Line 147: | ||
|} | |} | ||
Do not forget to update arch/arm/boot/dts/Makefile to add this DT in the compilation list. | |||
{{Info|To generate a new device tree, | {{Info|To generate a new device tree, follow the indications given in [[Getting_started/STM32MP1_boards/STM32MP157x-DK2/Develop_on_Arm®_Cortex®-A7/Modify,_rebuild_and_reload_the_Linux®_kernel|Modify, rebuild and reload the Linux® kernel]] }} | ||
===Activate the new configuration in the STM32MP157C-DK2 board=== | ===Activate the new configuration in the STM32MP157C-DK2 board=== | ||
Line 161: | Line 161: | ||
/boot/stm32mp157c-dk2-m4-examples.dtb | /boot/stm32mp157c-dk2-m4-examples.dtb | ||
/boot/stm32mp157c-dk2.dtb | /boot/stm32mp157c-dk2.dtb | ||
{{ReviewsComments|-- [[User:Emmanuel Combette|Emmanuel Combette]] ([[User talk:Emmanuel Combette|talk]]) 16:17, 26 May 2021 (CEST)<br />stm32mp157c-dk2-iks01ax.dtb does not exist anymore in V3.0.0 image}} | |||
{{ReviewsComments|-- [[User:Christophe Priouzeau|Christophe Priouzeau]] ([[User talk:Christophe Priouzeau|talk]]) 16:31, 26 May 2021 (CEST)<br />On previous section 3.2.2, you can see request to user to create the file with this name stm32mp157c-dk2-iks01ax.dts}} | |||
* Add a new entry in stm32mp157c-dk2_extlinux.conf file located in '''/boot/mmc0_extlinux/'''. If the mmc0_<something> directory is not available, add the new entry in '''/boot/mmc0_extlinux/extlinux.conf'''. | * Add a new entry in stm32mp157c-dk2_extlinux.conf file located in '''/boot/mmc0_extlinux/'''. If the mmc0_<something> directory is not available, add the new entry in '''/boot/mmc0_extlinux/extlinux.conf'''. | ||
Line 237: | Line 238: | ||
{{Info|With IKS01A3, lsm6dsl is replaced by lsm6dso }} | {{Info|With IKS01A3, lsm6dsl is replaced by lsm6dso }} | ||
{{Info|If the results are different, check that | {{Info|If the results are different, check that: | ||
# the expansion board is correctly connected | # the expansion board is correctly connected | ||
# all steps, described above, were correctly done.}} | # all steps, described above, were correctly done.}} | ||
==Read motion MEMS via bash script== | ==Read motion MEMS via bash script== | ||
The goal of this section is to read the | The goal of this section is to read the information provided by the Linux kernel interface and to process it with a bash script. | ||
=== List of sensor entries === | === List of sensor entries === | ||
The IKS01Ax expansion board provides several MEMS | The IKS01Ax expansion board provides several MEMS such as, HTS221, LSM6DSx, LPS22HB.<br> | ||
The list of hardware MEMS detected by Linux via the [[IIO overview|IIO framework]] can be verified in the sysfs. | The list of hardware MEMS detected by Linux via the [[IIO overview|IIO framework]] can be verified in the sysfs. | ||
Line 260: | Line 261: | ||
The HTS221 is a capacitive digital sensor for relative humidity and temperature. | The HTS221 is a capacitive digital sensor for relative humidity and temperature. | ||
In this example, '''hts221''' entry is '''/sys/bus/iio/devices/iio:device0/'''. In case the user has a different setup, the entry | In this example, '''hts221''' entry is '''/sys/bus/iio/devices/iio:device0/'''. In case the user has a different setup, the entry must be adapted accordingly in the scripts provided hereafter. | ||
====Temperature==== | ====Temperature==== | ||
Line 272: | Line 273: | ||
'''Temperature''' = ( '''Raw''' value + '''Offset''' value) * '''Scale''' value) | '''Temperature''' = ( '''Raw''' value + '''Offset''' value) * '''Scale''' value) | ||
* Calculate temperature by shell script : '''static''' IIO entries | * Calculate temperature by shell script: '''static''' IIO entries | ||
Content of '''hts221_read_temperature_on_device0.sh''': | Content of '''hts221_read_temperature_on_device0.sh''': | ||
<syntaxhighlight lang="bash" class="noscroll"> | <syntaxhighlight lang="bash" class="noscroll"> | ||
Line 710: | Line 711: | ||
==Read motion MEMS via Python script== | ==Read motion MEMS via Python script== | ||
The goal of this section is to read the | The goal of this section is to read the information provided by Linux kernel interface and process it with a python script.<br/> | ||
The python displays the calculated value through a graphic user interface. | The python displays the calculated value through a graphic user interface. | ||
Line 763: | Line 764: | ||
===Read temperature=== | ===Read temperature=== | ||
Part of code for reading temperature with HTS221 driver: | Part of the code for reading temperature with HTS221 driver: | ||
<syntaxhighlight lang="python" class="noscroll"> | <syntaxhighlight lang="python" class="noscroll"> | ||
def found_iio_device_with_name(data, name): | def found_iio_device_with_name(data, name): | ||
Line 809: | Line 810: | ||
===Read humidity=== | ===Read humidity=== | ||
Part of code for reading humidity with HTS221 driver: | Part of the code for reading humidity with HTS221 driver: | ||
<syntaxhighlight lang="python" class="noscroll"> | <syntaxhighlight lang="python" class="noscroll"> | ||
def found_iio_device_with_name(data, name): | def found_iio_device_with_name(data, name): | ||
Line 855: | Line 856: | ||
===Read accelerometer=== | ===Read accelerometer=== | ||
Part of code for reading accelerometer with LSM6DSx driver: | Part of the code for reading accelerometer with LSM6DSx driver: | ||
<syntaxhighlight lang="python" class="noscroll"> | <syntaxhighlight lang="python" class="noscroll"> | ||
def found_iio_device_with_name(data, name): | def found_iio_device_with_name(data, name): | ||
Line 912: | Line 913: | ||
===Read gyroscope=== | ===Read gyroscope=== | ||
Part of code for reading gyroscope with LSM6DSx driver: | Part of the code for reading gyroscope with LSM6DSx driver: | ||
<syntaxhighlight lang="python" class="noscroll"> | <syntaxhighlight lang="python" class="noscroll"> | ||
def found_iio_device_with_name(data, name): | def found_iio_device_with_name(data, name): | ||
Line 1,260: | Line 1,261: | ||
<noinclude> | <noinclude> | ||
{{PublicationRequestId | 12269 | {{PublicationRequestId | 22134 | 2022-01-04 |review done by Souad in stm32mpu-v3 wiki - previous : 12269 / 07Jun'19}} | ||
[[Category:Sub-articles]] | |||
</noinclude> | </noinclude> |
Latest revision as of 12:15, 10 January 2023
1. Article purpose
The purpose of this article is to explain how to integrate IKS01A2 and IKS01A3 expansion boards with STM32MP157C-DK2, managed by Linux® on Cortex®-A7.
The IKS01Ax boards are expansion boards that include several motion MEMS such as, HTS221 and LSM6DSx.
Sensors available on IKS01A2 expansion board:
- LSM6DSL: MEMS 3D accelerometer (±2/±4/±8/±16 g) and 3D gyroscope (±125/±245/±500/±1000/±2000 dps)
- LSM303AGR: MEMS 3D accelerometer (±2/±4/±8/±16 g) and MEMS3D magnetometer (±50 gauss)
- LPS22HB: MEMS pressure sensor, 260-1260 hPa absolute digital output barometer
- HTS221: capacitive digital relative humidity and temperature
Sensors available on IKS01A3 expansion board:
- LSM6DSO: MEMS 3D accelerometer (±2/±4/±8/±16 g) + 3D gyroscope (±125/±250/±500/±1000/±2000 dps)
- LIS2MDL: MEMS 3D magnetometer (±50 gauss)
- LIS2DW12: MEMS 3D accelerometer (±2/±4/±8/±16 g)
- LPS22HH: MEMS pressure sensor, 260-1260 hPa absolute digital output barometer
- HTS221: capacitive digital relative humidity and temperature
- STTS751: Temperature sensor (–40 °C to +125 °C)
This article provides step-by-step instructions to:
- configure the Linux software to support IKS01Ax expansion board
- activate/use several motion MEMS such as HTS221 and LSM6DSx
2. Prerequisites
2.1. Hardware prerequisites
- STM32MP157C-DK2
For more information about the STM32 discovery board and how to start it up, see section: Getting_started/STM32MP1_boards/STM32MP157x-DK2
- IKS01Ax expansion boards
2.2. Software prerequisites
The STM32MP157C-DK2 board must be downloaded with the appropriate software in order to support IKS01Ax expansion board. For proceeding, follow the step-by-step instructions provided at STM32MP157C-DK2 Let's start.
3. Software customization to support IKS01Ax expansion board
The STM32MP157C-DK2 Linux software must be configured to activate the IKS01Ax board connected on top of the STM32MP157C-DK2 board.
The configuration consists in modifying the STM32MP157C-DK2 Linux kernel and managing some new device tree elements.
3.1. Kernel configuration
By default, the motion MEMS drivers present on IKS01Ax expansion board are enabled in STM32MP1 kernel configuration: HTS221, pressure(LP22HB) and LSM6DSx. The device tree must be updated to declare and activate them.
To check whether associated drivers are enabled inside the kernel, type the commands provided below:
Board $> cat /proc/config.gz | gunzip | grep HTS221
CONFIG_HTS221=y
CONFIG_HTS221_I2C=y
CONFIG_HTS221_SPI=y
Board $> 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
Board $> 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
File:Info.png | On Linux kernel, LSM6DSL MEMS and LSM6DSO MEMS are managed by the same kernel configuration: CONFIG_IIO_ST_LSM6DSX |
File:Info.png | If the above configurations are not enabled, follow the indications given in Modify, rebuild and reload the Linux® kernel |
3.2. Kernel device tree configuration
3.2.1. Hardware / software interface
The HTS221 and LSM6DSx motion MEMS present on IKS01Ax expansion board are involved in use cases, such as, measurement of temperature, measurement of humidity, read Accelerometer / Gyroscope data.
According to IKS01A2 user manual[1] and IKS01A3 user manual[2], both motion MEMS are controlled by I2C bus.
In the schematics of IKS01A2 [3] and STM32MP157C-DK2[4] presented below, the pins that are interconnected are highlighted.
- IKS01A2 schematic (Arduino connector) [3]
- Pins 10 and 9 of CN5 are used for I2C Bus (SDA and SCL) (I2C1 and I2C2 bus instances are mixed via JP7 and JP8 jumpers).
- 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) [4]
- 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).
![]() |
I2C5 bus instance MUST be enabled by the software in order to access the motion MEMS present on IKS01A2 |
3.2.2. Kernel device tree configuration
As indicated in the previous section, the IKS01Ax expansion board is controlled via I2C bus. On STM32MP157C-DK2, the associated I2C bus is I2C5.
The I2C5 bus must be activated into STM32MP157C-DK2 device tree and a node must be added for each hardware to be supported (see entries such as hts221, as shown in the device tree content example below).
To perform this, create stm32mp157c-dk2-iks01ax.dtb file with the following content:
IKS01A2 expansion board | IKS01A3 expansion board |
/dts-v1/;
#include "stm32mp157c-dk2.dts"
&i2c5 {
status = "okay";
hts221@5f {
compatible = "st,hts221";
reg = <0x5f>;
};
lsm6dsl@6b {
compatible = "st,lsm6dsl";
reg = <0x6b>;
};
};
|
/dts-v1/;
#include "stm32mp157c-dk2.dts"
&i2c5 {
status = "okay";
hts221@5f {
compatible = "st,hts221";
reg = <0x5f>;
};
lsm6dso@6b {
compatible = "st,lsm6dso";
reg = <0x6b>;
};
};
|
Do not forget to update arch/arm/boot/dts/Makefile to add this DT in the compilation list.
File:Info.png | To generate a new device tree, follow the indications given in Modify, rebuild and reload the Linux® kernel |
3.3. Activate the new configuration in the STM32MP157C-DK2 board
- Prerequisites: The device tree and the Linux kernel must have been regenerated. If not done yet, follow the indications given in Modify, rebuild and reload the Linux® kernel
- Add the two generated files in the board file system, precisely in the bootfs partition (/boot directory)
Board $> ls -1 /boot/stm32*dk2*
/boot/stm32mp157c-dk2-a7-examples.dtb
/boot/stm32mp157c-dk2-iks01ax.dtb
/boot/stm32mp157c-dk2-m4-examples.dtb
/boot/stm32mp157c-dk2.dtb
- Add a new entry in stm32mp157c-dk2_extlinux.conf file located in /boot/mmc0_extlinux/. If the mmc0_<something> directory is not available, add the new entry in /boot/mmc0_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-iks01ax
LABEL OpenSTLinux
KERNEL /uImage
FDTDIR /
INITRD /uInitrd
APPEND root=PARTUUID=e91c4e10-16e6-4c0e-bd0e-77becf4a3582 rootwait rw console=ttySTM0,115200
LABEL stm32mp157c-dk2-a7-examples
KERNEL /uImage
FDT /stm32mp157c-dk2-a7-examples.dtb
INITRD /uInitrd
APPEND root=PARTUUID=e91c4e10-16e6-4c0e-bd0e-77becf4a3582 rootwait rw console=ttySTM0,115200
LABEL stm32mp157c-dk2-m4-examples
KERNEL /uImage
FDT /stm32mp157c-dk2-m4-examples.dtb
INITRD /uInitrd
APPEND root=PARTUUID=e91c4e10-16e6-4c0e-bd0e-77becf4a3582 rootwait rw console=ttySTM0,115200
LABEL stm32mp157c-dk2-iks01ax
KERNEL /uImage
FDT /stm32mp157c-dk2-iks01ax.dtb
APPEND root=PARTUUID=e91c4e10-16e6-4c0e-bd0e-77becf4a3582 rootwait rw console=ttySTM0,115200
![]() |
Do not forget to synchronize the file system before rebooting the board Board $> sync |
- Reboot the board
3.4. Verify the new configuration on board
- Verify if i2c5 is enabled:
Board $> cat /proc/device-tree/soc/i2c\@40015000/status
okay
- Verify if the motion MEMS drivers are declared in the device tree node:
Board $> ls -l /proc/device-tree/soc/i2c\@40015000/
total 0
-r--r--r-- 1 root root 4 Feb 7 15:56 #address-cells
-r--r--r-- 1 root root 4 Feb 7 15:56 #size-cells
-r--r--r-- 1 root root 4 Feb 7 15:56 clock-frequency
-r--r--r-- 1 root root 8 Feb 7 15:56 clocks
-r--r--r-- 1 root root 17 Feb 7 15:56 compatible
drwxr-xr-x 2 root root 0 Feb 7 15:51 hts221@5f
-r--r--r-- 1 root root 4 Feb 7 15:56 i2c-scl-falling-time-ns
-r--r--r-- 1 root root 4 Feb 7 15:56 i2c-scl-rising-time-ns
-r--r--r-- 1 root root 12 Feb 7 15:56 interrupt-names
-r--r--r-- 1 root root 28 Feb 7 15:56 interrupts-extended
drwxr-xr-x 2 root root 0 Feb 7 15:51 lsm6dsl@6b
-r--r--r-- 1 root root 4 Feb 7 15:56 name
-r--r--r-- 1 root root 4 Feb 7 15:56 pinctrl-0
-r--r--r-- 1 root root 4 Feb 7 15:56 pinctrl-1
-r--r--r-- 1 root root 14 Feb 7 15:56 pinctrl-names
-r--r--r-- 1 root root 4 Feb 7 15:56 power-domains
-r--r--r-- 1 root root 8 Feb 7 15:56 reg
-r--r--r-- 1 root root 8 Feb 7 15:56 resets
-r--r--r-- 1 root root 12 Feb 7 15:56 st,syscfg-fmp
-r--r--r-- 1 root root 5 Feb 7 15:56 status
-r--r--r-- 1 root root 0 Feb 7 15:56 wakeup-source
File:Info.png | With IKS01A3, lsm6dsl@6b is replaced by lsm6dso@6b |
- Verify if the motion MEMS drivers are correctly probed and if the system provides access to the associated hardware:
Board $> grep OF_NAME /sys/bus/iio/devices/iio\:device*/uevent
/sys/bus/iio/devices/iio:device0/uevent:OF_NAME=hts221
/sys/bus/iio/devices/iio:device1/uevent:OF_NAME=lsm6dsl
/sys/bus/iio/devices/iio:device2/uevent:OF_NAME=lsm6dsl
File:Info.png | With IKS01A3, lsm6dsl is replaced by lsm6dso |
File:Info.png | If the results are different, check that:
|
4. Read motion MEMS via bash script
The goal of this section is to read the information provided by the Linux kernel interface and to process it with a bash script.
4.1. List of sensor entries
The IKS01Ax expansion board provides several MEMS such as, HTS221, LSM6DSx, LPS22HB.
The list of hardware MEMS detected by Linux via the IIO framework can be verified in the sysfs.
Board $> grep OF_NAME /sys/bus/iio/devices/iio\:device*/uevent
/sys/bus/iio/devices/iio:device0/uevent:OF_NAME=hts221
/sys/bus/iio/devices/iio:device1/uevent:OF_NAME=lsm6dsl
/sys/bus/iio/devices/iio:device2/uevent:OF_NAME=lsm6dsl
File:Info.png | With IKS01A3, lsm6dsl is replaced by lsm6dso |
This list provides the association between entries and MEMS drivers. In the rest of the article, this list is used a as reference.
4.2. HTS221: Temperature/Humidity
The HTS221 is a capacitive digital sensor for relative humidity and temperature.
In this example, hts221 entry is /sys/bus/iio/devices/iio:device0/. In case the user has a different setup, the entry must be adapted accordingly in the scripts provided hereafter.
4.2.1. Temperature
- Read IIO entries associated to the temperature for HTS221 driver
Board $> cat /sys/bus/iio/devices/iio\:device0/in_temp_raw
Board $> cat /sys/bus/iio/devices/iio\:device0/in_temp_offset
Board $> cat /sys/bus/iio/devices/iio\:device0/in_temp_scale
- Calculate real temperature according with the following formula
Temperature = ( Raw value + Offset value) * Scale value)
- Calculate temperature by shell script: static IIO entries
Content of hts221_read_temperature_on_device0.sh:
#!/bin/sh
raw=`cat /sys/bus/iio/devices/iio\:device0/in_temp_raw`
offset=`cat /sys/bus/iio/devices/iio\:device0/in_temp_offset`
scale=`cat /sys/bus/iio/devices/iio\:device0/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
Board $> ./hts221_read_temperature_on_device0.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
- Read IIO entries associated to humidity for HTS221 driver
Board $> cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_raw
Board $> cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_offset
Board $> cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_scale
- Calculate real humidity according with the following formula
Humidity = ( Raw value + Offset value) * Scale value)
- Calculate humidity by shell script: static IIO entries
Content of hts221_read_humidity_on_device0.sh:
#!/bin/sh
raw=`cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_raw`
offset=`cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_offset`
scale=`cat /sys/bus/iio/devices/iio\:device0/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
Board $> ./hts221_read_humidity_on_device0.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 and LSM6DS0: accelerometer/gyroscope
LSM6DSL and LSM6DS0 are inertial measurement unit (IMU) with ultra-low power and high accuracy, for smartphones and battery operated IoT, gaming, wearables and consumer electronics.
In this example, lsm6dsl entries are /sys/bus/iio/devices/iio:device1/ and /sys/bus/iio/devices/iio:device2/.
The device2 entry is dedicated to accelerometer and the device1 one to gyroscope.
4.3.1. Accelerometer
- Read IIO entries associated to accelerometer for LSM6DSx driver
Board $> cat /sys/bus/iio/devices/iio\:device2/in_accel_scale
Board $> cat /sys/bus/iio/devices/iio\:device2/in_accel_x_raw
Board $> cat /sys/bus/iio/devices/iio\:device2/in_accel_y_raw
Board $> cat /sys/bus/iio/devices/iio\:device2/in_accel_z_raw
- Calculate accelerometer values according with the 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 LMS6DSx_accel_read_on_device2.sh:
#!/bin/sh
rscale=`cat /sys/bus/iio/devices/iio\:device2/in_accel_scale`
xraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_x_raw`
yraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_y_raw`
zraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
- Calculate accelerometer value by shell script: auto detection of IIO entries
Content of LMS6DSx_accel_read_with_entry_detection.sh:
#!/bin/sh
DRIVER_NAME=LMS6DSx_accel
for d in `ls -d1 /sys/bus/iio/devices/*device*`;
do
if grep -q $DRIVER_NAME $d/name ;
then
rscale=`cat $d/in_accel_x_scale`
xraw=`cat $d/in_accel_x_raw`
yraw=`cat $d/in_accel_y_raw`
zraw=`cat $d/in_accel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
break;
fi
done
- Test on board
Board $> ./LMS6DSx_accel_read_on_device2.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
- Read IIO entries associated to gyroscope for LSM6DSx driver
Board $> cat /sys/bus/iio/devices/iio\:device1/in_anglvel_scale
Board $> cat /sys/bus/iio/devices/iio\:device1/in_anglvel_x_raw
Board $> cat /sys/bus/iio/devices/iio\:device1/in_anglvel_y_raw
Board $> cat /sys/bus/iio/devices/iio\:device1/in_anglvel_z_raw
- 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 LMS6DSx_gyro_read_on_device1.sh:
#!/bin/sh
rscale=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_scale`
xraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_x_raw`
yraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_y_raw`
zraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$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 LMS6DSx_gyro_read_with_entry_detection.sh:
#!/bin/sh
DRIVER_NAME=LMS6DSx_gyro
for d in `ls -d1 /sys/bus/iio/devices/*device*`;
do
if grep -q $DRIVER_NAME $d/name ;
then
rscale=`cat $d/in_anglvel_scale`
xraw=`cat $d/in_anglvel_x_raw`
yraw=`cat $d/in_anglvel_y_raw`
zraw=`cat $d/in_anglvel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
break;
fi
done
- Test on board
Board $> ./LMS6DSx_gyro_read_on_device1.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
- Content of iks01a2.sh
#!/bin/sh
echo "============================="
echo "=== HTS221 ==="
echo "=== (temperature) ==="
echo "============================="
raw=`cat /sys/bus/iio/devices/iio\:device0/in_temp_raw`
offset=`cat /sys/bus/iio/devices/iio\:device0/in_temp_offset`
scale=`cat /sys/bus/iio/devices/iio\:device0/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\:device0/in_humidityrelative_raw`
offset=`cat /sys/bus/iio/devices/iio\:device0/in_humidityrelative_offset`
scale=`cat /sys/bus/iio/devices/iio\:device0/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 "=== LSM6DSx ==="
echo "=== (accelerometer) ==="
echo "============================="
rscale=`cat /sys/bus/iio/devices/iio\:device2/in_accel_scale`
xraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_x_raw`
yraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_y_raw`
zraw=`cat /sys/bus/iio/devices/iio\:device2/in_accel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
echo "============================="
echo "=== LSM6DSx ==="
echo "=== (gyroscope) ==="
echo "============================="
xscale=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_scale`
xraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_x_raw`
yraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_y_raw`
zraw=`cat /sys/bus/iio/devices/iio\:device1/in_anglvel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$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 LMS6DSx_accel $d/name ;
then
echo "============================="
echo "=== LSM6DSx ==="
echo "=== (accelerometer) ==="
echo "============================="
rscale=`cat $d/in_accel_scale`
xraw=`cat $d/in_accel_x_raw`
yraw=`cat $d/in_accel_y_raw`
zraw=`cat $d/in_accel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Accelerometer value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
fi
# for lsm6dsl: gyroscope
if grep -q LMS6DSx_gyro $d/name ;
then
echo "============================="
echo "=== LSM6DSx ==="
echo "=== (gyroscope) ==="
echo "============================="
rscale=`cat $d/in_anglvel_scale`
xraw=`cat $d/in_anglvel_x_raw`
yraw=`cat $d/in_anglvel_y_raw`
zraw=`cat $d/in_anglvel_z_raw`
printf "Value read: X (raw/scale) %d / %.06f \n" $xraw $rscale
printf "Value read: Y (raw/scale) %d / %.06f \n" $yraw $rscale
printf "Value read: Z (raw/scale) %d / %.06f \n" $zraw $rscale
factor=`echo "scale=2;256.0 / 9.81" | bc`
xval=`echo "scale=2;$xraw*$rscale*$factor" | bc`
yval=`echo "scale=2;$yraw*$rscale*$factor" | bc`
zval=`echo "scale=2;$zraw*$rscale*$factor" | bc`
printf "Gyroscope value: [ %.02f, %.02f, %.02f ]\n" $xval $yval $zval
fi
done
5. Read motion MEMS via Python script
The goal of this section is to read the information provided by Linux kernel interface and process it with a python script.
The python displays the calculated value through a graphic user interface.
5.1. Display a window with Python and weston/wayland
#!/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
Part of the 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
Part of the 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
Part of the code for reading accelerometer with LSM6DSx 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")
if prefix_path is None:
prefix_path = found_iio_device_with_name("in_anglvel_x_raw", "lsm6dso")
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_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'scale', exc)
rscale = 0.0
accel_x = int(xraw * rscale * 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
accel_y = int(yraw * rscale * 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
accel_z = int(zraw * rscale * 256.0 / 9.81)
5.5. Read gyroscope
Part of the code for reading gyroscope with LSM6DSx 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")
if prefix_path is None:
prefix_path = found_iio_device_with_name("in_anglvel_x_raw", "lsm6dso")
try:
with open(prefix_path + "in_anglvel_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'scale', exc)
rscale = 0.0
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
gyro_x = int(xraw * rscale * 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
gyro_y = int(yraw * rscale * 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
gyro_z = int(zraw * rscale * 256.0 / 9.81)
5.6. Full script with information displayed in a graphic user interface
#!/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")
if self.sensor_dictionnary['accelerometer'] is None:
self.sensor_dictionnary['accelerometer'] = self.found_iio_device_with_name("in_accel_x_raw", "lsm6dso")
self.sensor_dictionnary['gyroscope'] = self.found_iio_device_with_name("in_anglvel_x_raw", "lsm6dsl")
if self.sensor_dictionnary['gyroscope'] is None:
self.sensor_dictionnary['gyroscope'] = self.found_iio_device_with_name("in_anglvel_x_raw", "lsm6dso")
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_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_accel_" + 'scale', exc)
rscale = 0.0
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
accel_x = int(xraw * rscale * 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
accel_y = int(yraw * rscale * 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
accel_z = int(zraw * rscale * 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_" + 'scale', 'r') as f:
rscale = float(f.read())
except Exception as exc:
print("[ERROR] read %s " % prefix_path + "in_anglvel_" + 'scale', exc)
rscale = 0.0
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
gyro_x = int(xraw * rscale * 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
gyro_y = int(yraw * rscale * 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
gyro_z = int(zraw * rscale * 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(homogeneous=False, 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(homogeneous=False, spacing=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(homogeneous=False, spacing=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(homogeneous=False, spacing=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(homogeneous=False, spacing=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)
GLib.timeout_add(TIME_UPATE, self.update_ui)
def destroy(self, widget, data=None):
Gtk.main_quit()
def update_ui(self):
# 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 showing the results in the graphic user interface
5.7. More screenshot examples with results displayed in a graphic user interface
6. References
- ↑ IKS01A2 User Manual [1]
- ↑ IKS01A3 User Manual [2]
- ↑ Jump up to: 3.0 3.1 IKS01A2 Schematics [3]
- ↑ Jump up to: 4.0 4.1 STM32MP157C-DK2 Schematics