Air Quality Sensing with Sensirion’s Environmental Sensing Module
Getting Started with Sensirion SENSEVAL-SCB4XV1 and X-NUCLEO-IKS4A1 Expansion Board

Image Source: snvv/stock.adobe.com
By Youssef Abdelsalam, Mouser Electronics
Published May 29, 2026
In industrial automation, environmental conditions such as temperature, humidity, air quality, and pressure are critical for maintaining efficiency, reliability, and safety. These factors can influence machine performance, product quality, and even worker well-being. For example, in systems such as autonomous mobile robots (AMRs) and edge devices, the ability to sense and respond to these conditions is highly beneficial, enabling them to adapt to dynamic environments, reduce inefficiencies, and support safer operations. To make this possible, Sensirion offers the SENSEVAL SCB4xV1 sensor evaluation board, a compact and easy-to-integrate platform that combines temperature, humidity, volatile organic compound (VOC), and pressure sensing for real-time environmental monitoring.
This project article explains how to extract meaningful data from the sensors on the Sensirion SENSEVAL SCB4xV1 board, as well as motion sensor data from ST’s IKS4A1 expansion module, giving developers the tools to combine environmental and movement measurements in their designs.
Project Materials and Resources
- STMicroelectronics NUCLEO-C092RC Development Board
- STMicroelectronics X-NUCLEO-IKS4A1 Expansion Board
- Sensirion SENSEVAL-SCB4XV1 Evaluation Board
- Adafruit USB Type-C cable
Software and Tools:
- STM32CubeIDE
- STM32CubeMX
- X-CUBE-MEMS1 expansion software package for STM32Cube
- Project GitHub repository
- Sensirion Gas Index Algorithm
- PC running Windows
Project Technology Overview
The following sections provide information on the development boards and technologies we will use in this project.
Development Boards
The STMicroelectronics NUCLEO-C092RC Nucleo-64 development board (Figure 1) offers an affordable and flexible way to build prototypes using the STM32C092RC microcontroller. The board features Arduino Uno R3-compatible headers as well as ST morpho headers for full access to the STM32 inputs and outputs (I/Os). The NUCLEO-C092RC board interfaces with a wide choice of integrated development environments (IDEs), including the STM32CubeIDE. The board integrates the ST-LINK debugger/programmer without the need for a separate probe, and comes with the comprehensive, free STM32 software libraries and examples available with the STM32Cube MCU package.

Figure 1: STMicroelectronics NUCLEO-C092RC development board. (Source: Mouser Electronics)
The STMicroelectronics X-NUCLEO-IKS4A1 expansion board (Figure 2) is a versatile sensor evaluation kit designed for advanced motion and environmental sensing. It features a main board that hosts MEMS sensors and environmental sensors, as well as a detachable STEVAL-MKE001A add-on board for QVAR swipe gesture detection. With an onboard LSM6DSO16IS and LSM6DSV16X MEMS 3D accelerometers, the expansion board is ideal for developing smart industrial applications. Crucially, its 24-pin DIL (DIL24) socket is compatible with the Sensirion SENSEVAL-SCB4xV1 module, enabling seamless integration of high-precision temperature, humidity, VOC, and pressure sensing.

Figure 2: STMicroelectronics X-NUCLEO-IKS4A1 expansion board. (Source: Mouser Electronics)
The Sensirion SENSEVAL-SCB4XV1 evaluation board (Figure 3) incorporates a Sensirion SHT40 temperature and humidity sensor, an SGP40 VOC sensor, and an STMicroelectronics LPS22DF barometric pressure sensor. The board is also compatible with the STMicroelectronics DIL24 socket.

Figure 3: Sensirion SENSEVAL-SCB4XV1 Evaluation Board. (Source: Mouser Electronics)
Hardware Setup
Both the IKS4A1 expansion board and the Sensirion SENSEVAL SCB4xV1 evaluation board feature a Sensirion SHT40 temperature and humidity sensor and an ST LPS22DF pressure sensor connected to the I²C bus. Since the SHT40 supports only a single fixed I²C address, having two on the same bus causes an address conflict. To resolve this conflict, on the IKS4A1 expansion board, desolder the 0Ω resistor on SB37 and SB39 (SCL and SDA traces), and then desolder the 0Ω resistor on R22 (VDD trace) (Figures 4 and 5).

Figure 4: SHT40 schematic with solder bridges highlighted. (Source: STMicroelectronics)

Figure 5: The IKS4A1 expansion board with solder bridges highlighted. (Source: Mouser Electronics)
The LPS22DF, on the other hand, offers two selectable I²C addresses: When its SA0 pin is connected to VDD, its address is 0x5D (0xBA in code). When the SA0 pin is connected to GND, the address is 0x5C (0xB8 in code). The pressure sensor on the IKS4A1 expansion board is connected to VDD, while the sensor on the Sensirion evaluation board is connected to GND. Because each board’s sensor is connected to a different pin, they have different addresses on the same I²C bus, which resolves the communication problem.
Plug the Sensirion evaluation board into the DIL24 connector on the IKS4A1 expansion board. Then plug the expansion board into the Nucleo board’s Arduino-compatible headers and plug the Nucleo board’s USB Type-C cable into the PC.
Software Setup
Before you can configure the boards, you must download and install STM32CubeMX (Figure 6) and STM32CubeIDE. After installation, download the X-CUBE-MEMS1 expansion software package.
STM32CubeMX
- Open STM32CubeMX.
- Click Access to Board Selector and select the NUCLEO-C092RC board. The configuration window opens.
- Enable the Virtual COM Port option and the GPIO LED (LD2) option. The Virtual COM Port is used to send serial data to the PC through the board’s USB/ST-LINK connection.
- Select pin PB8 and set it to I2C1_SCL, then select pin PB9 and set it to I2C1_SDA. These are the I²C pins in the Arduino Uno-compatible headers.
- Optional: Configure USART1 only when a separate UART connection is needed on the Arduino header pins.
-
- In the Pinout & Configuration tab, select USART1.
- Set the mode to Asynchronous, then assign PB6 as USART1_TX and PB7 as USART1_RX. These pins are separate from the onboard Virtual COM Port and require an external UART connection, such as a 3.3V USB-to-UART adapter or a compatible shield, to communicate with a PC.
- Use the board’s Virtual COM Port for the USB serial output to a PuTTY terminal or a custom graphical user interface (GUI).
- In the Project Manager tab, enter a name for your project in the Project Name field.
- Click the Toolchain/IDE dropdown menu and select STM32CubeIDE.
- Click Generate Code. This action generates the STM32CubeIDE project files based on your .ioc configuration.
- Once the project has been generated, click Open Project.

Figure 6: The final pin assignments for the STM32C092RC MCU in STM32CubeMX. (Source: Mouser Electronics)
STM32CubeIDE
After opening the project in STM32CubeIDE, locate the X-CUBE-MEMS1 folder, and navigate to <your X-CUBE-MEMS1 package folder>/Drivers/BSP/Components/.
The required sensor drivers can also be added via software packs in STM32CubeMX/STM32CubeIDE using X-CUBE-MEMS1. The following method is provided for users who want direct control over which driver files are included in the project.
Locate the following folders (bold indicates sensors on the SENSEVAL-SCB4XV1 board):
- \lis2duxs12
- \lis2mdl
- \lps22df
- \lsm6dso16is
- \lsm6dsv16x
- \sgp40
- \sht40ad1b
- \stts22h
To add these drivers manually:
- Copy the required .h files from each selected driver folder into <your_project>/Core/Inc.
- Copy the required .c files from each selected driver folder into <your_project>/Core/Src.
- Download the Sensirion Gas Index Algorithm files from the link provided in the Project Materials and Resources section.
- Copy sensirion_gas_index_algorithm.h into <your_project>/Core/Inc.
- Copy sensirion_gas_index_algorithm.c into <your_project>/Core/Src.
Note: To enable moderate customization, we will include the individual library for each sensor module. While it is possible to run code from the IKS4A1-provided examples, this method removes the need to explore additional libraries and code to find what you are looking for.
In …\Src\main.c, type:
#include “lis2duxs12.h”
#include “lis2mdl.h”
#include “lps22df.h”
#include “lsm6dso16is.h”
#include “lsm6dsv16x.h”
#include “sgp40.h”
#include “sht40ad1b.h”
#include “stts22h.h”
In the X-CUBE-MEMS1 expansion software package used in this project, each sensor exposes two key structures:
- <sensor name>_IO_t
- <sensor name>_Object_t
In the main.c, before the main() function, define the IO objects:
<sensor name>_IO_t mysensor_io={
.Init = I2C_Init,
.DeInit = I2C_DeInit,
.BusType = 0U,
.Address = #Device Address#,
.Write = I2C_Write, //sometimes WriteReg
.Read = I2C_Read, //sometimes ReadReg
.GetTick = HAL_GetTick,
.Delay = HAL_Delay
};
Each sensor library defines its own struct for I/O operations, but these structs share the same members, such as function pointers for communication routines like I²C read and write. All of these function pointers typically point to the same user-defined functions, since the communication logic is identical across sensors. The only difference between these structs is the device-specific address. These user-defined functions are fine-tuned versions of the original HAL_I2C functions.
As such, define the following:
int32_t I2C_Init(void) {
return (HAL_I2C_Init(&hi2c1) == HAL_OK) ? 0 : -1;
}
int32_t I2C_DeInit(void) {
return (HAL_I2C_DeInit(&hi2c1) == HAL_OK) ? 0 : -1;
}
int32_t I2C_Write(uint16_t DevAddr, uint8_t *pData, uint16_t Length) {
return (HAL_I2C_Master_Transmit(&hi2c1, DevAddr, pData, Length, HAL_MAX_DELAY) == HAL_OK) ? 0 : -1;
}
int32_t I2C_Write_Reg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) {return (HAL_I2C_Mem_Write(&hi2c1, DevAddr, Reg,
I2C_MEMADD_SIZE_8BIT, pData, Length, HAL_MAX_DELAY) == HAL_OK) ? 0 : -1;
}
int32_t I2C_Read(uint16_t DevAddr, uint8_t *pData, uint16_t Length) {
return (HAL_I2C_Master_Receive(&hi2c1, DevAddr, pData, Length, HAL_MAX_DELAY) == HAL_OK) ? 0 : -1;
}
int32_t I2C_Read_Reg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) {
return (HAL_I2C_Mem_Read(&hi2c1, DevAddr, Reg,
I2C_MEMADD_SIZE_8BIT, pData, Length, HAL_MAX_DELAY) == HAL_OK) ? 0 : -1;
}
Then define the sensor object:
<sensor name>_Object_t mysensor_obj;
GasIndexAlgorithmParams params; //for gas-index-algorithm
In the main() function, before the while(1) loop, call each sensor’s initialization functions:
…_RegisterBusIO(&mysensor_obj, &mysensor_io);
…_Init(&mysensor_obj);
…_<functionality>_Enable(&mysensor_obj);
//for gas-index-algorithm
GasIndexAlgorithm_init(¶ms, GasIndexAlgorithm_ALGORITHM_TYPE_VOC);
float value; //for voc index int32_t
Define a float variable in which to save the values. Inside the while(1) loop, call the getter functions:
<functionality>_GetValue(&mysensor_obj, &value);
//for gas-index-algorithm
GasIndexAlgorithm_process(¶ms, sgp40_voc_val, &voc_index_value);
Then use a printf()-function to print the values and read them from PuTTY.
Gas Index Algorithm
Sensirion provides the Gas Index Algorithm specifically for the SGP40 and SGP41 sensors. This algorithm extracts the value from SGP40_GAS_GetValue() and calculates the VOC index. (It can also extract NOx index values from the SGP41 sensor, though the SGP41 is not included in this project.) If no humidity or temperature values are provided to the sensor, it will set them to 50 percent humidity and 25°C by default.
Before the SGP40_GAS_GetValue() function is called, the SHT40AD1B_HUM_GetHumidity() and SHT40AD1B_TEMP_GetTemperature() functions are called. The humidity and temperature values are extracted and fed to the SGP40_GAS_SetHumidity() and SGP40_GAS_SetTemperature() setter functions. After that, you may call the GasIndexAlgorithm_process() function.
Custom GUI
Because the PuTTY terminal is not ideal for displaying sensor values as they update, we created a GUI in Python (available in the GitHub repository). The GUI receives values through the previously defined UART channel and formats them as graphs that users can better understand (Figure 7).
- Connect the Nucleo board to the PC via a USB Type-C cable.
- Open GUI.exe, select the board’s COM port, and enter 115200 as the baud rate.
Note: ST’s MEMS-STUDIO provides a similar experience to this custom GUI, but it is not compatible with the NUCLEO-C092RC board.

Figure 7: The custom GUI can be configured to provide a grid view of all sensor data. (Source: Mouser Electronics)
Example Application: Deployment in AMRs
Using this Sensirion board project, we created a proof of concept for deploying it on an AMR we built for a previous project. We mounted the three-board constellation on the AMR vehicle and integrated it with the existing Robot Operating System 2 (ROS 2) sensor nodes.
In the current setup, the Nucleo MCU reads sensors over I²C and sends a single serial/USB stream to the PC. The IKS4A1 and SENSEVAL-SCB4xV1 boards act as expansion sensor boards that interface to the Nucleo via board connectors (i.e., they do not connect via USB directly).
As a result, the PC could continuously read serial data from the C092RC, IKS4A1, and SCB4XV1 boards via USB and publish it ia a custom interface, allowing any node to subscribe to this topic and act accordingly. For example, this setup enables us to link the 3D model (i.e., the Unified Robot Description Format (URDF) file in ROS2) to orientation data from inertial measurement units (IMUs), providing a better visualization. Using those data, we can determine whether the AMR is ascending or descending and then adjust the power accordingly.
Conclusion
The integration of multi-sensor platforms, such as Sensirion’s SENSEVAL-SCB4xV1, with STM32-based development boards demonstrates how environmental awareness can be seamlessly integrated into industrial automation applications. By combining temperature, humidity, VOC, and pressure sensing with flexible software tools and a custom GUI for visualization, we enable real-time monitoring and adaptive decision-making at the edge. This approach not only enhances operational safety and efficiency but also opens the door for advanced applications such as predictive maintenance and intelligent AMR navigation. Ultimately, these technologies pave the way for smarter, connected systems that respond dynamically to changing conditions in industrial environments.