This project aims to present a device to control air quality in schools, improving health and quality of life for students.
Problem description
Purpose
Prototype
For prototyping the device the Azure Sphere AVNET Starter Kit and Mikroe Air Quality 4 click sensor will be used. The Azure Sphere platform consists of a microcontroller, a secure operating system, and a suite of cloud services that ensure device security and constant operation. The Mikroe Air Quality 4 click sensor is a device for prototyping air quality meters that checks two main parameters: CO2 concentration and TVOC concentration. TVOC stands for Total Volatile Organic Compounds, which is a measure of the concentration of organic compounds in air. The higher the concentration of these two parameters, the worse the quality of breathing air is considered.
Building the device
OK now we know what the sensor do and what protocol we will use to comunicate with it. But how we can do that? To start we will use the project provide by Avnet in your GitHub: https://github.com/CloudConnectKits/Azure_Sphere_SK_ADC_RTApp This repository has two projects we will use the AvnetAzureSphereSK_OLED, because this project has the code necessary to use I2C protocol and send data to Azure IoT Central. If you prefer I will publish in another repository my version of this same project with the changes ready. Clone this project and open with Visual Studio 2017 or 2019. If you look at the main.c file, you will find the call for a function named initI2C().
This function initI2C do two important fings, first they inicialize the Azure Sphere as a I2C MASTER device and write the pointer for the I2C library on the variable i2cFd, remeber this name.
At the end of the initI2C function code, it still schedules the execution of the function AccelTimerEventHandler. This second function will be responsible for collect data from sensors and send to Azure IoT Hub or Azure IoT Central. We will code our final code in this function.
Ok now we have to look at the SGP30 datasheet to understand how to communicate. On this section we will find that the sensor will respond on the I2C address 0x58 in hexadecimal.
Most I2C sensors have some type of communication test command. The SGP30 has a measure test, if we send the command 0x2032 we will get a reply default value 0xD400.
To test that we will use this simple code, into the initi2c() after I2C Master inicialization.
uint8_t buff[2];
buff[0] = 0x20;
buff[1] = 0x32;
int32_t retVal;
uint8_t sgp30_buffer[2];
Log_Debug("SEND [%d] 0x%02x [%d] 0x%02x\n", 0, buff[0], 1, buff[1]);
retVal = I2CMaster_Write(i2cFd, 0x58, buff, 16);
sleep(1);
retVal = I2CMaster_Read(i2cFd, 0x58, sgp30_buffer, 2);
Log_Debug("RET [%d] 0x%02x [%d] 0x%02x\n", 0, sgp30_buffer[0], 1, sgp30_buffer[1]);
if (retVal < 0) {
Log_Debug("ERROR: platform_read(read step): errno=%d (%s)\n", errno, strerror(errno));
}
The variable buff is the buffer that contains the command in hexadecimal that we want o send. The I2CMaster_Write send the command in buff variable, using the i2cFd pointer for the MASTER I2C device, and the address 0x58 that represents the sensor. The last parameter is the number of the bytes that has in the buffer variabel (16 bytes).
We wait a long time 1 second, but you can a smaller value. Than we use the I2CMaster_Read to read the response and writes on sgp30_buffer. If we lookat the output console, we will see that the sensor respond with the correct value.
Now we go back to the datasheet and find this instructions to get de sensor data. First we need to send the command Initi_air_quality 0x2003 then we can send the command Measure_air_quality 0x2008. For 15 seconds the response will be 400 for CO2 and zero for TVOC. IMPORTANT: put in comment ou remove the code that we did in the last step.
On the begin of initi2c() function we will put this code, to send the Init_air_quality command.
uint8_t buff[2];
int32_t retVal;
buff[0] = 0x20;
buff[1] = 0x03;
Log_Debug("INIT [%d] 0x%02x [%d] 0x%02x \n", 0, buff[0], 1, buff[1]);
retVal = I2CMaster_Write(i2cFd, 0x58, buff, 16);
On the begin of AccelTimerEventHandler() function we will put this code, they first send the Measure_air_quality command 0x2008 then wait for 1 second. After that, we use the I2CMaster_Read() function to get the values in the sgp30_buffer. The data return will be structured like this:
8bits_CO2 | 8bits_CO2 | 8bits_CRC_CO2 | 8bits_TVOC | 8bits_TVOC | 8bits_CRC_TVOC
In the end we use the command to convert hexadecimal values to decimal.
uint8_t buff[2];
int32_t retVal;
uint8_t sgp30_buffer[6];
buff[0] = 0x20;
buff[1] = 0x08;
Log_Debug("READ [%d] 0x%02x [%d] 0x%02x \n", 0, buff[0], 1, buff[1]);
retVal = I2CMaster_Write(i2cFd, 0x58, buff, 16);
sleep(1);
retVal = I2CMaster_Read(i2cFd, 0x58, sgp30_buffer, 6);
Log_Debug("RET [%d] 0x%02x ", 0, sgp30_buffer[0]);
Log_Debug("[%d] 0x%02x ", 1, sgp30_buffer[1]);
Log_Debug("[%d] 0x%02x \n", 2, sgp30_buffer[2]);
Log_Debug("RET [%d] 0x%02x ", 3, sgp30_buffer[3]);
Log_Debug("[%d] 0x%02x ", 4, sgp30_buffer[4]);
Log_Debug("[%d] 0x%02x \n", 5, sgp30_buffer[5]);
int co2 = (sgp30_buffer[0]<<8) | sgp30_buffer[1];
int tvoc = (sgp30_buffer[3] << 8) | sgp30_buffer[4];
Log_Debug("[ CO2 %d ] [ TVOC %d ]", co2, tvoc);
if (retVal < 0) {
Log_Debug("ERROR: platform_read(read step): errno=%d (%s)\n", errno, strerror(errno));
}
You will see that the sensor reacts as expected, returning constant values first and then changing after 15 seconds.
Send this data to Azure IoT Central
To send this data to Azure IoT Central, we need to alter the sensor_var struct to include out two new parameters.
And then write this to the sensor_data structure.
Than we need to alter de i2c.c file to change the JSON message generation, to add your new parameters. Search for this snprintf on the code.
To connect using a simple way with Azure IoT Central we will use part of this tutorial from Microsoft, to use de Device Provision Service to generate the connection string: https://docs.microsoft.com/pt-br/azure/iot-central/howto-connect-windowsiotcore
You have to enter on Azure Portal, and create a new or access a existing instance of Azure IoT Central.
First we click on device models and create a new model.
Than we enter in create a new telemetry parameter, and use the names: co2 and tvoc
Once the two parameters co2 and tvoc are add to your model, we can continue and create a new device.
Enter on devices and create a new device use the new model type we create in the last step. Select the type REAL device when you are creating the new one.
On the device list, select your new device and click on connect link on the top right corner, this screen will show, copy the Azure IoT Central Scope code, the device id and the SAS primary key.
Now you need the NodeJS installed in your computer to use npm package manager to install de dps-keygen. This module will generate connection string we need in your device code.
npm i -g dps-keygen
Use this command fillin the gaps with the informations from Azure IoT Central device connection screen.
dps-keygen -di:<Device ID> -dk:<Primary or Secondary Key> -si:<Scope ID>
Copy the connection string show on the console and paste into the MY_CONNECTION_STRING into the connection_string.h file.
At last, change the app_manifest.json copy the Azure IoT Hub URL from the connection string to the AllowedConnections parameter.
If you run your code on Azure Sphere and go to Azure IoT Central you will see the data from the Air Quality Sensor display into the graph.
Improvements
Using the Azure IoT Central platform, we can create a dashboard that shows the air quality situation of all classrooms, and generates alerts for school managers to intervene and instruct teachers to have practices that allow the classroom environment of class has higher quality.
Source Code
The source code of this project could be found in: https://github.com/waltercoan/AzureSphereAVNET_AirQuality