This article presents how to use NXP’s Model-Based Design Toolbox (MBDT) to implement an Air Quality Monitor that integrates multiple sensors, which will be configured to run on the 3S32K144 EVB.
The Model-Based Design Toolbox offers a solution for deploying complex applications on NXP hardware directly from Simulink. It incorporates hardware-optimized software, including drivers, libraries, and tools, allowing users to concentrate solely on algorithm development. The toolbox manages the hardware integration, ensuring the applications are hardware-aware. By integrating with the MathWorks ecosystem, the Model-Based Design Toolbox leverages the model-based design paradigm. This enables a programming process based on models, where users create logical diagrams using Simulink blocks for dedicated functions, eliminating the need to write C code for their designs.
This article aims to show how this tool can be used for designing and deploying on an S32K144 Evaluation board an air quality monitor application. Therefore, the steps meant to accomplish this are parted in the following sections:
II. General purpose – what is the aim of the application;
III. Application overview – how the application works and how the sensors are integrated;
IV. Hardware design – the description of the components used;
V. Software design – the execution flow of the application and the model implementation explained in detail;
VI. Conclusion – results of the application.
This application shows how easily an Air Quality Monitor can be implemented when using the MBD toolbox for S32K1xx, which helps the users simplify their job by providing the means to use a graphic and visual way to put their idea into use and generate the C code from it, which will be uploaded on the EVB.
The application displays in FreeMASTER the values of temperature, humidity, dust density, pressure, and the values of eCO2 and TVOC. Those values are read from the sensors connected to the EVB and computed using the algorithms from the libraries corresponding to each sensor, such as Adafruit’s libraries for BMP280 and CCS811, Sparkfun library for HTU21D and the GP2Y1010AU0F library, which are then adapted in Simulink logic. The application will be split into four subsystems, each covering a sensor and its algorithm.
Figure 1: Block Diagram
4.1. Hardware components
The required components for this application are:
1) S32K144 Evaluation Board
The S32K144EVB is a low-cost evaluation and development board for general-purpose industrial and automotive applications. The board represents the main part of the application as it collects the data from the sensors and applies the algorithm to compute the values shown in FreeMASTER.
For more information about the board, access the following NXP page.
2) Temperature and humidity sensor HTU21D
The HTU21D is an easy-to-use, digital sensor for measuring humidity and temperature levels. It utilizes the I2C communication protocol, making it suitable for various applications, such as an Air Quality Monitor.
3) eCO2 and TVOC sensor CCS811
The CCS811 sensor precisely monitors indoor air quality, measuring TVOCs and carbon dioxide levels in real time. Using the I2C communication protocol, it is easily integrated into air quality monitor applications.
4) Pressure sensor BMP280
The BMP280 sensor accurately measures atmospheric pressure using the I2C communication protocol.
5) Dust density sensor GP2Y1010AU0F
The GP2Y1010AU0F sensor is utilized for the measurement of dust density with high precision. Utilizing an analog output mechanism, it delivers reliable data for comprehensive air quality assessments.
Apart from the components described above (HTU21D sensor, CCS811 sensor, BMP280 sensor and GP2Y1010AU0F sensor), a resistor and a capacitor will be needed.
The following electrical schematic is an example of how the sensors can be connected:
Figure 2: Electrical schematic
To be able to follow the next steps presented in this article, the following software will be necessary:
The application uses the Simulink environment to implement the algorithms for computing the data read from the sensors connected to the S32K144 EVB. The model is organized into two big sections: initialization and sensors’ algorithms. For the sensors part, each sensor has its subsystem where the algorithm is implemented.
Figure 3: Application’s model
The initialization holds the blocks required for our model to work. On the first line, from left to right, the following can be found:
1) The Configuration block for S32K1xx processor family. The required settings of the processor configuration block are the default ones, except for the processor family and the download interface.
Figure 4: Configuration block for S32K1xx family of processors
2) The LP2IC Configuration block. Here the functioning mode (master or slave) can be changed, and the pins used for communication can be chosen. This application has three sensors that use this communication protocol:
Figure 5: Configuration block for LPI2C
3) The FreeMASTER configuration block. Here the communication interface, the baud rate, and long interrupt serial communication can be set. This component facilitates communication between the S32K144 EVB LPUART1 instance and the FreeMaster tool, via the microUSB serial port.
Figure 6: Configuration block for FreeMASTER
4) The configuration block for ADC. The ADC converter number and the resolution mode can be selected from here.
Figure 7: Configuration block for ADC
On the second line, the data stores for the variables used in this project can be found. The data type and size for the data stores can be found in the following table:
VARIABLE NAMES |
DATA TYPE |
SIZE / DIMENSION |
SENSOR |
aux_temp |
uint8 |
3 |
BMP280 |
aux_press |
uint8 |
3 |
BMP280 |
BMP280_Temp |
uint8 |
6 |
BMP280 |
BMP280_Press |
uint8 |
18 |
BMP280 |
BMP280_T |
uint16 |
1 |
BMP280 |
BMP280_T2 |
int16 |
2 |
BMP280 |
BMP280_P |
uint16 |
1 |
BMP280 |
BMP280_P2 |
int16 |
8 |
BMP280 |
raw_press |
int32 |
1 |
BMP280 |
raw_temp |
int32 |
1 |
BMP280 |
Pressure |
double |
1 |
BMP280 |
buf |
uint8 |
8 |
CCS811 |
TVOC |
uint16 |
1 |
CCS811 |
eCO2 |
uint16 |
1 |
CCS811 |
temperature |
double |
1 |
HTU21D |
humidity |
double |
1 |
HTU21D |
hum_raw |
uint16 |
1 |
HTU21D |
temp_raw |
uint16 |
1 |
HTU21D |
humcomp |
default |
default |
HTU21D |
dustDensity |
default |
default |
GP2Y1010AU0F |
Figure 8: Variables
Note! It is important, for the variables to be visible in FreeMASTER, to go to Apps -> Embedded Coder -> Code Interface -> Default Code Mappings -> Data Stores and set all the variables to Volatile.
Figure 9: Embedded Coder selection
Figure 10: Default Code Mappings
The second part of the model consists of every sensor’s subsystem. In each subsystem, the necessary algorithm for computing the data is implemented.
Let’s look at every subsystem and algorithm.
For this sensor’s initialization, BMP280_Temp and BMP280_Press will be used. Top down, five subsystems can be found: Global Initialization Sensor, Temp Calib, read16LE – temp, Press Calib, read16LE – press.
Figure 11: BMP280 subsystems
The purpose of the Global Initialization Sensor is to prepare the sensor for subsequent data reading. This involves transmitting specific data to the sensor using the LPI2C Master Transmit block. These data include values such as 0xF5 and 108, as well as 0xF4 and 111, which serve to configure and calibrate the sensor for upcoming tasks. Having multiple sensors connected using I2C communication protocol, the way the sensor can differentiate between them is by their address. Therefore, the data will be sent to the 0x76 address, which corresponds to the address of the pressure sensor.
Figure 12: Pressure sensor initialization
In Temp Calib subsystem, data is read from the temperature's memory location and placed into the BMP280_Temp data store mentioned earlier. The addresses from which data needs to be read are sequential, so reading begins from the 0x88 address and 6 bits of data are requested, resulting in reading from address 0x88 to address 0x8C inclusively.
Figure 13: I2C Master Multi Transfer
In read16LE – temp subsystem, the add operation is utilized to perform an OR bit operation for calibrating the data and placing it into the BMP280_T data store and the BMP280_T2. LE stands for Little Endian.
Figure 14: Temperature data calibration
For the Press Calib and read16LE – press subsystems, the same operations described previously are performed, but for a greater number of bits. After the initialization is completed, the Else subsystem is entered, where the computing takes place. An auxiliary temperature is computed, which is required for the pressure's formula. For this purpose, the data store named aux_temp will be used. Within this subsystem, there are 2 further subsystems: READ TEMP REGISTER and RAW TEMP.
In READ TEMP REGISTER, data is read from the 0xFA address using an LPI2C Master Multi Transfer, and 3 bits of data are transferred into the aforementioned aux_temp data store.
In RAW TEMP, the raw_temp necessary for the pressure calculation formula is computed.
Similar to the temperature calculation, the pressure calculation data is read from the 0xF7 address into the data store named aux_press, and then the raw_press required for the formula is computed.
For the actual computation of the pressure, an S-Function block with C code inside is utilized, where the algorithm found in the Adafruit Library for BMP280 is included. [1] [functions float Adafruit_BMP280::readTemperature() and float Adafruit_BMP280::readPressure()].
Figure 15: convertPressure S-Function
For this sensor, during initialization, the same procedure as before is followed: specific data is sent to the sensor using the LPI2C Master Transmit to notify it of the upcoming data reading. Specifically, the predefined data 0xF4 and 0x01, 16 is now transmitted.
Figure 16: Initialization for eCO2 and TVOC sensor
In the Else subsystem, 8 bits of data are read and placed into the buf variable using the LPI2C Master Multi Transfer block. Subsequently, after the necessary data is retrieved from the sensor, the required values are computed, with their formulas sourced from the Adafruit Library for the CCS811 sensor [2]:
_eCO2 = ((uint16_t)buf[0] <<
_TVOC = ((uint16_t)buf[2] <<
Figure 17: Compute data for eCO2 and TVOC values
For this sensor, another library [3] will be utilized to obtain the necessary formulas and the algorithm. Initially, for both temperature and humidity readings, the LPI2C Master Multi Transfer block will be employed to retrieve the required values. Specifically, the command to trigger temperature readings is 227, and for humidity, it is 229. Each reading will consist of 3 bits, from which only the most significant bit and the least significant bit will be utilized for temperature and humidity, respectively.
For both of them, the raw values need to be computed. The formulas needed are:
uint16_t rawValue = ((uint16_t) msb <<
temp_raw = rawValue & 0xFFFC;
2. For humidity:
uint16_t rawValue = ((uint16_t) msb <<
hum_raw = rawValue & 0xFFFC;
The temperature is computed using the following formula:
Temperature = temp_raw * (175.72 / 65536.0) – 46.85;
Figure 18: Temperature computing
The humidity is computed using the following formula:
Humidity = (-6) + 125 * (hum_raw / 65536.0) + (25 – Temperature) * (-0.15);
Figure 19: Humidity computing
Figure 20: Temperature and humidity subsystem
For this final sensor, an additional library [4] will be employed to implement our model-based design algorithm for measuring and computing the PM2.5 levels in our surroundings.
In this scenario, the GPIO Write block will be utilized to activate and deactivate the infrared LED on the sensor. Following activation, a 0.28ms delay will be introduced before employing the ADC to read the data, which will then be computed using the provided formula:
dustDensity = (170 * 5 / 1024 – 0.1) * Voltage
Figure 21: Formula applied for dust density
After applying the above-mentioned formula, another delay of 0.04ms will be used and then the LED will be turned off.
Figure 22: Dust Pm2.5 subsystem
To visualize the results from the application, a FreeMASTER project can be created. Once created, the .elf file of the built application can be added by navigating to Project -> Resource files -> "pack" directory setup -> MAP Files -> Default symbol file.
Variables can be added to the Variable Watch section. For this project, the most important ones are Pressure, eCO2, TVOC, humidity, temperature, and dustDensity.
Figure 23: Variable watch section
A possible example for hardware setup is represented in the below picture:
Figure 24: Hardware setup
The application covers the steps of developing an air quality monitor that monitors how the pressure, TVOC, eCO2, humidity, temperature, and dust density evolve in a room, using the Model-Based Design Toolbox for S32K1 MCUs. It can be a good academic study for how to use the S32K1XX EVB and sensors using the MBDT and for how to adapt C code and use it in a graphic programming environment such as Simulink to simplify your work.
Bibliography:
[1] https://github.com/adafruit/Adafruit_BMP280_Library
[2] https://github.com/adafruit/Adafruit_CCS811
[3] https://github.com/sparkfun/SparkFun_HTU21D_Breakout_Arduino_Library
[4] https://github.com/mickey9801/GP2Y1010AU0F
NXP is a trademark of NXP B.V. All other product or service names are the property of their respective owners. © 2024 NXP B.V. MATLAB, Simulink, and Embedded Coder are registered trademarks of The MathWorks, Inc. See mathworks.com/trademarks for a list of additional trademarks.