This tutorial shows how to build a indoor air quality sensor with the WisBlock eco system.
With the release of the new RAK12037 CO2 and RAK12039 Particle Matter sensor the most important air quality indizes can now be measured.
The final device in this tutorial is measuring CO2, Particle Matter, VOC, temperature, humidity and barometric pressure. It can be comined with the RAK14000 to display the different values. But more important, it sends the measured values over LoRaWAN for further processing and taking actions.
This firmware is using the WisBlock API V2
For the displays, the RAK14000 EPD module with the 2.13" display can be used. But for better visualization this code supports as well a 3.52" and a 4.2" display. The 4.2" display might be added as a variant to the WisBlock RAK14000 in the future.
- Hardware supported
- Software used
- How to use it
- Packet data format
- Compiler Flags
- Example for a visualization and alert message
Module | Function |
---|---|
RAK4631 |
WisBlock Core module |
RAK19001 |
WisBlock Fullsize Base board |
RAK1901 |
WisBlock Temperature and Humidty Sensor |
RAK1902 |
WisBlock Barometer Pressure Sensor |
RAK1906 |
WisBlock Environment Sensor |
RAK12002 |
WisBlock RTC module |
RAK12010 |
WisBlock Ambient Light sensor |
RAK12019 |
WisBlock UV Light sensor |
RAK12037 |
WisBlock CO2 sensor |
RAK12039 |
WisBlock Particle Matter sensor |
RAK12047 |
WisBlock VOC sensor |
RAK14000 |
WisBlock EPD |
- PlatformIO
⤴️ - alternative ArduinoIDE
⤴️ - Adafruit nRF52 BSP
⤴️ - Patch to use RAK4631 with PlatformIO
⤴️
- Adafruit BME680 Library
⤴️ - Adafruit LPS2X
⤴️ - Adafruit Unified Sensor
⤴️ - ClosedCube OPT3001
⤴️ - Melopero RV3028
⤴️ - nRF52_OLED
⤴️ - RAK12019_LTR390_UV_Light
⤴️ - RAKwireless VEML Light Sensor
⤴️ - Sensirion Core
⤴️ - Sensirion Gas Index Algorithm
⤴️ - Sensirion I2C SGP40
⤴️ - SparkFun SHTC3 Humidity and Temperature Sensor Library
⤴️ - LPS35HW
⤴️ - RAK12039 PM Sensor
⤴️ - SparkFun SCD30 Arduino Library
⤴️ - Adafruit EPD
- Bosch BSEC V1.6.1480
The project was developed using Platform IO.
When using PlatformIO, the libraries are all listed in the platformio.ini
and are automatically installed when the project is compiled.
Compile the firmware and flash it on a WisBlock with all required modules installed.
Connect over USB to setup the LPWAN credentials. Use the DevEUI printed on the RAK4631, use the AppEUI and AppKey from your LPWAN server. Do NOT activate automatic join yet. As weather sensor levels are not changing very fast, it might be sufficient to set the send frequency to every 10 minutes. The send frequency is set in seconds, so the value would be 10 * 60 ==> 600
The AT commands are compatible with RAKwireless RUI3 AT commands. Not all AT commands are supported due to the differences in the LoRaWAN stack.
See AT Command Manual
Alternative the RAKwireless WisToolBox
WisToolBox makes it easy to setup all required parameters through a simple user interface. (Work in progress, not all functions available)
Example AT commands:
AT+NWM=1
AT+NJM=1
AT+BAND=10
AT+DEVEUI=1000000000000001
AT+APPEUI=AB00AB00AB00AB00
AT+APPKEY=AB00AB00AB00AB00AB00AB00AB00AB00
AT+SENDFREQ=600
Command | Explanation |
---|---|
AT+NWM=1 | set the node into LoRaWAN mode |
AT+NJM=1 | set network join method to OTAA |
AT+BAND=10 | set LPWAN region (here AS923-3) see AT Command Manual |
AT+DEVEUI=1000000000000001 | set the device EUI, best to use the DevEUI that is printed on the label of your WisBlock Core module |
AT+APPEUI=AB00AB00AB00AB00 | set the application EUI, required on the LoRaWAN server |
AT+APPKEY=AB00AB00AB00AB00AB00AB00AB00AB00 | set the application Key, used to encrypt the data packet during network join |
AT+SENDFREQ=600 | set the frequency the sensor node will send data packets. 600 == 10 x 60 seconds == 10minutes |
The manual for all AT commands can be found here: AT Command Manual
Use the WisBlock Toolbox
Alternative the RAKwireless WisToolBox
WisToolBox makes it easy to setup all required parameters through a simple user interface. (Work in progress, not all functions available)
The packet data is made compatible with the extended Cayenne LPP encoding from ElectronicCats/CayenneLPP
The content of the packet depends on the modules installed on the WisBlock Base Board:
Data | Channel # | Channel ID | Length | Comment | Required Module | Decoded Field Name |
---|---|---|---|---|---|---|
Battery value | 1 | 116 | 2 bytes | 0.01 V Unsigned MSB | RAK4631 | voltage_1 |
Humidity | 2 | 104 | 1 bytes | in %RH | RAK1901 | humidity_2 |
Temperature | 3 | 103 | 2 bytes | in °C | RAK1901 | temperature_3 |
Barometric Pressure | 4 | 115 | 2 bytes | in hPa (mBar) | RAK1902 | barometer_4 |
Illuminance | 5 | 101 | 2 bytes | 1 lux unsigned | RAK1903 | illuminance_5 |
Humidity 2 | 6 | 104 | 1 bytes | in %RH | RAK1906 | humidity_6 |
Temperature 2 | 7 | 103 | 2 bytes | in °C | RAK1906 | temperature_7 |
Barometric Pressure 2 | 8 | 115 | 2 bytes | in hPa (mBar) | RAK1906 | barometer_8 |
Gas Resistance 2 | 9 | 2 | 2 bytes | 0.01 signed (kOhm) | RAK1906 | analog_9 |
GNSS stand. resolution | 10 | 136 | 9 bytes | 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01 meter | RAK1910, RAK12500 | gps_10 |
GNSS enhanced resolution | 10 | 137 | 11 bytes | 4 byte lon/lat 0.000001 °, 3 bytes alt 0.01 meter | RAK1910, RAK12500 | gps_10 |
Soil Temperature | 11 | 103 | 2 bytes | in °C | RAK12023/RAK12035 | temperature_11 |
Soil Humidity | 12 | 104 | 1 bytes | in %RH | RAK12023/RAK12035 | humidity_12 |
Soil Humidity Raw | 13 | 2 | 2 bytes | 0.01 signed | RAK12023/RAK12035 | analog_in_13 |
Soil Data Valid | 14 | 102 | 1 bytes | bool | RAK12023/RAK12035 | presence_14 |
Illuminance 2 | 15 | 101 | 2 bytes | 1 lux unsigned | RAK12010 | illuminance_15 |
VOC | 16 | 138 | 2 bytes | VOC index | RAK12047 | voc_16 |
MQ2 Gas | 17 | 2 | 2 bytes | 0.01 signed | RAK12004 | analog_in_17 |
MQ2 Gas Percentage | 18 | 120 | 1 bytes | 1-100% unsigned | RAK12004 | percentage_18 |
MG812 Gas | 19 | 2 | 2 bytes | 0.01 signed | RAK12008 | analog_in_19 |
MG812 Gas Percentage | 20 | 120 | 1 bytes | 1-100% unsigned | RAK12008 | percentage_20 |
MQ3 Alcohol Gas | 21 | 2 | 2 bytes | 0.01 signed | RAK12009 | analog_in_21 |
MQ3 Alcohol Gas Perc. | 22 | 120 | 1 bytes | 1-100% unsigned | RAK12009 | percentage_22 |
ToF distance | 23 | 2 | 2 bytes | 0.01 signed | RAK12014 | analog_in_23 |
ToF Data Valid | 24 | 102 | 1 bytes | bool | RAK12014 | presence_24 |
Gyro triggered | 25 | 134 | 6 bytes | 2 bytes per axis, 0.01 °/s | RAK12025 | gyrometer_25 |
Gesture detected | 26 | 0 | 1 byte | 1 byte with id of gesture | RAK14008 | digital_in_26 |
LTR390 UVI value | 27 | 2 | 2 byte | 0.01 signed | RAK12019 | analog_in_27 |
LTR390 UVS value | 28 | 101 | 2 bytes | 1 lux unsigned | RAK12019 | illuminance_28 |
INA219 Current | 29 | 2 | 2 byte | 0.01 signed | RAK16000 | analog_29 |
INA219 Voltage | 30 | 2 | 2 byte | 0.01 signed | RAK16000 | analog_30 |
INA219 Power | 31 | 2 | 2 byte | 0.01 signed | RAK16000 | analog_31 |
Touchpad left | 32 | 102 | 1 bytes | bool | RAK14002 | presence_32 |
Touchpad middle | 33 | 102 | 1 bytes | bool | RAK14002 | presence_33 |
Touchpad right | 34 | 102 | 1 bytes | bool | RAK14002 | presence_34 |
SCD30 CO2 concentration | 35 | 125 | 2 bytes | 1 ppm unsigned | RAK12037 | concentration_35 |
SCD30 temperature | 36 | 103 | 2 bytes | in °C | RAK12037 | temperature_36 |
SCD30 humidity | 37 | 104 | 1 bytes | in %RH | RAK12037 | humidity_37 |
MLX90632 sensor temp | 38 | 103 | 2 bytes | in °C | RAK12003 | temperature_38 |
MLX90632 object temp | 39 | 103 | 2 bytes | in °C | RAK12003 | temperature_39 |
PM 1.0 value | 40 | 138 | 2 bytes | in ug/m3 | RAK12003 | voc_40 |
PM 2.5 value | 40 | 138 | 2 bytes | in ug/m3 | RAK12003 | voc_41 |
PM 10 value | 40 | 138 | 2 bytes | in ug/m3 | RAK12003 | voc_42 |
Channel ID's in cursive are extended format and not supported by standard Cayenne LPP data decoders.
Example decoder [RAKwireless_Standardized_Payload.js] for TTN, Chirpstack, Helium and Datacake can be found in the folder RAKwireless_Standardized_Payload repo.
If using LoRa P2P, the first 8 bytes of the data packet are the devices Dev EUI. This way in LoRa P2P the "gateway" can determine which node sent the packet.
If the Bosch BSEC library is used, Gas Resistance 2 value is the IAQ index calculated by BSEC algorithm.
The application uses several #define for different application options like the usage of an EPD display or for different Base Boards.
All defines are in platformio.ini as build flags
-DSW_VERSION_1=1 ; major version increase on API change / not backwards compatible
-DSW_VERSION_2=0 ; minor version increase on API change / backward compatible
-DSW_VERSION_3=0 ; patch version increase on bugfix, no affect on API
-DLIB_DEBUG=0 ; 0 Disable LoRaWAN debug output
-DAPI_DEBUG=0 ; 0 Disable WisBlock API debug output
-DCFG_DEBUG=1 ; 0 Disable BSP debug output
-DMY_DEBUG=0 ; 0 Disable application debug output
-DBASE_BOARD=0 ; 1 = RAK19003 0 = other base boards
-DNO_BLE_LED=1
-DHAS_EPD=0 ; 1 = RAK14000 4.2" present 2 = 2.13" BW present, 3 = 2.13" BWR present, 4 - 3.52" BW present, 0 = no RAK14000 present
-DEPD_ROTATION=3 ; 3 = top at cable connection, 1 top opposite of cable connection. Only for 4.2" display
-D USE_BSEC=1 ; 1 = Use Bosch BSEC algo, 0 = use simple T/H/P readings
-L".pio/libdeps/rak4631-release/BSEC Software Library/src/cortex-m4/fpv4-sp-d16-hard"
As an simple example to visualize the IAQ data and sending an alert, I created a device in Datacake.
Datacake is an easy to use Low Code IoT Platform. In my Datacake account I setup the device with the matching payload decoder, visualization and creation of an email alert.
In the device configuration the Datacake decoder from the decoders folder is used.
As the SI and PGA values are sent as 10 times of the value, beside of the data fields a formula feed is required to transform the received values to the real values.
Field Name | Identifier | Type |
---|---|---|
VOC index | VOC_16 | Integer |
CO2 value | CONCENTRATION_35 | Integer |
PM 1.0 | VOC_40 | Integer |
PM 2.5 | VOC_41 | Integer |
PM 10 | VOC_42 | Integer |
Humidity | HUMIDITY_2 | Float |
Temperature | TEMPERATURE_3 | Float |
Barometric pressure | BAROMETER_8 | Float |
Battery | VOLTAGE_1 | Float |
In the dashboard you can show the current status and the latest SI and PGA levels.