This sketch is the production firmware for the MCCI® Model 4841 Air Quality Sensor.
Contents:
- Introduction
- Installing and Building
- Firmware Update via Serial
- Overview
- Activities
- Primary Data Acquisition
- Uplink Data
- Data Formats
- Commands
- Required libraries
- Meta
The Model 4841 combines an MCCI Catena® 4630 LPWAN radio sensor board with a Plantower PMS7003 air quality sensor. The 4630 has an STM32L0 processor, a LoRa radio based on the Semtech SX1276, a Sensirion SHT3x temperature/humidity sensor, and a Sensirion SGPC3 gas sensor on board. This firmware runs on the STM32L0 processor in the 4630.
The best way to install and build this software is to start with COLLECTION-model4841, a top-level collection that includes this repository as a submodule, along with the required libraries and a build procedure that uses the arduino-cli
. It is, of course, also possible to install the libraries individually and build with a variety of build procedures. See "Required libraries" for details.
This is a feature to load the firmware via serial without getting the board into DFU mode. Version 1.4.0 and later version of the sketch supports this feature.
-
As the feature is available from version 1.4.0 and later of the sketch, the existing firmware on board should be the version v1.4.0 or later version firmware.
-
Clone the repository in a desired location.
-
Place the bin file of the sketch inside "extra" folder of the repository.
-
Open the cmd prompt and navigate to "extra" folder where the bin file was placed.
-
Run the following example command:
python catena-download.py -v -c "system update" model4841-production-lorawan.ino.bin COM10
-
This will load the new firmware in Catena board with a "Success!" message.
D:\IoT-Projects\Model4841\sketches\model4841-production-lorawan\extra>python catena-download.py -v -c "system update" model4841-production-lorawan.ino.bin COM10 Read file: size 104108 Using port COM10 system update Update firmware: echo off, timeout 2 seconds <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<OK<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Success!
-
Once the firmware is loaded, RESET Model 4841, this will start to run the newly loaded sketch in Model 4841.
Note
- COM port (COM10 used in example command) might vary for different devices. Use the COM port which is enumerated for the Catena board in use.
- To find the COM port, open the "device manager" from start menu and find the COM port which is enumerated for the Catena board in use.
- Make sure the COM port is not connected to any Serial monitors.
The primary function of the Catena 4630 is to capture and transmit real-time air quality and dust particle data to remote data consumers, using LoRaAWAN. For consistency with MCCI's other monitoring products, information is captured and transmitted at six minute intervals.
This firmware has the following features.
-
During startup, the sketch initializes the PMS7003.
-
If the device is provisioned as a LoRaWAN device, it enters the measurement loop.
-
Every measurement cycle, the sketch powers up the PMS7003. It then takes a sequence of 10 measurements. Data is gathered from the atmospheric PM serias and the dust series. For each series, outliers are discarded using an IQR1.5 filter, and then the remaining data is averaged.
-
Temperature and humidity are measured by the SHT3x.
-
Air quality value (Total Volatile Organic Compounds, or "TVOC") read from the SGPC3 sensor.
-
Data is encoded into binary and transmitted to the LoRaWAN network, using LoRaWAN port 1, as a class A device.
-
The sketch uses mcci-catena/SGPC3 library to measure TVOC value and transmit over network. This library is based on the gb88/SGPC3 library, with light modifications for LoRaWAN compatibility.
-
The sketch uses the Catena Arduino Platform, and therefore the basic provisioning commands from the platform are always available while the sketch is running. This also allows user commands to be added if desired.
-
The
McciCatena::cPollableObject
paradigm is used to simplify the coordination of the activities described above.
- Setup: an activity that launches the other activities.
- Primary Data Acquisition: the activity that configures the PMS7003, and then takes data. It wakes up periodically, poll registers, computes and send an uplink on LoRaWAN port 5.
- LoRaWAN control: this activity manages transmission and reception of data over LoRaWAN.
- Local serial command processor
- [Future] A firmware update activity
- [Future] An activity to handle copying firmware
The primary loop wakes up based on elapsed time, makes a series of measurements, scales them, and transmits them.
It senses temp sensor data, TVOC data, particulat matter data, dust particle concentrations, battery level, and boot count. By default, the cycle time is every six minutes, but this can be adjusted using the cycle-time downlink.
Port 1 is used for normal uplink demand data. It is the usual bitmap/data formant.
It has the usual scheme:
byte 0: id (0x21)
byte 1: flag byte
bytes 2..n: variable data, governed by flag byte.
The flags:
bit 0: Vbat
is present.
We transmit:
bytes | format | units | contents |
---|---|---|---|
0 | uint8 |
number | 0x21 , identifying the data format. |
1 | uint8 |
flag byte | bitmask describing data fields that follow. |
2..n | - | - | data bytes; use bitmap to decode. |
The bitmap byte has the following interpretation.
Bit | Field length (bytes) | Data format | Description |
---|---|---|---|
0 | 2 | int16 |
Battery voltage |
1 | 2 | int16 |
System voltage |
2 | 2 | int16 |
Bus voltage |
3 | 1 | uint8 |
Boot counter |
4 | 4 | int16 , uint16 |
uint16 |
5 | 2 | 3 x uint16 |
Particulate matter |
6 | 2 | 6 x uint16 |
Dust |
7 | 1 | uint16 |
TVOC |
Field 0, if present, carries the current battery voltage. To get the voltage, extract the int16 value, and divide by 4096.0. (Thus, this field can represent values from -8.0 volts to 7.998 volts.)
Field 1, if present, carries the current System voltage. Divide by 4096.0 to convert from counts to volts. (Thus, this field can represent values from -8.0 volts to 7.998 volts.)
Note: this field is not transmitted by the firmware.
Field 2, if present, carries the current voltage from USB VBus. Divide by 4096.0 to convert from counts to volts. (Thus, this field can represent values from -8.0 volts to 7.998 volts.)
Field 3, if present, is a counter of number of recorded system reboots, modulo 256.
Field 4, if present, has two environmental readings as four bytes of data.
-
The first two bytes are a int16 representing the temperature (divide by 256 to get degrees Celsius).
-
The next two bytes are a uint16 representing the relative humidity (divide by 65535 to get percent). This field can represent humidity from 0% to 100%, in steps of roughly 0.001529%.
Field 5, if present, represents the particulate matter (PM1.0, PM2.5, PM10) in the atmosphere.
Field 6, is present, represents the Dust (PM0.3, PM0.5, PM1.0, PM2.5, PM5, PM10) in the environment.
Field 7, is present, represents the air quality TVOC in the environment.
All multi-byte data is transmitted with the most significant byte first (big-endian format). Comments on the individual formats follow.
an integer from 0 to 65536.
a signed integer from -32,768 to 32,767, in two's complement form. (Thus 0..0x7FFF represent 0 to 32,767; 0x8000 to 0xFFFF represent -32,768 to -1.)
an integer from 0 to 255.
a signed integer from -2,147,483,648 to 2,147,483,647, in two's complement form. (0x00000000 through 0x7FFFFFFF represent 0 to 2,147,483,647; 0x80000000 to 0xFFFFFFFF represent -2,147,483,648 to -1.)
An IEEE-754 single-precision floating point number, in big-endian byte order. The layout is:
31 | 30..23 | 22..0 |
---|---|---|
sign | exponent | mantissa |
The sign bit is set if the number is negative, reset otherwise. Note that negative zero is possible.
The exponent is the binary exponent to be applied to the mantissa, less 127. (Thus an exponent of zero is represented by 0x7F in this field).
The mantissa is the least significant 23 bits of the binary fraction, starting at bit -1 (the "two-to-the-1/2" bit). The effective mantissa is the represented mantissa, plus 1 if the exponent field is not 0x7F.
The following JavaScript code extracts a float32
starting at position i
from buffer bytes
. It handles NANs and +/- infinity, which are all represented with uExp
== 0xFF. JavaScript doesn't distinguish quiet and signaling NaNs, nor does it have signed NaNs. So for all NaNs, the result is just Number.NaN
.
function u4toFloat32(bytes, i) {
// pick up four bytes at index i into variable u32
var u32 = (bytes[i] << 24) + (bytes[i+1] << 16) + (bytes[i+2] << 8) + bytes[i+3];
// extract sign, exponent, mantissa
var bSign = (u32 & 0x80000000) ? true : false;
var uExp = (u32 & 0x7F800000) >> 23;
var uMantissa = (u32 & 0x007FFFFF);
// if non-numeric, return appropriate result.
if (uExp == 0xFF) {
if (uMantissa == 0)
return bSign ? Number.NEGATIVE_INFINITY
: Number.POSITIVE_INFINITY;
else
return Number.NaN;
// else unless denormal, set the 1.0 bit
} else if (uExp != 0) {
uMantissa += 0x00800000;
} else { // denormal: exponent is the minimum
uExp = 1;
}
// make a floating mantissa in [0,2); usually [1,2), but
// sometimes (0,1) for denormals, and exactly zero for zero.
var mantissa = uMantissa / 0x00800000;
// apply the exponent.
mantissa = Math.pow(2, uExp - 127) * mantissa;
// apply sign and return result.
return bSign ? -mantissa : mantissa;
}
In addition to the default commands provided by the library, the sketch provides the following commands:
Get or set the debug mask, which controls the verbosity of debug output from the library.
To get the debug mask, enter command debugmask
on a line by itself.
To set the debug mask, enter debugmask number
, where number is a C-style number indicating the value. For example, debugmask 0x31
is the same as debugmask 49
-- it turns on bits 0, 4, and 5.
The following bits are defined.
Bit | Mask | Name | Description |
---|---|---|---|
0 | 0x00000001 | kError |
Enables error messages |
1 | 0x00000002 | kWarning |
Enables warning messages (none are defined at present) |
2 | 0x00000004 | kTrace |
Enables trace messages. This specifically causes the FSM transitions to be displayed. |
3 | 0x00000008 | kInfo |
Enables informational messages (none are defined at present) |
4 | 0x00000010 | kTxData |
Enable display of data sent by the library to the PMS7003 |
5 | 0x00000020 | kRxDiscard |
Enable display of discarded receive data bytes |
Start or stop the measurement loop. After boot, the measurement loop is enabled by default.
Display the receive statistics. The library keeps track of spurious characters and messages; this is an easy way to get access.
The following Arduino standard libraries are used in this project.
- SPI
- Wire
The following additional libraries are used in this project.
- Arduino LMIC
- Arduino LoRaWAN
- Catena Arduino Platform
- Catena MCCIADK
- MCCI-CatenaPMS7003
- MCCI FRAM I2C
- SGPC3
- MCCI-Catena-SHT3x
Note that the libraries mentioned here are actually govenered by the versions chosen in COLLECTION-model4841.
v1.4.0 has the following changes.
-
Updated the production sketch with a new feature "Firmware Update via Serial" to avoid getting the board into DFU mode.
-
Use the following library:
Name Version Comments BSP 3.1.0 Pick up latest release Catena-Arduino-Platform 0.21.2 Pick up bug fixes
v1.3.2 only has changes in the build system.
Name | Version | Comments |
---|---|---|
tools-build-with-cli | 2.0.1 | set build artifact prefix independtly of sketch name. |
v1.3.1 has the following changes. All are patch changes in libraries, so there's only a patch-release bump.
-
Update the following libraries.
Name Version Comments BSP 3.0.5 Pick up error fix for USB hot interrupt problem arduino-lmic 4.2.0-pre1 Pick up network time support. MCCI-Catena-PMS7003 0.1.2 Pick up official relase (no code changes) MCCI-Catena-SHT3x 0.2.1 pick up official release (no code changes)
v1.3.0 has the following changes
- Updated libraries, thereby adding the
lorawan status
andlorawan subband
commands, thereby causing a minor version bump. - Updated COLLECTION to use common build system.
v1.2.0 has the following changes
-
Fix #1: initialize radio before initializing sensors, so that commands are present.
-
Using the following libraries:
Name Version Comments Catena-Arduino-Platform 0.20.0.30 Pick up error fix for 59-day hang Arduino-LoRaWAN 0.8.0 Arduino-LMIC 3.3.0 MCCIADK 0.2.2 MCCI-Arduino-BSP 2.8.0
v1.1.0 has the following changes.
-
Use the following libraries:
Name Version Catena-Arduino-Platform 0.20.0 Arduino-LoRaWAN 0.8.0 Arduino-LMIC 3.3.0 MCCIADK 0.2.2 MCCI-Arduino-BSP 2.8.0
MCCI and MCCI Catena are registered trademarks of MCCI Corporation. LoRa is a registered trademark of Semtech Corporation. LoRaWAN is a registered trademark of the LoRa Alliance.
This document and the contents of this repository are copyright 2019-2022, MCCI Corporation.
This repository is released under the MIT license. Commercial licenses are also available from MCCI Corporation.
MCCI invests time and resources providing this open source code, please support MCCI and open-source hardware by purchasing products from MCCI, Adafruit and other open-source hardware/software vendors!
For information about MCCI's products, please visit store.mcci.com.