first commit
This commit is contained in:
commit
5893b00dd2
1669 changed files with 1982740 additions and 0 deletions
21
libraries/M5Unit-ENV/LICENSE
Normal file
21
libraries/M5Unit-ENV/LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 M5Stack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
105
libraries/M5Unit-ENV/README.md
Normal file
105
libraries/M5Unit-ENV/README.md
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# M5Unit - ENV
|
||||
|
||||
## Overview
|
||||
|
||||
### SKU:U001 & U001-B & U001-C & U090 & U053-B & U053-D & U103
|
||||
|
||||
Contains M5Stack-**UNIT ENV & Hat ENV & UNIT BPS & UNIT CO2** series related case programs.
|
||||
|
||||
ENV is an environmental sensor with integrated SHT30 and QMP6988 internally to detect temperature, humidity, and atmospheric pressure data.
|
||||
|
||||
BPS is a barometer unit, which integrates the Bosch BMP280 pressure sensor to measure atmospheric pressure and estimate the altitude.
|
||||
|
||||
BPS(QMP6988) Unit is a barometer unit that uses QMP6988 barometric pressure sensor to measure atmospheric pressure and altitude estimation
|
||||
|
||||
CO2 is a photoacoustic Carbon Dioxide (CO2) Unit that will tell you the CO2 PPM (parts-per-million) composition of ambient air.
|
||||
|
||||
## Related Link
|
||||
|
||||
- [Unit ENVIV - Document & Datasheet](https://docs.m5stack.com/en/unit/ENV%E2%85%A3%20Unit)
|
||||
- [Unit ENVIII - Document & Datasheet](https://docs.m5stack.com/en/unit/envIII)
|
||||
- [Unit ENVII - Document & Datasheet](https://docs.m5stack.com/en/unit/envII)
|
||||
- [Unit ENV - Document & Datasheet](https://docs.m5stack.com/en/unit/env)
|
||||
- [Hat ENVIII - Document & Datasheet](https://docs.m5stack.com/en/hat/hat_envIII)
|
||||
- [Hat ENVII - Document & Datasheet](https://docs.m5stack.com/en/hat/hat_envII)
|
||||
- [Unit BPS - Document & Datasheet](https://docs.m5stack.com/en/unit/bps)
|
||||
- [Unit BPS(QMP6988) - Document & Datasheet](https://docs.m5stack.com/en/unit/BPS(QMP6988))
|
||||
- [Unit CO2 - Document & Datasheet](https://docs.m5stack.com/en/unit/co2)
|
||||
|
||||
## Required Libraries:
|
||||
|
||||
- [Adafruit_BMP280_Library](https://github.com/adafruit/Adafruit_BMP280_Library)
|
||||
- [Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor)
|
||||
- [Sensirion I2C SCD4x](https://github.com/Sensirion/arduino-i2c-scd4x)
|
||||
- [Sensirion I2C SHT4x](https://github.com/Sensirion/arduino-i2c-sht4x)
|
||||
- [Sensirion Core](https://github.com/Sensirion/arduino-core)
|
||||
|
||||
## License
|
||||
|
||||
- [M5Unit-ENV - MIT](LICENSE)
|
||||
|
||||
---
|
||||
|
||||
## M5UnitUnified
|
||||
Library for Unit ENV using [M5UnitUnified](https://github.com/m5stack/M5UnitUnified).
|
||||
M5UnitUnified is a library for unified handling of various M5 units products.
|
||||
|
||||
### Supported units
|
||||
- Unit CO2 (SKU:U103)
|
||||
- Unit CO2L (SKU:U104)
|
||||
- Unit ENVIII (SKU:U001-C)
|
||||
- Unit ENVIV (SKU:U001-D)
|
||||
- Unit ENVPro (SKU:U169)
|
||||
- Unit TVOC (SKU:U088)
|
||||
|
||||
### SKU:U088
|
||||
|
||||
TVOC/eCO2 mini Unit is a digital multi-pixel gas sensor unit with integrated SGP30.
|
||||
|
||||
It mainly measures various VOC (volatile organic compounds) and H2 in the air. It can be programmed to detect TVOC (total volatile organic compounds) and eCO2 (equivalent carbon dioxide reading)Concentration measurement.
|
||||
|
||||
Typical measurement accuracy is 15% within the measurement range, the SGP30 reading is internally calibrated and output, which can maintain long-term stability. SGP30 uses I2C protocol communication with on-chip humidity compensation function, which can be turned on through an external humidity sensor.
|
||||
|
||||
If you need to obtain accurate results, you need to calibrate according to a known measurement source. SGP30 has a built-in calibration function. In addition, eCO2 is calculated based on the concentration of H2 and cannot completely replace "true" CO2 sensors for laboratory use.
|
||||
|
||||
## Related Link
|
||||
See also examples using conventional methods here.
|
||||
|
||||
- [UnitTVOC/eCO2 & Datasheet](https://docs.m5stack.com/en/unit/tvoc)
|
||||
|
||||
|
||||
### Include file
|
||||
```cpp
|
||||
#include <M5UnitUnifiedENV.h> // For UnitUnified
|
||||
//#include <M5UnitENV.h> // When using M5UnitUnified, do not use it at the same time as conventional libraries
|
||||
```
|
||||
Supported units will be added in the future.
|
||||
|
||||
### Required Libraries:
|
||||
- [M5UnitUnified](https://github.com/m5stack/M5UnitUnified)
|
||||
- [M5Utility](https://github.com/m5stack/M5Utility)
|
||||
- [M5HAL](https://github.com/m5stack/M5HAL)
|
||||
|
||||
The Bosch library is required by ENVPro to obtain values that cannot be obtained without using the Bosch library.
|
||||
- [Bosch-BME68x-Library](https://github.com/boschsensortec/Bosch-BME68x-Library)
|
||||
- [Bosch-BSEC2-Library](https://github.com/boschsensortec/Bosch-BSEC2-Library) (Excluding NanoC6)
|
||||
|
||||
### Examples
|
||||
See also [examples/UnitUnified](examples/UnitUnified)
|
||||
|
||||
### Doxygen document
|
||||
[GitHub Pages](https://m5stack.github.io/M5Unit-ENV/)
|
||||
|
||||
If you want to generate documents on your local machine, execute the following command
|
||||
|
||||
```
|
||||
bash docs/doxy.sh
|
||||
```
|
||||
|
||||
It will output it under docs/html
|
||||
If you want to output Git commit hashes to html, do it for the git cloned folder.
|
||||
|
||||
#### Required
|
||||
- [Doxyegn](https://www.doxygen.nl/)
|
||||
- [pcregrep](https://formulae.brew.sh/formula/pcre2)
|
||||
- [Git](https://git-scm.com/) (Output commit hash to html)
|
||||
41
libraries/M5Unit-ENV/boards/m5stack-atoms3r.json
Normal file
41
libraries/M5Unit-ENV/boards/m5stack-atoms3r.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"memory_type": "qio_opi",
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"partitions": "default_8MB.csv"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_M5STACK_ATOMS3R",
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"mcu": "esp32s3",
|
||||
"variant": "m5stack_atoms3"
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth",
|
||||
"wifi"
|
||||
],
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "M5Stack AtomS3R",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.m5stack.com/en/core/AtomS3R",
|
||||
"vendor": "M5Stack"
|
||||
}
|
||||
33
libraries/M5Unit-ENV/boards/m5stack-nanoc6.json
Normal file
33
libraries/M5Unit-ENV/boards/m5stack-nanoc6.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"build": {
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DARDUINO_M5STACK_NANOC6"
|
||||
],
|
||||
"f_cpu": "160000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"mcu": "esp32c6",
|
||||
"variant": "esp32c6"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32c6.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "M5Stack NanoC6",
|
||||
"upload": {
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194384,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.m5stack.com/en/core/M5NanoC6",
|
||||
"vendor": "M5Stack"
|
||||
}
|
||||
40
libraries/M5Unit-ENV/boards/m5stick-cplus2.json
Normal file
40
libraries/M5Unit-ENV/boards/m5stick-cplus2.json
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32_out.ld",
|
||||
"partitions": "default_8MB.csv"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DM5STACK_M5STICK_CPLUS2",
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-mfix-esp32-psram-cache-issue",
|
||||
"-mfix-esp32-psram-cache-strategy=memw",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"mcu": "esp32",
|
||||
"variant": "m5stick_c"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi",
|
||||
"bluetooth"
|
||||
],
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "M5Stick-CPlus2",
|
||||
"upload": {
|
||||
"flash_size": "8MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 8388608,
|
||||
"require_upload_port": true,
|
||||
"speed": 1500000
|
||||
},
|
||||
"url": "https://docs.m5stack.com/en/core/M5StickC%20PLUS2",
|
||||
"vendor": "M5Stack"
|
||||
}
|
||||
12
libraries/M5Unit-ENV/custom_script.py
Normal file
12
libraries/M5Unit-ENV/custom_script.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Import("env")
|
||||
|
||||
EXCLUDE_FILES = (env.GetProjectOption("custom_exclude_src_files") or []).split(' ')
|
||||
print(EXCLUDE_FILES)
|
||||
|
||||
def skip_from_build(node):
|
||||
np = node.get_path()
|
||||
if any(ef in np for ef in EXCLUDE_FILES):
|
||||
return None
|
||||
return node
|
||||
|
||||
env.AddBuildMiddleware(skip_from_build, "*")
|
||||
2817
libraries/M5Unit-ENV/docs/Doxyfile
Normal file
2817
libraries/M5Unit-ENV/docs/Doxyfile
Normal file
File diff suppressed because it is too large
Load diff
11
libraries/M5Unit-ENV/docs/doxy.sh
Executable file
11
libraries/M5Unit-ENV/docs/doxy.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Please execute on repositry root
|
||||
|
||||
## Get version from library.properties
|
||||
## Get git rev of HEAD
|
||||
LIB_VERSION="$(pcregrep -o1 "^\s*version\s*=\s*(\*|\d+(\.\d+){0,3}(\.\*)?)" library.properties)"
|
||||
#echo ${DOXYGEN_PROJECT_NUMBER}
|
||||
DOXYGEN_PROJECT_NUMBER="${LIB_VERSION} git rev:$(git rev-parse --short HEAD)" doxygen docs/Doxyfile
|
||||
|
||||
|
||||
64
libraries/M5Unit-ENV/examples/ENV/ENV.ino
Normal file
64
libraries/M5Unit-ENV/examples/ENV/ENV.ino
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file ENV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
66
libraries/M5Unit-ENV/examples/ENV_II/ENV_II.ino
Normal file
66
libraries/M5Unit-ENV/examples/ENV_II/ENV_II.ino
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file ENV_II.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_II
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
60
libraries/M5Unit-ENV/examples/ENV_III/ENV_III.ino
Normal file
60
libraries/M5Unit-ENV/examples/ENV_III/ENV_III.ino
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
/**
|
||||
* @file ENV_III.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_III
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
71
libraries/M5Unit-ENV/examples/ENV_IV/ENV_IV.ino
Normal file
71
libraries/M5Unit-ENV/examples/ENV_IV/ENV_IV.ino
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
/**
|
||||
* @file ENV_IV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_IV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT4X sht4;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht4.begin(&Wire, SHT40_I2C_ADDR_44, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT4x");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
// You can have 3 different precisions, higher precision takes longer
|
||||
sht4.setPrecision(SHT4X_HIGH_PRECISION);
|
||||
sht4.setHeater(SHT4X_NO_HEATER);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht4.update()) {
|
||||
Serial.println("-----SHT4X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht4.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht4.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
142
libraries/M5Unit-ENV/examples/ENV_PRO/ENV_PRO.ino
Normal file
142
libraries/M5Unit-ENV/examples/ENV_PRO/ENV_PRO.ino
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
|
||||
/**
|
||||
* @file ENV_PRO.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_PRO
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* BME68x Sensor library: https://github.com/boschsensortec/Bosch-BME68x-Library
|
||||
* BSEC2 Software Library: https://github.com/boschsensortec/Bosch-BSEC2-Library
|
||||
*/
|
||||
|
||||
#include <bsec2.h>
|
||||
|
||||
/**
|
||||
* @brief : This function checks the BSEC status, prints the respective error
|
||||
* code. Halts in case of error
|
||||
* @param[in] bsec : Bsec2 class object
|
||||
*/
|
||||
void checkBsecStatus(Bsec2 bsec);
|
||||
|
||||
/**
|
||||
* @brief : This function is called by the BSEC library when a new output is
|
||||
* available
|
||||
* @param[in] input : BME68X sensor data before processing
|
||||
* @param[in] outputs : Processed BSEC BSEC output data
|
||||
* @param[in] bsec : Instance of BSEC2 calling the callback
|
||||
*/
|
||||
void newDataCallback(const bme68xData data, const bsecOutputs outputs,
|
||||
Bsec2 bsec);
|
||||
|
||||
/* Create an object of the class Bsec2 */
|
||||
Bsec2 envSensor;
|
||||
|
||||
/* Entry point for the example */
|
||||
void setup(void) {
|
||||
/* Desired subscription list of BSEC2 outputs */
|
||||
bsecSensor sensorList[] = {
|
||||
BSEC_OUTPUT_IAQ, BSEC_OUTPUT_RAW_TEMPERATURE,
|
||||
BSEC_OUTPUT_RAW_PRESSURE, BSEC_OUTPUT_RAW_HUMIDITY,
|
||||
BSEC_OUTPUT_RAW_GAS, BSEC_OUTPUT_STABILIZATION_STATUS,
|
||||
BSEC_OUTPUT_RUN_IN_STATUS};
|
||||
|
||||
/* Initialize the communication interfaces */
|
||||
Serial.begin(115200);
|
||||
Wire.begin(21, 22);
|
||||
|
||||
/* Valid for boards with USB-COM. Wait until the port is open */
|
||||
while (!Serial) delay(10);
|
||||
|
||||
/* Initialize the library and interfaces */
|
||||
if (!envSensor.begin(BME68X_I2C_ADDR_HIGH, Wire)) {
|
||||
checkBsecStatus(envSensor);
|
||||
}
|
||||
|
||||
/* Subsribe to the desired BSEC2 outputs */
|
||||
if (!envSensor.updateSubscription(sensorList, ARRAY_LEN(sensorList),
|
||||
BSEC_SAMPLE_RATE_LP)) {
|
||||
checkBsecStatus(envSensor);
|
||||
}
|
||||
|
||||
/* Whenever new data is available call the newDataCallback function */
|
||||
envSensor.attachCallback(newDataCallback);
|
||||
|
||||
Serial.println("BSEC library version " + String(envSensor.version.major) +
|
||||
"." + String(envSensor.version.minor) + "." +
|
||||
String(envSensor.version.major_bugfix) + "." +
|
||||
String(envSensor.version.minor_bugfix));
|
||||
}
|
||||
|
||||
/* Function that is looped forever */
|
||||
void loop(void) {
|
||||
/* Call the run function often so that the library can
|
||||
* check if it is time to read new data from the sensor
|
||||
* and process it.
|
||||
*/
|
||||
if (!envSensor.run()) {
|
||||
checkBsecStatus(envSensor);
|
||||
}
|
||||
}
|
||||
|
||||
void newDataCallback(const bme68xData data, const bsecOutputs outputs,
|
||||
Bsec2 bsec) {
|
||||
if (!outputs.nOutputs) {
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(
|
||||
"BSEC outputs:\n\ttimestamp = " +
|
||||
String((int)(outputs.output[0].time_stamp / INT64_C(1000000))));
|
||||
for (uint8_t i = 0; i < outputs.nOutputs; i++) {
|
||||
const bsecData output = outputs.output[i];
|
||||
switch (output.sensor_id) {
|
||||
case BSEC_OUTPUT_IAQ:
|
||||
Serial.println("\tiaq = " + String(output.signal));
|
||||
Serial.println("\tiaq accuracy = " +
|
||||
String((int)output.accuracy));
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_TEMPERATURE:
|
||||
Serial.println("\ttemperature = " + String(output.signal));
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_PRESSURE:
|
||||
Serial.println("\tpressure = " + String(output.signal));
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_HUMIDITY:
|
||||
Serial.println("\thumidity = " + String(output.signal));
|
||||
break;
|
||||
case BSEC_OUTPUT_RAW_GAS:
|
||||
Serial.println("\tgas resistance = " + String(output.signal));
|
||||
break;
|
||||
case BSEC_OUTPUT_STABILIZATION_STATUS:
|
||||
Serial.println("\tstabilization status = " +
|
||||
String(output.signal));
|
||||
break;
|
||||
case BSEC_OUTPUT_RUN_IN_STATUS:
|
||||
Serial.println("\trun in status = " + String(output.signal));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkBsecStatus(Bsec2 bsec) {
|
||||
if (bsec.status < BSEC_OK) {
|
||||
Serial.println("BSEC error code : " + String(bsec.status));
|
||||
|
||||
} else if (bsec.status > BSEC_OK) {
|
||||
Serial.println("BSEC warning code : " + String(bsec.status));
|
||||
}
|
||||
|
||||
if (bsec.sensor.status < BME68X_OK) {
|
||||
Serial.println("BME68X error code : " + String(bsec.sensor.status));
|
||||
} else if (bsec.sensor.status > BME68X_OK) {
|
||||
Serial.println("BME68X warning code : " + String(bsec.sensor.status));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
/**
|
||||
* @file Hat_ENVIII_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Hat_ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
/**
|
||||
* @file Hat_ENVIII_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Hat_ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/**
|
||||
* @file Hat_ENVII_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Hat_ENVII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
|
||||
/**
|
||||
* @file Hat_ENVII_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Hat_ENVII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 0, 26, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitCO2
|
||||
Required
|
||||
- M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitCO2
|
||||
*/
|
||||
// #define USING_M5HAL // When using M5HAL
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
m5::unit::UnitCO2 unit;
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
|
||||
#if defined(USING_M5HAL)
|
||||
#pragma message "Using M5HAL"
|
||||
// Using M5HAL
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
if (!Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#pragma message "Using Wire"
|
||||
// Using TwoWire
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
if (!Units.add(unit, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
|
||||
{
|
||||
auto ret = unit.stopPeriodicMeasurement();
|
||||
float offset{};
|
||||
ret &= unit.readTemperatureOffset(offset);
|
||||
uint16_t altitude{};
|
||||
ret &= unit.readSensorAltitude(altitude);
|
||||
uint16_t pressure{};
|
||||
ret &= unit.readAmbientPressure(pressure);
|
||||
bool asc{};
|
||||
ret &= unit.readAutomaticSelfCalibrationEnabled(asc);
|
||||
uint16_t ppm{};
|
||||
ret &= unit.readAutomaticSelfCalibrationTarget(ppm);
|
||||
ret &= unit.startPeriodicMeasurement();
|
||||
|
||||
M5.Log.printf(
|
||||
" temp offset:%f\n"
|
||||
" sensor altitude:%u\n"
|
||||
"ambient pressure:%u\n"
|
||||
" ASC enabled:%u\n"
|
||||
" ASC target:%u\n",
|
||||
offset, altitude, pressure, asc, ppm);
|
||||
|
||||
if (!ret) {
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
if (unit.updated()) {
|
||||
// Can be checked e.g. by serial plotters
|
||||
M5.Log.printf(">CO2:%u\n>Temperature:%2.2f\n>Humidity:%2.2f\n", unit.co2(), unit.temperature(),
|
||||
unit.humidity());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitCO2L
|
||||
Required
|
||||
- M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2025 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitCO2L
|
||||
*/
|
||||
// #define USING_M5HAL // When using M5HAL
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
m5::unit::UnitCO2L unit;
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace m5::unit::scd4x;
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
|
||||
#if defined(USING_M5HAL)
|
||||
#pragma message "Using M5HAL"
|
||||
// Using M5HAL
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
if (!Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#pragma message "Using Wire"
|
||||
// Using TwoWire
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
if (!Units.add(unit, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
|
||||
{
|
||||
auto ret = unit.stopPeriodicMeasurement();
|
||||
float offset{};
|
||||
ret &= unit.readTemperatureOffset(offset);
|
||||
uint16_t altitude{};
|
||||
ret &= unit.readSensorAltitude(altitude);
|
||||
uint16_t pressure{};
|
||||
ret &= unit.readAmbientPressure(pressure);
|
||||
bool asc{};
|
||||
ret &= unit.readAutomaticSelfCalibrationEnabled(asc);
|
||||
uint16_t ppm{};
|
||||
ret &= unit.readAutomaticSelfCalibrationTarget(ppm);
|
||||
uint16_t initialPeriod{}, standardPeriod{};
|
||||
ret &= unit.readAutomaticSelfCalibrationInitialPeriod(initialPeriod);
|
||||
ret &= unit.readAutomaticSelfCalibrationStandardPeriod(standardPeriod);
|
||||
|
||||
ret &= unit.startPeriodicMeasurement();
|
||||
|
||||
M5.Log.printf(
|
||||
" temp offset:%f\n"
|
||||
" sensor altitude:%u\n"
|
||||
"ambient pressure:%u\n"
|
||||
" ASC enabled:%u\n"
|
||||
" ASC target:%u\n"
|
||||
" initial period:%u\n"
|
||||
" standard period:%u\n",
|
||||
offset, altitude, pressure, asc, ppm, initialPeriod, standardPeriod);
|
||||
|
||||
if (!ret) {
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
auto touch = M5.Touch.getDetail();
|
||||
|
||||
// Periodic
|
||||
Units.update();
|
||||
if (unit.updated()) {
|
||||
// Can be checked e.g. by serial plotters
|
||||
M5.Log.printf(">CO2:%u\n>Temperature:%2.2f\n>Humidity:%2.2f\n", unit.co2(), unit.temperature(),
|
||||
unit.humidity());
|
||||
}
|
||||
|
||||
// Single shot
|
||||
if (M5.BtnA.wasClicked() || touch.wasClicked()) {
|
||||
static bool all{}; // false: RHT only
|
||||
all = !all;
|
||||
M5.Log.printf("Try single shot %u, waiting measurement...\n", all);
|
||||
unit.stopPeriodicMeasurement();
|
||||
Data d{};
|
||||
if (all) {
|
||||
if (unit.measureSingleshot(d)) {
|
||||
M5.Log.printf(" SingleAll: %u/%2.2f/%2.2f\n", d.co2(), d.temperature(), d.humidity());
|
||||
}
|
||||
} else {
|
||||
if (unit.measureSingleshotRHT(d)) {
|
||||
M5.Log.printf(" SingleRHT: %2.2f/%2.2f", d.temperature(), d.humidity());
|
||||
}
|
||||
}
|
||||
unit.startPeriodicMeasurement();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVIII
|
||||
Required
|
||||
- M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVIII
|
||||
*/
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
|
||||
// #define USING_M5HAL // When using M5HAL
|
||||
|
||||
// Using single shot measurement If defined
|
||||
// #define USING_SINGLE_SHOT
|
||||
|
||||
// Using combined unit if defined
|
||||
#define USING_ENV3
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
|
||||
#if defined(USING_ENV3)
|
||||
#pragma message "Using combined unit(ENV3)"
|
||||
m5::unit::UnitENV3 unitENV3;
|
||||
#else
|
||||
#pragma message "Using each unit"
|
||||
m5::unit::UnitSHT30 unitSHT30;
|
||||
m5::unit::UnitQMP6988 unitQMP6988;
|
||||
#endif
|
||||
|
||||
#if defined(USING_ENV3)
|
||||
auto& sht30 = unitENV3.sht30;
|
||||
auto& qmp6988 = unitENV3.qmp6988;
|
||||
#else
|
||||
auto& sht30 = unitSHT30;
|
||||
auto& qmp6988 = unitQMP6988;
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
|
||||
#if defined(USING_SINGLE_SHOT)
|
||||
{
|
||||
auto cfg = sht30.config();
|
||||
cfg.start_periodic = false;
|
||||
sht30.config(cfg);
|
||||
}
|
||||
{
|
||||
auto cfg = qmp6988.config();
|
||||
cfg.start_periodic = false;
|
||||
qmp6988.config(cfg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USING_ENV3)
|
||||
#if defined(USING_M5HAL)
|
||||
#pragma message "Using M5HAL"
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
if (!Units.add(unitENV3, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#pragma message "Using Wire"
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
|
||||
if (!Units.add(unitENV3, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if defined(USING_M5HAL)
|
||||
#pragma message "Using M5HAL"
|
||||
m5::hal::bus::I2CBusConfig i2c_cfg;
|
||||
i2c_cfg.pin_sda = m5::hal::gpio::getPin(pin_num_sda);
|
||||
i2c_cfg.pin_scl = m5::hal::gpio::getPin(pin_num_scl);
|
||||
auto i2c_bus = m5::hal::bus::i2c::getBus(i2c_cfg);
|
||||
if (!Units.add(unitSHT30, i2c_bus ? i2c_bus.value() : nullptr) ||
|
||||
!Units.add(unitQMP6988, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#pragma message "Using Wire"
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
if (!Units.add(unitSHT30, Wire) || !Units.add(unitQMP6988, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
#if defined(USING_SINGLE_SHOT)
|
||||
M5_LOGI("\n>>> Click BtnA to single shot measurement");
|
||||
#endif
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
|
||||
#if defined(USING_SINGLE_SHOT)
|
||||
if (M5.BtnA.wasClicked()) {
|
||||
m5::unit::sht30::Data ds{};
|
||||
if (sht30.measureSingleshot(ds)) {
|
||||
M5.Log.printf(">SHT30Temp:%2.2f\n>Humidity:%2.2f\n", ds.temperature(), ds.humidity());
|
||||
}
|
||||
m5::unit::qmp6988::Data dq{};
|
||||
if (qmp6988.measureSingleshot(dq)) {
|
||||
M5.Log.printf(">QMP6988Temp:%2.2f\n>Pressure:%.2f\n", dq.temperature(), dq.pressure() * 0.01f);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (sht30.updated()) {
|
||||
M5.Log.printf(">SHT30Temp:%2.2f\n>Humidity:%2.2f\n", sht30.temperature(), sht30.humidity());
|
||||
}
|
||||
if (qmp6988.updated()) {
|
||||
M5.Log.printf(">QMP6988Temp:%2.2f\n>Pressure:%.2f\n", qmp6988.temperature(), qmp6988.pressure() * 0.01f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVIV
|
||||
Required
|
||||
- M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVIV
|
||||
*/
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
#include <cmath>
|
||||
|
||||
#define USING_ENV4
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
|
||||
#if defined(USING_ENV4)
|
||||
#pragma message "Using combined unit(ENV4)"
|
||||
m5::unit::UnitENV4 unitENV4;
|
||||
#else
|
||||
#pragma message "Using each unit"
|
||||
m5::unit::UnitSHT40 unitSHT40;
|
||||
m5::unit::UnitBMP280 unitBMP280;
|
||||
#endif
|
||||
|
||||
#if defined(USING_ENV4)
|
||||
auto& sht40 = unitENV4.sht40;
|
||||
auto& bmp280 = unitENV4.bmp280;
|
||||
#else
|
||||
auto& sht40 = unitSHT40;
|
||||
auto& bmp280 = unitBMP280;
|
||||
#endif
|
||||
|
||||
float calculate_altitude(const float pressure, const float seaLvhPa = 1013.25f)
|
||||
{
|
||||
return 44330.f * (1.0f - pow((pressure / 100.f) / seaLvhPa, 0.1903f));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
|
||||
{
|
||||
using namespace m5::unit::bmp280;
|
||||
auto cfg = bmp280.config();
|
||||
cfg.osrs_pressure = Oversampling::X16;
|
||||
cfg.osrs_temperature = Oversampling::X2;
|
||||
cfg.filter = Filter::Coeff16;
|
||||
cfg.standby = Standby::Time500ms;
|
||||
bmp280.config(cfg);
|
||||
}
|
||||
|
||||
#if defined(USING_ENV4)
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
|
||||
if (!Units.add(unitENV4, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#else
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400000U);
|
||||
if (!Units.add(unitSHT40, Wire) || !Units.add(unitBMP280, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
|
||||
if (sht40.updated()) {
|
||||
M5.Log.printf(
|
||||
">SHT40Temp:%.4f\n"
|
||||
">Humidity:%.4f\n",
|
||||
sht40.temperature(), sht40.humidity());
|
||||
}
|
||||
if (bmp280.updated()) {
|
||||
auto p = bmp280.pressure();
|
||||
M5.Log.printf(
|
||||
">BMP280Temp:%.4f\n"
|
||||
">Pressure:%.4f\n"
|
||||
">Altitude:%.4f\n",
|
||||
bmp280.temperature(), p * 0.01f /* To hPa */, calculate_altitude(p));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVPro
|
||||
Required
|
||||
- M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitENVPro
|
||||
*/
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
m5::unit::UnitUnified Units;
|
||||
m5::unit::UnitENVPro unit;
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400 * 1000U);
|
||||
|
||||
if (!Units.add(unit, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
if (unit.updated()) {
|
||||
#if defined(UNIT_BME688_USING_BSEC2)
|
||||
M5.Log.printf(">IAQ:%.2f\n>Temperature:%.2f\n>Pressure:%.2f\n>Humidity:%.2f\n>GAS:%.2f\n", unit.iaq(),
|
||||
unit.temperature(), unit.pressure(), unit.humidity(), unit.gas());
|
||||
#else
|
||||
M5.Log.printf(">Temperature:%.2f\n>Pressure:%.2f\n>Humidity:%.2f\n>GAS:%.2f\n", unit.temperature(),
|
||||
unit.pressure(), unit.humidity(), unit.gas());
|
||||
m5::utility::delay(1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitTVOC
|
||||
*/
|
||||
#include "main/PlotToSerial.cpp"
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*
|
||||
Example using M5UnitUnified for UnitTVOC
|
||||
*/
|
||||
#include <M5Unified.h>
|
||||
#include <M5UnitUnified.h>
|
||||
#include <M5UnitUnifiedENV.h>
|
||||
#include <Wire.h>
|
||||
|
||||
namespace {
|
||||
auto& lcd = M5.Display;
|
||||
|
||||
m5::unit::UnitUnified Units;
|
||||
m5::unit::UnitTVOC unit;
|
||||
} // namespace
|
||||
|
||||
void setup()
|
||||
{
|
||||
M5.begin();
|
||||
|
||||
auto pin_num_sda = M5.getPin(m5::pin_name_t::port_a_sda);
|
||||
auto pin_num_scl = M5.getPin(m5::pin_name_t::port_a_scl);
|
||||
M5_LOGI("getPin: SDA:%u SCL:%u", pin_num_sda, pin_num_scl);
|
||||
Wire.end();
|
||||
Wire.begin(pin_num_sda, pin_num_scl, 400 * 1000U);
|
||||
|
||||
if (!Units.add(unit, Wire) || !Units.begin()) {
|
||||
M5_LOGE("Failed to begin");
|
||||
lcd.clear(TFT_RED);
|
||||
while (true) {
|
||||
m5::utility::delay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
M5_LOGI("M5UnitUnified has been begun");
|
||||
M5_LOGI("%s", Units.debugInfo().c_str());
|
||||
M5_LOGW("SGP30 measurement starts 15 seconds after begin");
|
||||
|
||||
lcd.clear(TFT_DARKGREEN);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
M5.update();
|
||||
Units.update();
|
||||
|
||||
// SGP30 measurement starts 15 seconds after begin.
|
||||
if (unit.updated()) {
|
||||
// Can be checked on serial plotters
|
||||
M5.Log.printf("\n>CO2eq:%u\n>TVOC:%u", unit.co2eq(), unit.tvoc());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5Atom.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Atom + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5AtomS3.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3 + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5AtomS3Lite.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3Lite + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5Core.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file Unit_BPS1.1_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit BPS 1.1
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5Atom.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Atom + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5AtomS3.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3 + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5AtomS3Lite.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3Lite + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5Core.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* @file Unit_BPS_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit BPS
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_CO2_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit CO2
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_CO2_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit CO2
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_CO2_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit CO2
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SCD4X scd4x;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!scd4x.begin(&Wire, SCD4X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SCD4X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
uint16_t error;
|
||||
// stop potentially previously started measurement
|
||||
error = scd4x.stopPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute stopPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
// Start Measurement
|
||||
error = scd4x.startPeriodicMeasurement();
|
||||
if (error) {
|
||||
Serial.print("Error trying to execute startPeriodicMeasurement(): ");
|
||||
}
|
||||
|
||||
Serial.println("Waiting for first measurement... (5 sec)");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (scd4x.update()) // readMeasurement will return true when
|
||||
// fresh data is available
|
||||
{
|
||||
Serial.println();
|
||||
|
||||
Serial.print(F("CO2(ppm):"));
|
||||
Serial.print(scd4x.getCO2());
|
||||
|
||||
Serial.print(F("\tTemperature(C):"));
|
||||
Serial.print(scd4x.getTemperature(), 1);
|
||||
|
||||
Serial.print(F("\tHumidity(%RH):"));
|
||||
Serial.print(scd4x.getHumidity(), 1);
|
||||
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.print(F("."));
|
||||
}
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file ENV_III.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.2
|
||||
* @date 2024-07-18
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Atom + Unit ENV_III
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 26, 32, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 26, 32, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file ENV_III.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.2
|
||||
* @date 2024-07-18
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3 + Unit ENV_III
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 2, 1, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file ENV_III.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.2
|
||||
* @date 2024-07-18
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5AtomS3Lite + Unit ENV_III
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 2, 1, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
while (1) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
/**
|
||||
* @file ENV_III.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_III
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file Unit_ENVIII_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file Unit_ENVIII_M5Station.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Station + Unit ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @file Unit_ENVIII_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* @file Unit_ENVIII_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit ENVIII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
QMP6988 qmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find QMP6988");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (qmp.update()) {
|
||||
Serial.println("-----QMP6988-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(qmp.cTemp);
|
||||
Serial.println(" *C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(qmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(qmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file ENV_II.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_II
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file ENV_II.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_II
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file ENV_II.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_II
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file ENV_II.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_II
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* @file Unit_ENVII_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit ENVII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* @file Unit_ENVII_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit ENVII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* @file Unit_ENVII_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit ENVII
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT3X sht3x;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
|
||||
if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find SHT3X");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht3x.update()) {
|
||||
Serial.println("-----SHT3X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht3x.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht3x.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
/**
|
||||
* @file ENV_IV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV_IV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
SHT4X sht4;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
if (!sht4.begin(&Wire, SHT40_I2C_ADDR_44, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find SHT4x");
|
||||
while (1) delay(1);
|
||||
}
|
||||
|
||||
// You can have 3 different precisions, higher precision takes longer
|
||||
sht4.setPrecision(SHT4X_HIGH_PRECISION);
|
||||
sht4.setHeater(SHT4X_NO_HEATER);
|
||||
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (sht4.update()) {
|
||||
Serial.println("-----SHT4X-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(sht4.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(sht4.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2023 by M5Stack
|
||||
* Equipped with M5Core2 sample source code
|
||||
* 配套 M5Core2 示例源代码
|
||||
* Visit to get information: https://docs.m5stack.com/en/unit/ENV%E2%85%A3%20Unit
|
||||
* 获取更多资料请访问: https://docs.m5stack.com/zh_CN/unit/ENV%E2%85%A3%20Unit
|
||||
*
|
||||
* Product: ENVIV_SHT40_BMP280. 环境传感器
|
||||
* Date: 2023/8/24
|
||||
*******************************************************************************
|
||||
Please connect to Port,Read temperature, humidity and atmospheric pressure and
|
||||
display them on the display screen
|
||||
请连接端口,读取温度、湿度和大气压强并在显示屏上显示
|
||||
Libraries:
|
||||
- [Adafruit_BMP280](https://github.com/adafruit/Adafruit_BMP280_Library)
|
||||
- [Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor)
|
||||
- [SensirionI2CSht4x](https://github.com/Tinyu-Zhao/arduino-i2c-sht4x)
|
||||
*/
|
||||
#include <M5Core2.h>
|
||||
#include <SensirionI2CSht4x.h>
|
||||
#include <Adafruit_BMP280.h>
|
||||
#include "Adafruit_Sensor.h"
|
||||
|
||||
// 初始化传感器
|
||||
Adafruit_BMP280 bmp;
|
||||
|
||||
SensirionI2CSht4x sht4x;
|
||||
float temperature, pressure,
|
||||
humidity; // Store the vuale of pressure and Temperature. 存储压力和温度
|
||||
|
||||
void setup()
|
||||
{
|
||||
// 初始化传感器
|
||||
M5.begin();
|
||||
M5.Lcd.setTextSize(2);
|
||||
Wire.begin(); // SDA = 16, SCL = 34
|
||||
Serial.begin(115200);
|
||||
while (!Serial)
|
||||
{
|
||||
delay(100);
|
||||
}
|
||||
while (!bmp.begin(
|
||||
0x76))
|
||||
{ // Init this sensor,True if the init was successful, otherwise
|
||||
// false. 初始化传感器,如果初始化成功返回1
|
||||
M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");
|
||||
Serial.println(F("BMP280 fail"));
|
||||
}
|
||||
M5.Lcd.clear(); // Clear the screen. 清屏
|
||||
Serial.println(F("BMP280 test"));
|
||||
|
||||
uint16_t error;
|
||||
char errorMessage[256];
|
||||
|
||||
sht4x.begin(Wire);
|
||||
|
||||
uint32_t serialNumber;
|
||||
error = sht4x.serialNumber(serialNumber);
|
||||
if (error)
|
||||
{
|
||||
Serial.print("Error trying to execute serialNumber(): ");
|
||||
errorToString(error, errorMessage, 256);
|
||||
Serial.println(errorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Serial Number: ");
|
||||
Serial.println(serialNumber);
|
||||
}
|
||||
|
||||
// 设置传感器的采样率和滤波器
|
||||
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, // 模式:正常
|
||||
Adafruit_BMP280::SAMPLING_X2, // 温度采样率:2倍
|
||||
Adafruit_BMP280::SAMPLING_X16, // 压力采样率:16倍
|
||||
Adafruit_BMP280::FILTER_X16, // 滤波器:16倍
|
||||
Adafruit_BMP280::STANDBY_MS_500); // 等待时间:500毫秒
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
uint16_t error;
|
||||
char errorMessage[256];
|
||||
|
||||
delay(1000);
|
||||
|
||||
error = sht4x.measureHighPrecision(temperature, humidity);
|
||||
if (error)
|
||||
{
|
||||
Serial.print("Error trying to execute measureHighPrecision(): ");
|
||||
errorToString(error, errorMessage, 256);
|
||||
Serial.println(errorMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print("Temperature:");
|
||||
Serial.print(temperature);
|
||||
Serial.print("\t");
|
||||
Serial.print("Humidity:");
|
||||
Serial.println(humidity);
|
||||
}
|
||||
pressure = bmp.readPressure();
|
||||
M5.Lcd.setCursor(0, 0); // 将光标设置在(0 ,0). Set the cursor to (0,0)
|
||||
M5.Lcd.printf("Pressure:%2.0fPa\nTemperature:%2.0f^C", pressure,
|
||||
temperature);
|
||||
M5.Lcd.setCursor(0, 40);
|
||||
M5.Lcd.print("humidity:");
|
||||
M5.Lcd.print(humidity);
|
||||
M5.Lcd.print("%");
|
||||
delay(100);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file ENV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 26, 32, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file ENV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file ENV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 2, 1, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* @file ENV.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
*/
|
||||
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 21, 22, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_ENV_M5Core2.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5Core2 + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_ENV_M5StickC.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickC + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* @file Unit_ENV_M5StickCPlus.ino
|
||||
* @author SeanKwok (shaoxiang@m5stack.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2024-01-30
|
||||
*
|
||||
*
|
||||
* @Hardwares: M5StickCPlus + Unit ENV
|
||||
* @Platform Version: Arduino M5Stack Board Manager v2.1.0
|
||||
* @Dependent Library:
|
||||
* M5UnitENV: https://github.com/m5stack/M5Unit-ENV
|
||||
* M5Unified: https://github.com/m5stack/M5Unified
|
||||
*/
|
||||
|
||||
#include <M5Unified.h>
|
||||
#include "M5UnitENV.h"
|
||||
|
||||
DHT12 dht;
|
||||
BMP280 bmp;
|
||||
|
||||
void setup() {
|
||||
M5.begin();
|
||||
if (!dht.begin(&Wire, DHT12_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find DHT12");
|
||||
while (1) delay(1);
|
||||
}
|
||||
if (!bmp.begin(&Wire, BMP280_I2C_ADDR, 32, 33, 400000U)) {
|
||||
Serial.println("Couldn't find BMP280");
|
||||
while (1) delay(1);
|
||||
}
|
||||
/* Default settings from datasheet. */
|
||||
bmp.setSampling(BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
BMP280::FILTER_X16, /* Filtering. */
|
||||
BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (dht.update()) {
|
||||
Serial.println("-----DHT12-----");
|
||||
Serial.print("Temperature: ");
|
||||
Serial.print(dht.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print("Humidity: ");
|
||||
Serial.print(dht.humidity);
|
||||
Serial.println("% rH");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
|
||||
if (bmp.update()) {
|
||||
Serial.println("-----BMP280-----");
|
||||
Serial.print(F("Temperature: "));
|
||||
Serial.print(bmp.cTemp);
|
||||
Serial.println(" degrees C");
|
||||
Serial.print(F("Pressure: "));
|
||||
Serial.print(bmp.pressure);
|
||||
Serial.println(" Pa");
|
||||
Serial.print(F("Approx altitude: "));
|
||||
Serial.print(bmp.altitude);
|
||||
Serial.println(" m");
|
||||
Serial.println("-------------\r\n");
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
34
libraries/M5Unit-ENV/library.json
Normal file
34
libraries/M5Unit-ENV/library.json
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "M5Unit-ENV",
|
||||
"description": "Library for M5Stack UNIT ENV",
|
||||
"keywords": "M5Stack UNIT ENV,M5UnitUnified",
|
||||
"authors": {
|
||||
"name": "M5Stack",
|
||||
"url": "http://www.m5stack.com"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/m5stack/M5Unit-ENV.git"
|
||||
},
|
||||
"dependencies":
|
||||
{
|
||||
"m5stack/M5UnitUnified": ">=0.1.0",
|
||||
"boschsensortec/BME68x Sensor library": ">=1.3.40408",
|
||||
"boschsensortec/bsec2": ">=1.10.2610"
|
||||
},
|
||||
"version": "1.3.0",
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"headers": [
|
||||
"M5UnitENV.h",
|
||||
"M5UnitUnifiedENV.h"
|
||||
],
|
||||
"platforms": "espressif32",
|
||||
"license": "MIT",
|
||||
"export": {
|
||||
"exclude": [
|
||||
"docs/html"
|
||||
]
|
||||
}
|
||||
}
|
||||
11
libraries/M5Unit-ENV/library.properties
Normal file
11
libraries/M5Unit-ENV/library.properties
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
name=M5Unit-ENV
|
||||
version=1.3.0
|
||||
author=M5Stack
|
||||
maintainer=M5Stack
|
||||
sentence=Library for M5Stack UNIT ENV
|
||||
paragraph=See more on https://docs.m5stack.com/en/unit/envIII
|
||||
category=Device Control
|
||||
url=https://github.com/m5stack/M5Unit-ENV
|
||||
architectures=esp32
|
||||
includes=M5UnitENV.h, M5UnitUnifiedENV.h
|
||||
depends=M5UnitUnified,M5Utility,M5HAL,bsec2,BME68x Sensor library
|
||||
203
libraries/M5Unit-ENV/platformio.ini
Normal file
203
libraries/M5Unit-ENV/platformio.ini
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
;-----------------------------------------------------------------------
|
||||
; M5Unit-ENV
|
||||
; For UnitTest and examples (Using M5UnitUnified)
|
||||
;-----------------------------------------------------------------------
|
||||
[platformio]
|
||||
extra_configs = unit_co2_env.ini, unit_env3_env.ini, unit_env4_env.ini, unit_envpro_env.ini, unit_tvoc_env.ini
|
||||
|
||||
[env]
|
||||
build_flags =-Wall -Wextra -Wreturn-local-addr -Werror=format -Werror=return-local-addr
|
||||
lib_ldf_mode = deep
|
||||
test_framework = googletest
|
||||
test_build_src = true
|
||||
lib_deps=m5stack/M5Unified
|
||||
m5stack/M5UnitUnified
|
||||
boschsensortec/BME68x Sensor library@>=1.3.40408
|
||||
|
||||
; --------------------------------
|
||||
[bsec2]
|
||||
lib_deps = boschsensortec/bsec2@>=1.10.2610
|
||||
|
||||
[m5base]
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder, time
|
||||
upload_speed = 1500000
|
||||
test_speed = 115200
|
||||
test_ignore= native/*
|
||||
|
||||
[Core]
|
||||
extends = m5base
|
||||
board = m5stack-grey
|
||||
;m5stack-grey
|
||||
;m5stack-core-esp32-16M ;;6.8.0 or later
|
||||
;m5stack-core-esp32
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[Core2]
|
||||
extends = m5base
|
||||
board = m5stack-core2
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[CoreS3]
|
||||
extends = m5base
|
||||
board = m5stack-cores3
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[Fire]
|
||||
extends = m5base
|
||||
board = m5stack-fire
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[StampS3]
|
||||
;include M5Capsule,M5DinMeter
|
||||
extends = m5base
|
||||
board = m5stack-stamps3
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[Dial]
|
||||
extends = m5base
|
||||
board = m5stack-stamps3
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
m5stack/M5Dial
|
||||
|
||||
[AtomMatrix]
|
||||
extends = m5base
|
||||
board = m5stack-atom
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[AtomS3]
|
||||
extends = m5base
|
||||
board = m5stack-atoms3
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
; Using ./boards/m5stack-atoms3r.json
|
||||
[AtomS3R]
|
||||
extends = m5base
|
||||
board = m5stack-atoms3r
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
; Using ./boards/m5stack-nanoc6.json
|
||||
[NanoC6]
|
||||
extends = m5base
|
||||
board = m5stack-nanoc6
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
platform_packages =
|
||||
platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git#3.0.7
|
||||
platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1
|
||||
board_build.partitions = default.csv
|
||||
lib_deps = ${env.lib_deps}
|
||||
|
||||
[StickCPlus]
|
||||
extends = m5base
|
||||
board = m5stick-c
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
; Using ./boards/m5stick-cplus2.json
|
||||
[StickCPlus2]
|
||||
extends = m5base
|
||||
board = m5stick-cplus2
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[Paper]
|
||||
extends = m5base
|
||||
board = m5stack-fire
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[CoreInk]
|
||||
extends = m5base
|
||||
board = m5stack-coreink
|
||||
lib_deps = ${env.lib_deps}
|
||||
${bsec2.lib_deps}
|
||||
|
||||
[sdl]
|
||||
build_flags = -O3 -xc++ -std=c++14 -lSDL2
|
||||
-arch arm64 ; for arm mac
|
||||
-I"/usr/local/include/SDL2" ; for intel mac homebrew SDL2
|
||||
-L"/usr/local/lib" ; for intel mac homebrew SDL2
|
||||
-I"${sysenv.HOMEBREW_PREFIX}/include/SDL2" ; for arm mac homebrew SDL2
|
||||
-L"${sysenv.HOMEBREW_PREFIX}/lib" ; for arm mac homebrew SDL2
|
||||
platform = native
|
||||
test_filter= native/*
|
||||
test_ignore= embedded/*
|
||||
lib_deps = ${env.lib_deps}
|
||||
|
||||
; --------------------------------
|
||||
;Choose framework
|
||||
[arduino_latest]
|
||||
platform = espressif32 @ 6.8.1
|
||||
framework = arduino
|
||||
|
||||
[arduino_6_6_0]
|
||||
platform = espressif32 @ 6.6.0
|
||||
framework = arduino
|
||||
|
||||
[arduino_6_0_1]
|
||||
platform = espressif32 @ 6.0.1
|
||||
framework = arduino
|
||||
|
||||
[arduino_5_4_0]
|
||||
platform = espressif32 @ 5.4.0
|
||||
framework = arduino
|
||||
|
||||
[arduino_4_4_0]
|
||||
platform = espressif32 @ 4.4.0
|
||||
framework = arduino
|
||||
|
||||
;[arduino_3_5_0]
|
||||
;platform = espressif32 @ 3.5.0
|
||||
;framework = arduino
|
||||
|
||||
[esp-idf]
|
||||
platform = espressif32 @ 6.8.1
|
||||
framework = espidf
|
||||
|
||||
; --------------------------------
|
||||
;Choose build options
|
||||
[option_release]
|
||||
build_type=release
|
||||
build_flags = ${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=3
|
||||
-DLOG_LOCAL_LEVEL=3
|
||||
-DAPP_LOG_LEVEL=3
|
||||
-DM5_LOG_LEVEL=3
|
||||
|
||||
[option_log]
|
||||
build_type=release
|
||||
build_flags = ${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=5
|
||||
-DLOG_LOCAL_LEVEL=5
|
||||
-DAPP_LOG_LEVEL=5
|
||||
|
||||
[option_debug]
|
||||
build_type=debug
|
||||
build_flags = ${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=5
|
||||
-DLOG_LOCAL_LEVEL=5
|
||||
-DAPP_LOG_LEVEL=5
|
||||
-DDEBUG
|
||||
|
||||
[option_map]
|
||||
build_type=release
|
||||
build_flags = ${env.build_flags}
|
||||
-DCORE_DEBUG_LEVEL=3
|
||||
-DLOG_LOCAL_LEVEL=3
|
||||
-DAPP_LOG_LEVEL=3
|
||||
-DM5_LOG_LEVEL=0
|
||||
-Wl,-Map,output.map
|
||||
|
||||
; Require at leaset C++14 after 1.13.0
|
||||
[test_fw]
|
||||
lib_deps = google/googletest@1.12.1
|
||||
|
||||
237
libraries/M5Unit-ENV/src/BMP280.cpp
Normal file
237
libraries/M5Unit-ENV/src/BMP280.cpp
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
#include "BMP280.h"
|
||||
|
||||
bool BMP280::begin(TwoWire* wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
if (!_i2c.exist(_addr)) {
|
||||
return false;
|
||||
}
|
||||
readCoefficients();
|
||||
setSampling();
|
||||
|
||||
return true;
|
||||
}
|
||||
bool BMP280::update() {
|
||||
readTemperature();
|
||||
readPressure();
|
||||
readAltitude();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float BMP280::readTemperature() {
|
||||
int32_t var1, var2;
|
||||
|
||||
int32_t adc_T = read24(BMP280_REGISTER_TEMPDATA);
|
||||
adc_T >>= 4;
|
||||
|
||||
var1 = ((((adc_T >> 3) - ((int32_t)_bmp280_calib.dig_T1 << 1))) *
|
||||
((int32_t)_bmp280_calib.dig_T2)) >>
|
||||
11;
|
||||
|
||||
var2 = (((((adc_T >> 4) - ((int32_t)_bmp280_calib.dig_T1)) *
|
||||
((adc_T >> 4) - ((int32_t)_bmp280_calib.dig_T1))) >>
|
||||
12) *
|
||||
((int32_t)_bmp280_calib.dig_T3)) >>
|
||||
14;
|
||||
|
||||
t_fine = var1 + var2;
|
||||
|
||||
float T = (t_fine * 5 + 128) >> 8;
|
||||
cTemp = T / 100;
|
||||
return cTemp;
|
||||
}
|
||||
|
||||
float BMP280::readPressure() {
|
||||
int64_t var1, var2, p;
|
||||
|
||||
// Must be done first to get the t_fine variable set up
|
||||
|
||||
int32_t adc_P = read24(BMP280_REGISTER_PRESSUREDATA);
|
||||
adc_P >>= 4;
|
||||
|
||||
var1 = ((int64_t)t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)_bmp280_calib.dig_P6;
|
||||
var2 = var2 + ((var1 * (int64_t)_bmp280_calib.dig_P5) << 17);
|
||||
var2 = var2 + (((int64_t)_bmp280_calib.dig_P4) << 35);
|
||||
var1 = ((var1 * var1 * (int64_t)_bmp280_calib.dig_P3) >> 8) +
|
||||
((var1 * (int64_t)_bmp280_calib.dig_P2) << 12);
|
||||
var1 =
|
||||
(((((int64_t)1) << 47) + var1)) * ((int64_t)_bmp280_calib.dig_P1) >> 33;
|
||||
|
||||
if (var1 == 0) {
|
||||
return 0; // avoid exception caused by division by zero
|
||||
}
|
||||
p = 1048576 - adc_P;
|
||||
p = (((p << 31) - var2) * 3125) / var1;
|
||||
var1 = (((int64_t)_bmp280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
|
||||
var2 = (((int64_t)_bmp280_calib.dig_P8) * p) >> 19;
|
||||
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)_bmp280_calib.dig_P7) << 4);
|
||||
pressure = p / 256;
|
||||
return pressure;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Calculates the approximate altitude using barometric pressure and the
|
||||
* supplied sea level hPa as a reference.
|
||||
* @param seaLevelhPa
|
||||
* The current hPa at sea level.
|
||||
* @return The approximate altitude above sea level in meters.
|
||||
*/
|
||||
float BMP280::readAltitude(float seaLevelhPa) {
|
||||
float pressure = readPressure(); // in Si units for Pascal
|
||||
pressure /= 100;
|
||||
altitude = 44330 * (1.0 - pow(pressure / seaLevelhPa, 0.1903));
|
||||
return altitude;
|
||||
}
|
||||
|
||||
void BMP280::setSampling(sensor_mode mode, sensor_sampling tempSampling,
|
||||
sensor_sampling pressSampling, sensor_filter filter,
|
||||
standby_duration duration) {
|
||||
_measReg.mode = mode;
|
||||
_measReg.osrs_t = tempSampling;
|
||||
_measReg.osrs_p = pressSampling;
|
||||
|
||||
_configReg.filter = filter;
|
||||
_configReg.t_sb = duration;
|
||||
|
||||
write8(BMP280_REGISTER_CONFIG, _configReg.get());
|
||||
write8(BMP280_REGISTER_CONTROL, _measReg.get());
|
||||
}
|
||||
|
||||
void BMP280::readCoefficients() {
|
||||
_bmp280_calib.dig_T1 = read16_LE(BMP280_REGISTER_DIG_T1);
|
||||
_bmp280_calib.dig_T2 = readS16_LE(BMP280_REGISTER_DIG_T2);
|
||||
_bmp280_calib.dig_T3 = readS16_LE(BMP280_REGISTER_DIG_T3);
|
||||
|
||||
_bmp280_calib.dig_P1 = read16_LE(BMP280_REGISTER_DIG_P1);
|
||||
_bmp280_calib.dig_P2 = readS16_LE(BMP280_REGISTER_DIG_P2);
|
||||
_bmp280_calib.dig_P3 = readS16_LE(BMP280_REGISTER_DIG_P3);
|
||||
_bmp280_calib.dig_P4 = readS16_LE(BMP280_REGISTER_DIG_P4);
|
||||
_bmp280_calib.dig_P5 = readS16_LE(BMP280_REGISTER_DIG_P5);
|
||||
_bmp280_calib.dig_P6 = readS16_LE(BMP280_REGISTER_DIG_P6);
|
||||
_bmp280_calib.dig_P7 = readS16_LE(BMP280_REGISTER_DIG_P7);
|
||||
_bmp280_calib.dig_P8 = readS16_LE(BMP280_REGISTER_DIG_P8);
|
||||
_bmp280_calib.dig_P9 = readS16_LE(BMP280_REGISTER_DIG_P9);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculates the pressure at sea level (QNH) from the specified altitude,
|
||||
* and atmospheric pressure (QFE).
|
||||
* @param altitude Altitude in m
|
||||
* @param atmospheric Atmospheric pressure in hPa
|
||||
* @return The approximate pressure in hPa
|
||||
*/
|
||||
float BMP280::seaLevelForAltitude(float altitude, float atmospheric) {
|
||||
// Equation taken from BMP180 datasheet (page 17):
|
||||
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
|
||||
|
||||
// Note that using the equation from wikipedia can give bad results
|
||||
// at high altitude. See this thread for more information:
|
||||
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064
|
||||
return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief calculates the boiling point of water by a given pressure
|
||||
@param pressure pressure in hPa
|
||||
@return temperature in °C
|
||||
*/
|
||||
|
||||
float BMP280::waterBoilingPoint(float pressure) {
|
||||
// Magnusformular for calculation of the boiling point of water at a given
|
||||
// pressure
|
||||
return (234.175 * log(pressure / 6.1078)) /
|
||||
(17.08085 - log(pressure / 6.1078));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Take a new measurement (only possible in forced mode)
|
||||
@return true if successful, otherwise false
|
||||
*/
|
||||
bool BMP280::takeForcedMeasurement() {
|
||||
// If we are in forced mode, the BME sensor goes back to sleep after each
|
||||
// measurement and we need to set it to forced mode once at this point, so
|
||||
// it will take the next measurement and then return to sleep again.
|
||||
// In normal mode simply does new measurements periodically.
|
||||
if (_measReg.mode == MODE_FORCED) {
|
||||
// set to forced mode, i.e. "take next measurement"
|
||||
write8(BMP280_REGISTER_CONTROL, _measReg.get());
|
||||
// wait until measurement has been completed, otherwise we would read
|
||||
// the values from the last measurement
|
||||
while (read8(BMP280_REGISTER_STATUS) & 0x08) delay(1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Resets the chip via soft reset
|
||||
*/
|
||||
void BMP280::reset(void) {
|
||||
write8(BMP280_REGISTER_SOFTRESET, MODE_SOFT_RESET_CODE);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Gets the most recent sensor event from the hardware status register.
|
||||
@return Sensor status as a byte.
|
||||
*/
|
||||
uint8_t BMP280::getStatus(void) {
|
||||
return read8(BMP280_REGISTER_STATUS);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Writes an 8 bit value over I2C/SPI
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void BMP280::write8(byte reg, byte value) {
|
||||
_i2c.writeByte(_addr, reg, value);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads an 8 bit value over I2C/SPI
|
||||
* @param reg
|
||||
* selected register
|
||||
* @return value from selected register
|
||||
*/
|
||||
uint8_t BMP280::read8(byte reg) {
|
||||
return _i2c.readByte(_addr, reg);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads a 16 bit value over I2C/SPI
|
||||
*/
|
||||
uint16_t BMP280::read16(byte reg) {
|
||||
uint8_t buffer[2];
|
||||
_i2c.readBytes(_addr, reg, buffer, 2);
|
||||
return uint16_t(buffer[0]) << 8 | uint16_t(buffer[1]);
|
||||
}
|
||||
|
||||
uint16_t BMP280::read16_LE(byte reg) {
|
||||
uint16_t temp = read16(reg);
|
||||
return (temp >> 8) | (temp << 8);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads a signed 16 bit value over I2C/SPI
|
||||
*/
|
||||
int16_t BMP280::readS16(byte reg) {
|
||||
return (int16_t)read16(reg);
|
||||
}
|
||||
|
||||
int16_t BMP280::readS16_LE(byte reg) {
|
||||
return (int16_t)read16_LE(reg);
|
||||
}
|
||||
|
||||
/*!
|
||||
* @brief Reads a 24 bit value over I2C/SPI
|
||||
*/
|
||||
uint32_t BMP280::read24(byte reg) {
|
||||
uint8_t buffer[3];
|
||||
_i2c.readBytes(_addr, reg, buffer, 3);
|
||||
return uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 |
|
||||
uint32_t(buffer[2]);
|
||||
}
|
||||
199
libraries/M5Unit-ENV/src/BMP280.h
Normal file
199
libraries/M5Unit-ENV/src/BMP280.h
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
|
||||
#ifndef _BMP280_H
|
||||
#define _BMP280_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "I2C_Class.h"
|
||||
|
||||
#define BMP280_I2C_ADDR 0x76
|
||||
|
||||
enum {
|
||||
BMP280_REGISTER_DIG_T1 = 0x88,
|
||||
BMP280_REGISTER_DIG_T2 = 0x8A,
|
||||
BMP280_REGISTER_DIG_T3 = 0x8C,
|
||||
BMP280_REGISTER_DIG_P1 = 0x8E,
|
||||
BMP280_REGISTER_DIG_P2 = 0x90,
|
||||
BMP280_REGISTER_DIG_P3 = 0x92,
|
||||
BMP280_REGISTER_DIG_P4 = 0x94,
|
||||
BMP280_REGISTER_DIG_P5 = 0x96,
|
||||
BMP280_REGISTER_DIG_P6 = 0x98,
|
||||
BMP280_REGISTER_DIG_P7 = 0x9A,
|
||||
BMP280_REGISTER_DIG_P8 = 0x9C,
|
||||
BMP280_REGISTER_DIG_P9 = 0x9E,
|
||||
BMP280_REGISTER_CHIPID = 0xD0,
|
||||
BMP280_REGISTER_VERSION = 0xD1,
|
||||
BMP280_REGISTER_SOFTRESET = 0xE0,
|
||||
BMP280_REGISTER_CAL26 = 0xE1, /**< R calibration = 0xE1-0xF0 */
|
||||
BMP280_REGISTER_STATUS = 0xF3,
|
||||
BMP280_REGISTER_CONTROL = 0xF4,
|
||||
BMP280_REGISTER_CONFIG = 0xF5,
|
||||
BMP280_REGISTER_PRESSUREDATA = 0xF7,
|
||||
BMP280_REGISTER_TEMPDATA = 0xFA,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16_t dig_T1; /**< dig_T1 cal register. */
|
||||
int16_t dig_T2; /**< dig_T2 cal register. */
|
||||
int16_t dig_T3; /**< dig_T3 cal register. */
|
||||
|
||||
uint16_t dig_P1; /**< dig_P1 cal register. */
|
||||
int16_t dig_P2; /**< dig_P2 cal register. */
|
||||
int16_t dig_P3; /**< dig_P3 cal register. */
|
||||
int16_t dig_P4; /**< dig_P4 cal register. */
|
||||
int16_t dig_P5; /**< dig_P5 cal register. */
|
||||
int16_t dig_P6; /**< dig_P6 cal register. */
|
||||
int16_t dig_P7; /**< dig_P7 cal register. */
|
||||
int16_t dig_P8; /**< dig_P8 cal register. */
|
||||
int16_t dig_P9; /**< dig_P9 cal register. */
|
||||
} bmp280_calib_data;
|
||||
|
||||
class BMP280 {
|
||||
public:
|
||||
/** Oversampling rate for the sensor. */
|
||||
enum sensor_sampling {
|
||||
/** No over-sampling. */
|
||||
SAMPLING_NONE = 0x00,
|
||||
/** 1x over-sampling. */
|
||||
SAMPLING_X1 = 0x01,
|
||||
/** 2x over-sampling. */
|
||||
SAMPLING_X2 = 0x02,
|
||||
/** 4x over-sampling. */
|
||||
SAMPLING_X4 = 0x03,
|
||||
/** 8x over-sampling. */
|
||||
SAMPLING_X8 = 0x04,
|
||||
/** 16x over-sampling. */
|
||||
SAMPLING_X16 = 0x05
|
||||
};
|
||||
|
||||
/** Operating mode for the sensor. */
|
||||
enum sensor_mode {
|
||||
/** Sleep mode. */
|
||||
MODE_SLEEP = 0x00,
|
||||
/** Forced mode. */
|
||||
MODE_FORCED = 0x01,
|
||||
/** Normal mode. */
|
||||
MODE_NORMAL = 0x03,
|
||||
/** Software reset. */
|
||||
MODE_SOFT_RESET_CODE = 0xB6
|
||||
};
|
||||
|
||||
/** Filtering level for sensor data. */
|
||||
enum sensor_filter {
|
||||
/** No filtering. */
|
||||
FILTER_OFF = 0x00,
|
||||
/** 2x filtering. */
|
||||
FILTER_X2 = 0x01,
|
||||
/** 4x filtering. */
|
||||
FILTER_X4 = 0x02,
|
||||
/** 8x filtering. */
|
||||
FILTER_X8 = 0x03,
|
||||
/** 16x filtering. */
|
||||
FILTER_X16 = 0x04
|
||||
};
|
||||
|
||||
/** Standby duration in ms */
|
||||
enum standby_duration {
|
||||
/** 1 ms standby. */
|
||||
STANDBY_MS_1 = 0x00,
|
||||
/** 62.5 ms standby. */
|
||||
STANDBY_MS_63 = 0x01,
|
||||
/** 125 ms standby. */
|
||||
STANDBY_MS_125 = 0x02,
|
||||
/** 250 ms standby. */
|
||||
STANDBY_MS_250 = 0x03,
|
||||
/** 500 ms standby. */
|
||||
STANDBY_MS_500 = 0x04,
|
||||
/** 1000 ms standby. */
|
||||
STANDBY_MS_1000 = 0x05,
|
||||
/** 2000 ms standby. */
|
||||
STANDBY_MS_2000 = 0x06,
|
||||
/** 4000 ms standby. */
|
||||
STANDBY_MS_4000 = 0x07
|
||||
};
|
||||
|
||||
public:
|
||||
bool begin(TwoWire *wire = &Wire, uint8_t addr = BMP280_I2C_ADDR,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U);
|
||||
bool update();
|
||||
|
||||
float pressure = 0;
|
||||
float cTemp = 0;
|
||||
float altitude = 0;
|
||||
|
||||
void reset(void);
|
||||
uint8_t getStatus(void);
|
||||
|
||||
float readTemperature();
|
||||
float readPressure(void);
|
||||
float readAltitude(float seaLevelhPa = 1013.25);
|
||||
float seaLevelForAltitude(float altitude, float atmospheric);
|
||||
float waterBoilingPoint(float pressure);
|
||||
bool takeForcedMeasurement();
|
||||
|
||||
void setSampling(sensor_mode mode = MODE_NORMAL,
|
||||
sensor_sampling tempSampling = SAMPLING_X16,
|
||||
sensor_sampling pressSampling = SAMPLING_X16,
|
||||
sensor_filter filter = FILTER_OFF,
|
||||
standby_duration duration = STANDBY_MS_1);
|
||||
|
||||
private:
|
||||
/** Encapsulates the config register */
|
||||
struct config {
|
||||
/** Initialize to power-on-reset state */
|
||||
config()
|
||||
: t_sb(STANDBY_MS_1), filter(FILTER_OFF), none(0), spi3w_en(0) {
|
||||
}
|
||||
/** Inactive duration (standby time) in normal mode */
|
||||
unsigned int t_sb : 3;
|
||||
/** Filter settings */
|
||||
unsigned int filter : 3;
|
||||
/** Unused - don't set */
|
||||
unsigned int none : 1;
|
||||
/** Enables 3-wire SPI */
|
||||
unsigned int spi3w_en : 1;
|
||||
/** Used to retrieve the assembled config register's byte value. */
|
||||
unsigned int get() {
|
||||
return (t_sb << 5) | (filter << 2) | spi3w_en;
|
||||
}
|
||||
};
|
||||
|
||||
/** Encapsulates trhe ctrl_meas register */
|
||||
struct ctrl_meas {
|
||||
/** Initialize to power-on-reset state */
|
||||
ctrl_meas()
|
||||
: osrs_t(SAMPLING_NONE), osrs_p(SAMPLING_NONE), mode(MODE_SLEEP) {
|
||||
}
|
||||
/** Temperature oversampling. */
|
||||
unsigned int osrs_t : 3;
|
||||
/** Pressure oversampling. */
|
||||
unsigned int osrs_p : 3;
|
||||
/** Device mode */
|
||||
unsigned int mode : 2;
|
||||
/** Used to retrieve the assembled ctrl_meas register's byte value. */
|
||||
unsigned int get() {
|
||||
return (osrs_t << 5) | (osrs_p << 2) | mode;
|
||||
}
|
||||
};
|
||||
|
||||
void readCoefficients(void);
|
||||
uint8_t spixfer(uint8_t x);
|
||||
void write8(byte reg, byte value);
|
||||
uint8_t read8(byte reg);
|
||||
uint16_t read16(byte reg);
|
||||
uint32_t read24(byte reg);
|
||||
int16_t readS16(byte reg);
|
||||
uint16_t read16_LE(byte reg);
|
||||
int16_t readS16_LE(byte reg);
|
||||
|
||||
int32_t t_fine;
|
||||
bmp280_calib_data _bmp280_calib;
|
||||
config _configReg;
|
||||
ctrl_meas _measReg;
|
||||
|
||||
private:
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
};
|
||||
|
||||
#endif
|
||||
23
libraries/M5Unit-ENV/src/DHT12.cpp
Normal file
23
libraries/M5Unit-ENV/src/DHT12.cpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#include "DHT12.h"
|
||||
|
||||
bool DHT12::begin(TwoWire* wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
return _i2c.exist(_addr);
|
||||
}
|
||||
|
||||
bool DHT12::update() {
|
||||
uint8_t datos[5] = {0};
|
||||
if (_i2c.readBytes(_addr, 0, datos, 5)) {
|
||||
if (datos[4] != (datos[0] + datos[1] + datos[2] + datos[3])) {
|
||||
return false;
|
||||
}
|
||||
cTemp = (datos[2] + (float)datos[3] / 10);
|
||||
fTemp = ((datos[2] + (float)datos[3] / 10) * 1.8 + 32);
|
||||
kTemp = (datos[2] + (float)datos[3] / 10) + 273.15;
|
||||
humidity = (datos[0] + (float)datos[1] / 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
26
libraries/M5Unit-ENV/src/DHT12.h
Normal file
26
libraries/M5Unit-ENV/src/DHT12.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#ifndef _DHT12_H
|
||||
#define _DHT12_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "I2C_Class.h"
|
||||
|
||||
#define DHT12_I2C_ADDR 0x5c
|
||||
|
||||
class DHT12 {
|
||||
public:
|
||||
bool begin(TwoWire* wire = &Wire, uint8_t addr = DHT12_I2C_ADDR,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U);
|
||||
bool update();
|
||||
float cTemp = 0;
|
||||
float fTemp = 0;
|
||||
float kTemp = 0;
|
||||
float humidity = 0;
|
||||
|
||||
private:
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
};
|
||||
|
||||
#endif
|
||||
93
libraries/M5Unit-ENV/src/I2C_Class.cpp
Normal file
93
libraries/M5Unit-ENV/src/I2C_Class.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include "I2C_Class.h"
|
||||
|
||||
void I2C_Class::begin(TwoWire *wire, uint8_t sda, uint8_t scl, long freq) {
|
||||
_wire = wire;
|
||||
_sda = sda;
|
||||
_scl = scl;
|
||||
_freq = freq;
|
||||
_wire->end();
|
||||
_wire->begin(static_cast<int>(_sda), _scl, freq);
|
||||
}
|
||||
|
||||
bool I2C_Class::exist(uint8_t addr) {
|
||||
int error;
|
||||
_wire->beginTransmission(addr);
|
||||
error = _wire->endTransmission();
|
||||
if (error == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool I2C_Class::writeBytes(uint8_t addr, uint8_t reg, uint8_t *buffer,
|
||||
uint8_t length) {
|
||||
_wire->beginTransmission(addr);
|
||||
_wire->write(reg);
|
||||
_wire->write(buffer, length);
|
||||
if (_wire->endTransmission() == 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool I2C_Class::readBytes(uint8_t addr, uint8_t reg, uint8_t *buffer,
|
||||
uint8_t length) {
|
||||
uint8_t index = 0;
|
||||
_wire->beginTransmission(addr);
|
||||
_wire->write(reg);
|
||||
_wire->endTransmission();
|
||||
if (_wire->requestFrom(addr, length)) {
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
buffer[index++] = _wire->read();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool I2C_Class::readU16(uint8_t addr, uint8_t reg_addr, uint16_t *value) {
|
||||
uint8_t read_buf[2] = {0x00, 0x00};
|
||||
bool result = readBytes(addr, reg_addr, read_buf, 2);
|
||||
*value = (read_buf[0] << 8) | read_buf[1];
|
||||
return result;
|
||||
}
|
||||
|
||||
bool I2C_Class::writeU16(uint8_t addr, uint8_t reg_addr, uint16_t value) {
|
||||
uint8_t write_buf[2];
|
||||
write_buf[0] = value >> 8;
|
||||
write_buf[1] = value & 0xff;
|
||||
return writeBytes(addr, reg_addr, write_buf, 2);
|
||||
}
|
||||
|
||||
bool I2C_Class::writeByte(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
_wire->beginTransmission(addr);
|
||||
_wire->write(reg);
|
||||
_wire->write(data);
|
||||
if (_wire->endTransmission() == 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t I2C_Class::readByte(uint8_t addr, uint8_t reg) {
|
||||
_wire->beginTransmission(addr);
|
||||
_wire->write(reg);
|
||||
_wire->endTransmission();
|
||||
|
||||
if (_wire->requestFrom(addr, 1)) {
|
||||
return _wire->read();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool I2C_Class::writeBitOn(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
uint8_t temp;
|
||||
uint8_t write_back;
|
||||
temp = readByte(addr, reg);
|
||||
write_back = (temp | data);
|
||||
return (writeByte(addr, reg, write_back));
|
||||
}
|
||||
|
||||
bool I2C_Class::writeBitOff(uint8_t addr, uint8_t reg, uint8_t data) {
|
||||
uint8_t temp;
|
||||
uint8_t write_back;
|
||||
temp = readByte(addr, reg);
|
||||
write_back = (temp & (~data));
|
||||
return (writeByte(addr, reg, write_back));
|
||||
}
|
||||
30
libraries/M5Unit-ENV/src/I2C_Class.h
Normal file
30
libraries/M5Unit-ENV/src/I2C_Class.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef _I2C_DEVICE_BUS_
|
||||
#define _I2C_DEVICE_BUS_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
|
||||
class I2C_Class {
|
||||
private:
|
||||
TwoWire* _wire;
|
||||
uint8_t _scl;
|
||||
uint8_t _sda;
|
||||
long _freq;
|
||||
|
||||
public:
|
||||
void begin(TwoWire* wire, uint8_t sda, uint8_t scl, long freq = 100000);
|
||||
bool exist(uint8_t addr);
|
||||
|
||||
bool writeBytes(uint8_t addr, uint8_t reg, uint8_t* buffer, uint8_t length);
|
||||
bool readBytes(uint8_t addr, uint8_t reg, uint8_t* buffer, uint8_t length);
|
||||
|
||||
bool readU16(uint8_t addr, uint8_t reg_addr, uint16_t* value);
|
||||
bool writeU16(uint8_t addr, uint8_t reg_addr, uint16_t value);
|
||||
|
||||
bool writeByte(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
uint8_t readByte(uint8_t addr, uint8_t reg);
|
||||
bool writeBitOn(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
bool writeBitOff(uint8_t addr, uint8_t reg, uint8_t data);
|
||||
};
|
||||
|
||||
#endif
|
||||
16
libraries/M5Unit-ENV/src/M5UnitENV.h
Normal file
16
libraries/M5Unit-ENV/src/M5UnitENV.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#if defined(M5_UNIT_UNIFIED_ENV_HPP)
|
||||
#error "DO NOT USE it at the same time as M5UnitUnified libraries"
|
||||
#endif
|
||||
|
||||
#ifndef _M5_UNIT_ENV_H_
|
||||
#define _M5_UNIT_ENV_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "DHT12.h"
|
||||
#include "QMP6988.h"
|
||||
#include "SHT3X.h"
|
||||
#include "SHT4X.h"
|
||||
#include "BMP280.h"
|
||||
#include "SCD4X.h"
|
||||
|
||||
#endif
|
||||
17
libraries/M5Unit-ENV/src/M5UnitUnifiedENV.h
Normal file
17
libraries/M5Unit-ENV/src/M5UnitUnifiedENV.h
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file M5UnitUnifiedENV.h
|
||||
@brief Main header of M5UnitENV using M5UnitUnfied
|
||||
*/
|
||||
#ifndef M5_UNIT_UNIFIED_ENV_H
|
||||
#define M5_UNIT_UNIFIED_ENV_H
|
||||
#ifdef __cplusplus
|
||||
#include "M5UnitUnifiedENV.hpp"
|
||||
#else
|
||||
#error M5UnitUnifiedENV requires a C++ compiler, please change file extension to .cc or .cpp
|
||||
#endif
|
||||
#endif
|
||||
55
libraries/M5Unit-ENV/src/M5UnitUnifiedENV.hpp
Normal file
55
libraries/M5Unit-ENV/src/M5UnitUnifiedENV.hpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file M5UnitUnifiedENV.hpp
|
||||
@brief Main header of M5UnitENV using M5UnitUnified
|
||||
|
||||
@mainpage M5Unit-ENV
|
||||
Library for UnitENV using M5UnitUnified.
|
||||
*/
|
||||
#if defined(_M5_UNIT_ENV_H_)
|
||||
#error "DO NOT USE it at the same time as conventional libraries"
|
||||
#endif
|
||||
|
||||
#ifndef M5_UNIT_UNIFIED_ENV_HPP
|
||||
#define M5_UNIT_UNIFIED_ENV_HPP
|
||||
|
||||
// CO2
|
||||
#include "unit/unit_SCD40.hpp"
|
||||
#include "unit/unit_SCD41.hpp"
|
||||
// ENVIII
|
||||
#include "unit/unit_SHT30.hpp"
|
||||
#include "unit/unit_QMP6988.hpp"
|
||||
#include "unit/unit_ENV3.hpp"
|
||||
// ENVPro
|
||||
#include "unit/unit_BME688.hpp"
|
||||
// TVOC
|
||||
#include "unit/unit_SGP30.hpp"
|
||||
// ENVIV
|
||||
#include "unit/unit_SHT40.hpp"
|
||||
#include "unit/unit_BMP280.hpp"
|
||||
#include "unit/unit_ENV4.hpp"
|
||||
|
||||
/*!
|
||||
@namespace m5
|
||||
@brief Top level namespace of M5stack
|
||||
*/
|
||||
namespace m5 {
|
||||
|
||||
/*!
|
||||
@namespace unit
|
||||
@brief Unit-related namespace
|
||||
*/
|
||||
namespace unit {
|
||||
|
||||
using UnitCO2 = m5::unit::UnitSCD40;
|
||||
using UnitCO2L = m5::unit::UnitSCD41;
|
||||
using UnitENVPro = m5::unit::UnitBME688;
|
||||
using UnitTVOC = m5::unit::UnitSGP30;
|
||||
|
||||
} // namespace unit
|
||||
} // namespace m5
|
||||
#endif
|
||||
353
libraries/M5Unit-ENV/src/QMP6988.cpp
Normal file
353
libraries/M5Unit-ENV/src/QMP6988.cpp
Normal file
|
|
@ -0,0 +1,353 @@
|
|||
#include <math.h>
|
||||
#include "stdint.h"
|
||||
#include "stdio.h"
|
||||
#include "QMP6988.h"
|
||||
|
||||
// DISABLE LOG
|
||||
#define QMP6988_LOG(format...)
|
||||
#define QMP6988_ERR(format...)
|
||||
|
||||
// ENABLE LOG
|
||||
// #define QMP6988_LOG Serial.printf
|
||||
// #define QMP6988_ERR Serial.printf
|
||||
|
||||
int QMP6988::getCalibrationData() {
|
||||
int status = 0;
|
||||
// BITFIELDS temp_COE;
|
||||
uint8_t a_data_uint8_tr[QMP6988_CALIBRATION_DATA_LENGTH] = {0};
|
||||
int len;
|
||||
|
||||
for (len = 0; len < QMP6988_CALIBRATION_DATA_LENGTH; len += 1) {
|
||||
status = _i2c.readBytes(_addr, QMP6988_CALIBRATION_DATA_START + len,
|
||||
&a_data_uint8_tr[len], 1);
|
||||
if (status == 0) {
|
||||
QMP6988_LOG("qmp6988 read 0xA0 error!");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
qmp6988.qmp6988_cali.COE_a0 =
|
||||
(QMP6988_S32_t)(((a_data_uint8_tr[18] << SHIFT_LEFT_12_POSITION) |
|
||||
(a_data_uint8_tr[19] << SHIFT_LEFT_4_POSITION) |
|
||||
(a_data_uint8_tr[24] & 0x0f))
|
||||
<< 12);
|
||||
qmp6988.qmp6988_cali.COE_a0 = qmp6988.qmp6988_cali.COE_a0 >> 12;
|
||||
|
||||
qmp6988.qmp6988_cali.COE_a1 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[20]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[21]);
|
||||
qmp6988.qmp6988_cali.COE_a2 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[22]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[23]);
|
||||
|
||||
qmp6988.qmp6988_cali.COE_b00 =
|
||||
(QMP6988_S32_t)(((a_data_uint8_tr[0] << SHIFT_LEFT_12_POSITION) |
|
||||
(a_data_uint8_tr[1] << SHIFT_LEFT_4_POSITION) |
|
||||
((a_data_uint8_tr[24] & 0xf0) >>
|
||||
SHIFT_RIGHT_4_POSITION))
|
||||
<< 12);
|
||||
qmp6988.qmp6988_cali.COE_b00 = qmp6988.qmp6988_cali.COE_b00 >> 12;
|
||||
|
||||
qmp6988.qmp6988_cali.COE_bt1 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[2]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[3]);
|
||||
qmp6988.qmp6988_cali.COE_bt2 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[4]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[5]);
|
||||
qmp6988.qmp6988_cali.COE_bp1 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[6]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[7]);
|
||||
qmp6988.qmp6988_cali.COE_b11 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[8]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[9]);
|
||||
qmp6988.qmp6988_cali.COE_bp2 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[10]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[11]);
|
||||
qmp6988.qmp6988_cali.COE_b12 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[12]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[13]);
|
||||
qmp6988.qmp6988_cali.COE_b21 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[14]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[15]);
|
||||
qmp6988.qmp6988_cali.COE_bp3 =
|
||||
(QMP6988_S16_t)(((a_data_uint8_tr[16]) << SHIFT_LEFT_8_POSITION) |
|
||||
a_data_uint8_tr[17]);
|
||||
|
||||
QMP6988_LOG("<-----------calibration data-------------->\r\n");
|
||||
QMP6988_LOG("COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\r\n",
|
||||
qmp6988.qmp6988_cali.COE_a0, qmp6988.qmp6988_cali.COE_a1,
|
||||
qmp6988.qmp6988_cali.COE_a2, qmp6988.qmp6988_cali.COE_b00);
|
||||
QMP6988_LOG("COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\r\n",
|
||||
qmp6988.qmp6988_cali.COE_bt1, qmp6988.qmp6988_cali.COE_bt2,
|
||||
qmp6988.qmp6988_cali.COE_bp1, qmp6988.qmp6988_cali.COE_b11);
|
||||
QMP6988_LOG("COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]\r\n",
|
||||
qmp6988.qmp6988_cali.COE_bp2, qmp6988.qmp6988_cali.COE_b12,
|
||||
qmp6988.qmp6988_cali.COE_b21, qmp6988.qmp6988_cali.COE_bp3);
|
||||
QMP6988_LOG("<-----------calibration data-------------->\r\n");
|
||||
|
||||
qmp6988.ik.a0 = qmp6988.qmp6988_cali.COE_a0; // 20Q4
|
||||
qmp6988.ik.b00 = qmp6988.qmp6988_cali.COE_b00; // 20Q4
|
||||
|
||||
qmp6988.ik.a1 = 3608L * (QMP6988_S32_t)qmp6988.qmp6988_cali.COE_a1 -
|
||||
1731677965L; // 31Q23
|
||||
qmp6988.ik.a2 = 16889L * (QMP6988_S32_t)qmp6988.qmp6988_cali.COE_a2 -
|
||||
87619360L; // 30Q47
|
||||
|
||||
qmp6988.ik.bt1 = 2982L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_bt1 +
|
||||
107370906L; // 28Q15
|
||||
qmp6988.ik.bt2 = 329854L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_bt2 +
|
||||
108083093L; // 34Q38
|
||||
qmp6988.ik.bp1 = 19923L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_bp1 +
|
||||
1133836764L; // 31Q20
|
||||
qmp6988.ik.b11 = 2406L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_b11 +
|
||||
118215883L; // 28Q34
|
||||
qmp6988.ik.bp2 = 3079L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_bp2 -
|
||||
181579595L; // 29Q43
|
||||
qmp6988.ik.b12 = 6846L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_b12 +
|
||||
85590281L; // 29Q53
|
||||
qmp6988.ik.b21 = 13836L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_b21 +
|
||||
79333336L; // 29Q60
|
||||
qmp6988.ik.bp3 = 2915L * (QMP6988_S64_t)qmp6988.qmp6988_cali.COE_bp3 +
|
||||
157155561L; // 28Q65
|
||||
QMP6988_LOG("<----------- int calibration data -------------->\r\n");
|
||||
QMP6988_LOG("a0[%d] a1[%d] a2[%d] b00[%d]\r\n", qmp6988.ik.a0,
|
||||
qmp6988.ik.a1, qmp6988.ik.a2, qmp6988.ik.b00);
|
||||
QMP6988_LOG("bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\r\n",
|
||||
qmp6988.ik.bt1, qmp6988.ik.bt2, qmp6988.ik.bp1, qmp6988.ik.b11);
|
||||
QMP6988_LOG("bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]\r\n",
|
||||
qmp6988.ik.bp2, qmp6988.ik.b12, qmp6988.ik.b21, qmp6988.ik.bp3);
|
||||
QMP6988_LOG("<----------- int calibration data -------------->\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
QMP6988_S16_t QMP6988::convTx02e(qmp6988_ik_data_t* ik, QMP6988_S32_t dt) {
|
||||
QMP6988_S16_t ret;
|
||||
QMP6988_S64_t wk1, wk2;
|
||||
|
||||
// wk1: 60Q4 // bit size
|
||||
wk1 = ((QMP6988_S64_t)ik->a1 * (QMP6988_S64_t)dt); // 31Q23+24-1=54 (54Q23)
|
||||
wk2 = ((QMP6988_S64_t)ik->a2 * (QMP6988_S64_t)dt) >>
|
||||
14; // 30Q47+24-1=53 (39Q33)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dt) >> 10; // 39Q33+24-1=62 (52Q23)
|
||||
wk2 = ((wk1 + wk2) / 32767) >> 19; // 54,52->55Q23 (20Q04)
|
||||
ret = (QMP6988_S16_t)((ik->a0 + wk2) >> 4); // 21Q4 -> 17Q0
|
||||
return ret;
|
||||
}
|
||||
|
||||
QMP6988_S32_t QMP6988::getPressure02e(qmp6988_ik_data_t* ik, QMP6988_S32_t dp,
|
||||
QMP6988_S16_t tx) {
|
||||
QMP6988_S32_t ret;
|
||||
QMP6988_S64_t wk1, wk2, wk3;
|
||||
|
||||
// wk1 = 48Q16 // bit size
|
||||
wk1 =
|
||||
((QMP6988_S64_t)ik->bt1 * (QMP6988_S64_t)tx); // 28Q15+16-1=43 (43Q15)
|
||||
wk2 = ((QMP6988_S64_t)ik->bp1 * (QMP6988_S64_t)dp) >>
|
||||
5; // 31Q20+24-1=54 (49Q15)
|
||||
wk1 += wk2; // 43,49->50Q15
|
||||
wk2 = ((QMP6988_S64_t)ik->bt2 * (QMP6988_S64_t)tx) >>
|
||||
1; // 34Q38+16-1=49 (48Q37)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)tx) >> 8; // 48Q37+16-1=63 (55Q29)
|
||||
wk3 = wk2; // 55Q29
|
||||
wk2 = ((QMP6988_S64_t)ik->b11 * (QMP6988_S64_t)tx) >>
|
||||
4; // 28Q34+16-1=43 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 55,61->62Q29
|
||||
wk2 = ((QMP6988_S64_t)ik->bp2 * (QMP6988_S64_t)dp) >>
|
||||
13; // 29Q43+24-1=52 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 1; // 39Q30+24-1=62 (61Q29)
|
||||
wk3 += wk2; // 62,61->63Q29
|
||||
wk1 += wk3 >> 14; // Q29 >> 14 -> Q15
|
||||
wk2 =
|
||||
((QMP6988_S64_t)ik->b12 * (QMP6988_S64_t)tx); // 29Q53+16-1=45 (45Q53)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)tx) >> 22; // 45Q53+16-1=61 (39Q31)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 1; // 39Q31+24-1=62 (61Q30)
|
||||
wk3 = wk2; // 61Q30
|
||||
wk2 = ((QMP6988_S64_t)ik->b21 * (QMP6988_S64_t)tx) >>
|
||||
6; // 29Q60+16-1=45 (39Q54)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 23; // 39Q54+24-1=62 (39Q31)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 1; // 39Q31+24-1=62 (61Q20)
|
||||
wk3 += wk2; // 61,61->62Q30
|
||||
wk2 = ((QMP6988_S64_t)ik->bp3 * (QMP6988_S64_t)dp) >>
|
||||
12; // 28Q65+24-1=51 (39Q53)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp) >> 23; // 39Q53+24-1=62 (39Q30)
|
||||
wk2 = (wk2 * (QMP6988_S64_t)dp); // 39Q30+24-1=62 (62Q30)
|
||||
wk3 += wk2; // 62,62->63Q30
|
||||
wk1 += wk3 >> 15; // Q30 >> 15 = Q15
|
||||
wk1 /= 32767L;
|
||||
wk1 >>= 11; // Q15 >> 7 = Q4
|
||||
wk1 += ik->b00; // Q4 + 20Q4
|
||||
// wk1 >>= 4; // 28Q4 -> 24Q0
|
||||
ret = (QMP6988_S32_t)wk1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void QMP6988::reset() {
|
||||
uint8_t ret = 0;
|
||||
|
||||
ret = _i2c.writeByte(_addr, QMP6988_RESET_REG, 0xe6);
|
||||
if (ret == 0) {
|
||||
QMP6988_LOG("reset fail!!! \r\n");
|
||||
}
|
||||
delay(20);
|
||||
ret = _i2c.writeByte(_addr, QMP6988_RESET_REG, 0x00);
|
||||
}
|
||||
|
||||
void QMP6988::setpPowermode(int power_mode) {
|
||||
uint8_t data;
|
||||
|
||||
QMP6988_LOG("qmp_set_powermode %d \r\n", power_mode);
|
||||
|
||||
qmp6988.power_mode = power_mode;
|
||||
_i2c.readBytes(_addr, QMP6988_CTRLMEAS_REG, &data, 1);
|
||||
data = data & 0xfc;
|
||||
if (power_mode == QMP6988_SLEEP_MODE) {
|
||||
data |= 0x00;
|
||||
} else if (power_mode == QMP6988_FORCED_MODE) {
|
||||
data |= 0x01;
|
||||
} else if (power_mode == QMP6988_NORMAL_MODE) {
|
||||
data |= 0x03;
|
||||
}
|
||||
_i2c.writeByte(_addr, QMP6988_CTRLMEAS_REG, data);
|
||||
|
||||
QMP6988_LOG("qmp_set_powermode 0xf4=0x%x \r\n", data);
|
||||
|
||||
delay(20);
|
||||
}
|
||||
|
||||
void QMP6988::setFilter(unsigned char filter) {
|
||||
uint8_t data;
|
||||
|
||||
data = (filter & 0x03);
|
||||
_i2c.writeByte(_addr, QMP6988_CONFIG_REG, data);
|
||||
|
||||
delay(20);
|
||||
}
|
||||
|
||||
void QMP6988::setOversamplingP(unsigned char oversampling_p) {
|
||||
uint8_t data;
|
||||
|
||||
_i2c.readBytes(_addr, QMP6988_CTRLMEAS_REG, &data, 1);
|
||||
data &= 0xe3;
|
||||
data |= (oversampling_p << 2);
|
||||
_i2c.writeByte(_addr, QMP6988_CTRLMEAS_REG, data);
|
||||
delay(20);
|
||||
}
|
||||
|
||||
void QMP6988::setOversamplingT(unsigned char oversampling_t) {
|
||||
uint8_t data;
|
||||
|
||||
_i2c.readBytes(_addr, QMP6988_CTRLMEAS_REG, &data, 1);
|
||||
data &= 0x1f;
|
||||
data |= (oversampling_t << 5);
|
||||
_i2c.writeByte(_addr, QMP6988_CTRLMEAS_REG, data);
|
||||
delay(20);
|
||||
}
|
||||
|
||||
float QMP6988::calcAltitude(float pressure, float temp) {
|
||||
float altitude;
|
||||
|
||||
altitude =
|
||||
(pow((101325 / pressure), 1 / 5.257) - 1) * (temp + 273.15) / 0.0065;
|
||||
QMP6988_LOG("altitude = %f\r\n", altitude);
|
||||
return altitude;
|
||||
}
|
||||
|
||||
float QMP6988::calcPressure() {
|
||||
uint8_t err = 0;
|
||||
QMP6988_U32_t P_read, T_read;
|
||||
QMP6988_S32_t P_raw, T_raw;
|
||||
uint8_t a_data_uint8_tr[6] = {0};
|
||||
QMP6988_S32_t T_int, P_int;
|
||||
|
||||
// press
|
||||
err = _i2c.readBytes(_addr, QMP6988_PRESSURE_MSB_REG, a_data_uint8_tr, 6);
|
||||
if (err == 0) {
|
||||
QMP6988_LOG("qmp6988 read press raw error! \r\n");
|
||||
return 0.0f;
|
||||
}
|
||||
P_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[0]))
|
||||
<< SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t)(a_data_uint8_tr[1]))
|
||||
<< SHIFT_LEFT_8_POSITION) |
|
||||
(a_data_uint8_tr[2]));
|
||||
P_raw = (QMP6988_S32_t)(P_read - SUBTRACTOR);
|
||||
|
||||
T_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[3]))
|
||||
<< SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t)(a_data_uint8_tr[4]))
|
||||
<< SHIFT_LEFT_8_POSITION) |
|
||||
(a_data_uint8_tr[5]));
|
||||
T_raw = (QMP6988_S32_t)(T_read - SUBTRACTOR);
|
||||
|
||||
T_int = convTx02e(&(qmp6988.ik), T_raw);
|
||||
P_int = getPressure02e(&(qmp6988.ik), P_raw, T_int);
|
||||
qmp6988.temperature = (float)T_int / 256.0f;
|
||||
qmp6988.pressure = (float)P_int / 16.0f;
|
||||
|
||||
return qmp6988.pressure;
|
||||
}
|
||||
|
||||
float QMP6988::calcTemperature() {
|
||||
uint8_t err = 0;
|
||||
QMP6988_U32_t P_read, T_read;
|
||||
QMP6988_S32_t P_raw, T_raw;
|
||||
uint8_t a_data_uint8_tr[6] = {0};
|
||||
QMP6988_S32_t T_int, P_int;
|
||||
|
||||
// press
|
||||
err = _i2c.readBytes(_addr, QMP6988_PRESSURE_MSB_REG, a_data_uint8_tr, 6);
|
||||
if (err == 0) {
|
||||
QMP6988_LOG("qmp6988 read press raw error! \r\n");
|
||||
return 0.0f;
|
||||
}
|
||||
P_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[0]))
|
||||
<< SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t)(a_data_uint8_tr[1]))
|
||||
<< SHIFT_LEFT_8_POSITION) |
|
||||
(a_data_uint8_tr[2]));
|
||||
P_raw = (QMP6988_S32_t)(P_read - SUBTRACTOR);
|
||||
|
||||
// temp
|
||||
err =
|
||||
_i2c.readBytes(_addr, QMP6988_TEMPERATURE_MSB_REG, a_data_uint8_tr, 3);
|
||||
if (err == 0) {
|
||||
QMP6988_LOG("qmp6988 read temp raw error! \n");
|
||||
}
|
||||
T_read = (QMP6988_U32_t)((((QMP6988_U32_t)(a_data_uint8_tr[3]))
|
||||
<< SHIFT_LEFT_16_POSITION) |
|
||||
(((QMP6988_U16_t)(a_data_uint8_tr[4]))
|
||||
<< SHIFT_LEFT_8_POSITION) |
|
||||
(a_data_uint8_tr[5]));
|
||||
T_raw = (QMP6988_S32_t)(T_read - SUBTRACTOR);
|
||||
|
||||
T_int = convTx02e(&(qmp6988.ik), T_raw);
|
||||
P_int = getPressure02e(&(qmp6988.ik), P_raw, T_int);
|
||||
qmp6988.temperature = (float)T_int / 256.0f;
|
||||
qmp6988.pressure = (float)P_int / 16.0f;
|
||||
|
||||
return qmp6988.temperature;
|
||||
}
|
||||
|
||||
bool QMP6988::begin(TwoWire* wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
if (!_i2c.exist(_addr)) {
|
||||
return false;
|
||||
}
|
||||
reset();
|
||||
getCalibrationData();
|
||||
setpPowermode(QMP6988_NORMAL_MODE);
|
||||
setFilter(QMP6988_FILTERCOEFF_4);
|
||||
setOversamplingP(QMP6988_OVERSAMPLING_8X);
|
||||
setOversamplingT(QMP6988_OVERSAMPLING_1X);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QMP6988::update() {
|
||||
pressure = calcPressure();
|
||||
cTemp = calcTemperature();
|
||||
altitude = calcAltitude(pressure, cTemp);
|
||||
return true;
|
||||
}
|
||||
153
libraries/M5Unit-ENV/src/QMP6988.h
Normal file
153
libraries/M5Unit-ENV/src/QMP6988.h
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
#ifndef __QMP6988_H
|
||||
#define __QMP6988_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Wire.h"
|
||||
#include "I2C_Class.h"
|
||||
|
||||
#define QMP6988_SLAVE_ADDRESS_L (0x70)
|
||||
#define QMP6988_SLAVE_ADDRESS_H (0x56)
|
||||
|
||||
#define QMP6988_U16_t unsigned short
|
||||
#define QMP6988_S16_t short
|
||||
#define QMP6988_U32_t unsigned int
|
||||
#define QMP6988_S32_t int
|
||||
#define QMP6988_U64_t unsigned long long
|
||||
#define QMP6988_S64_t long long
|
||||
|
||||
#define QMP6988_CHIP_ID 0x5C
|
||||
|
||||
#define QMP6988_CHIP_ID_REG 0xD1
|
||||
#define QMP6988_RESET_REG 0xE0 /* Device reset register */
|
||||
#define QMP6988_DEVICE_STAT_REG 0xF3 /* Device state register */
|
||||
#define QMP6988_CTRLMEAS_REG 0xF4 /* Measurement Condition Control Register */
|
||||
/* data */
|
||||
#define QMP6988_PRESSURE_MSB_REG 0xF7 /* Pressure MSB Register */
|
||||
#define QMP6988_TEMPERATURE_MSB_REG 0xFA /* Temperature MSB Reg */
|
||||
|
||||
/* compensation calculation */
|
||||
#define QMP6988_CALIBRATION_DATA_START \
|
||||
0xA0 /* QMP6988 compensation coefficients */
|
||||
#define QMP6988_CALIBRATION_DATA_LENGTH 25
|
||||
|
||||
#define SHIFT_RIGHT_4_POSITION 4
|
||||
#define SHIFT_LEFT_2_POSITION 2
|
||||
#define SHIFT_LEFT_4_POSITION 4
|
||||
#define SHIFT_LEFT_5_POSITION 5
|
||||
#define SHIFT_LEFT_8_POSITION 8
|
||||
#define SHIFT_LEFT_12_POSITION 12
|
||||
#define SHIFT_LEFT_16_POSITION 16
|
||||
|
||||
/* power mode */
|
||||
#define QMP6988_SLEEP_MODE 0x00
|
||||
#define QMP6988_FORCED_MODE 0x01
|
||||
#define QMP6988_NORMAL_MODE 0x03
|
||||
|
||||
#define QMP6988_CTRLMEAS_REG_MODE__POS 0
|
||||
#define QMP6988_CTRLMEAS_REG_MODE__MSK 0x03
|
||||
#define QMP6988_CTRLMEAS_REG_MODE__LEN 2
|
||||
|
||||
/* oversampling */
|
||||
#define QMP6988_OVERSAMPLING_SKIPPED 0x00
|
||||
#define QMP6988_OVERSAMPLING_1X 0x01
|
||||
#define QMP6988_OVERSAMPLING_2X 0x02
|
||||
#define QMP6988_OVERSAMPLING_4X 0x03
|
||||
#define QMP6988_OVERSAMPLING_8X 0x04
|
||||
#define QMP6988_OVERSAMPLING_16X 0x05
|
||||
#define QMP6988_OVERSAMPLING_32X 0x06
|
||||
#define QMP6988_OVERSAMPLING_64X 0x07
|
||||
|
||||
#define QMP6988_CTRLMEAS_REG_OSRST__POS 5
|
||||
#define QMP6988_CTRLMEAS_REG_OSRST__MSK 0xE0
|
||||
#define QMP6988_CTRLMEAS_REG_OSRST__LEN 3
|
||||
|
||||
#define QMP6988_CTRLMEAS_REG_OSRSP__POS 2
|
||||
#define QMP6988_CTRLMEAS_REG_OSRSP__MSK 0x1C
|
||||
#define QMP6988_CTRLMEAS_REG_OSRSP__LEN 3
|
||||
|
||||
/* filter */
|
||||
#define QMP6988_FILTERCOEFF_OFF 0x00
|
||||
#define QMP6988_FILTERCOEFF_2 0x01
|
||||
#define QMP6988_FILTERCOEFF_4 0x02
|
||||
#define QMP6988_FILTERCOEFF_8 0x03
|
||||
#define QMP6988_FILTERCOEFF_16 0x04
|
||||
#define QMP6988_FILTERCOEFF_32 0x05
|
||||
|
||||
#define QMP6988_CONFIG_REG 0xF1 /*IIR filter co-efficient setting Register*/
|
||||
#define QMP6988_CONFIG_REG_FILTER__POS 0
|
||||
#define QMP6988_CONFIG_REG_FILTER__MSK 0x07
|
||||
#define QMP6988_CONFIG_REG_FILTER__LEN 3
|
||||
|
||||
#define SUBTRACTOR 8388608
|
||||
|
||||
typedef struct _qmp6988_cali_data {
|
||||
QMP6988_S32_t COE_a0;
|
||||
QMP6988_S16_t COE_a1;
|
||||
QMP6988_S16_t COE_a2;
|
||||
QMP6988_S32_t COE_b00;
|
||||
QMP6988_S16_t COE_bt1;
|
||||
QMP6988_S16_t COE_bt2;
|
||||
QMP6988_S16_t COE_bp1;
|
||||
QMP6988_S16_t COE_b11;
|
||||
QMP6988_S16_t COE_bp2;
|
||||
QMP6988_S16_t COE_b12;
|
||||
QMP6988_S16_t COE_b21;
|
||||
QMP6988_S16_t COE_bp3;
|
||||
} qmp6988_cali_data_t;
|
||||
|
||||
typedef struct _qmp6988_fk_data {
|
||||
float a0, b00;
|
||||
float a1, a2, bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||
} qmp6988_fk_data_t;
|
||||
|
||||
typedef struct _qmp6988_ik_data {
|
||||
QMP6988_S32_t a0, b00;
|
||||
QMP6988_S32_t a1, a2;
|
||||
QMP6988_S64_t bt1, bt2, bp1, b11, bp2, b12, b21, bp3;
|
||||
} qmp6988_ik_data_t;
|
||||
|
||||
typedef struct _qmp6988_data {
|
||||
uint8_t slave;
|
||||
uint8_t chip_id;
|
||||
uint8_t power_mode;
|
||||
float temperature;
|
||||
float pressure;
|
||||
float altitude;
|
||||
qmp6988_cali_data_t qmp6988_cali;
|
||||
qmp6988_ik_data_t ik;
|
||||
} qmp6988_data_t;
|
||||
|
||||
class QMP6988 {
|
||||
private:
|
||||
qmp6988_data_t qmp6988;
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
|
||||
// read calibration data from otp
|
||||
int getCalibrationData();
|
||||
QMP6988_S32_t getPressure02e(qmp6988_ik_data_t* ik, QMP6988_S32_t dp,
|
||||
QMP6988_S16_t tx);
|
||||
QMP6988_S16_t convTx02e(qmp6988_ik_data_t* ik, QMP6988_S32_t dt);
|
||||
|
||||
void reset();
|
||||
|
||||
public:
|
||||
bool begin(TwoWire* wire = &Wire, uint8_t addr = QMP6988_SLAVE_ADDRESS_H,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U);
|
||||
bool update();
|
||||
|
||||
float pressure = 0;
|
||||
float cTemp = 0;
|
||||
float altitude = 0;
|
||||
|
||||
float calcAltitude(float pressure, float temp);
|
||||
float calcPressure();
|
||||
float calcTemperature();
|
||||
|
||||
void setpPowermode(int power_mode);
|
||||
void setFilter(unsigned char filter);
|
||||
void setOversamplingP(unsigned char oversampling_p);
|
||||
void setOversamplingT(unsigned char oversampling_t);
|
||||
};
|
||||
|
||||
#endif
|
||||
793
libraries/M5Unit-ENV/src/SCD4X.cpp
Normal file
793
libraries/M5Unit-ENV/src/SCD4X.cpp
Normal file
|
|
@ -0,0 +1,793 @@
|
|||
/*
|
||||
This is a library written for the SCD4X family of CO2 sensors
|
||||
SparkFun sells these at its website: www.sparkfun.com
|
||||
Do you like this library? Help support SparkFun. Buy a board!
|
||||
https://www.sparkfun.com/products/18365
|
||||
|
||||
Written by Paul Clark @ SparkFun Electronics, June 2nd, 2021
|
||||
|
||||
The SCD41 measures CO2 from 400ppm to 5000ppm with an accuracy of +/- 40ppm +
|
||||
5% of reading
|
||||
|
||||
This library handles the initialization of the SCD4X and outputs
|
||||
CO2 levels, relative humidty, and temperature.
|
||||
|
||||
https://github.com/sparkfun/SparkFun_SCD4x_Arduino_Library
|
||||
|
||||
Development environment specifics:
|
||||
Arduino IDE 1.8.13
|
||||
|
||||
SparkFun code, firmware, and software is released under the MIT License.
|
||||
Please see LICENSE.md for more details.
|
||||
*/
|
||||
|
||||
#include "SCD4X.h"
|
||||
|
||||
SCD4X::SCD4X(scd4x_sensor_type_e sensorType) {
|
||||
// Constructor
|
||||
_sensorType = sensorType;
|
||||
}
|
||||
|
||||
bool SCD4X::begin(TwoWire *wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq, bool measBegin, bool autoCalibrate,
|
||||
bool skipStopPeriodicMeasurements,
|
||||
bool pollAndSetDeviceType) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
_wire = wire;
|
||||
|
||||
if (!_i2c.exist(_addr)) {
|
||||
return false;
|
||||
}
|
||||
bool success = true;
|
||||
|
||||
// If periodic measurements are already running, getSerialNumber will
|
||||
// fail... To be safe, let's stop period measurements before we do anything
|
||||
// else The user can override this by setting skipStopPeriodicMeasurements
|
||||
// to true
|
||||
if (skipStopPeriodicMeasurements == false)
|
||||
success &= stopPeriodicMeasurement(); // Delays for 500ms...
|
||||
|
||||
char serialNumber[13]; // Serial number is 12 digits plus trailing NULL
|
||||
success &= getSerialNumber(serialNumber); // Read the serial number. Return
|
||||
// false if the CRC check fails.
|
||||
if (pollAndSetDeviceType == true) {
|
||||
scd4x_sensor_type_e sensorType;
|
||||
success &= getFeatureSetVersion(&sensorType);
|
||||
|
||||
setSensorType(sensorType);
|
||||
}
|
||||
|
||||
if (autoCalibrate ==
|
||||
true) // Must be done before periodic measurements are started
|
||||
{
|
||||
success &= setAutomaticSelfCalibrationEnabled(true);
|
||||
success &= (getAutomaticSelfCalibrationEnabled() == true);
|
||||
} else {
|
||||
success &= setAutomaticSelfCalibrationEnabled(false);
|
||||
success &= (getAutomaticSelfCalibrationEnabled() == false);
|
||||
}
|
||||
|
||||
if (measBegin == true) {
|
||||
success &= startPeriodicMeasurement();
|
||||
}
|
||||
|
||||
return (success);
|
||||
}
|
||||
|
||||
bool SCD4X::update() {
|
||||
return readMeasurement();
|
||||
}
|
||||
// Start periodic measurements. See 3.5.1
|
||||
// signal update interval is 5 seconds.
|
||||
bool SCD4X::startPeriodicMeasurement(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (true); // Maybe this should be false?
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_START_PERIODIC_MEASUREMENT);
|
||||
if (success) periodicMeasurementsAreRunning = true;
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Stop periodic measurements. See 3.5.3
|
||||
// Stop periodic measurement to change the sensor configuration or to save
|
||||
// power. Note that the sensor will only respond to other commands after waiting
|
||||
// 500 ms after issuing the stop_periodic_measurement command.
|
||||
|
||||
bool SCD4X::stopPeriodicMeasurement(uint16_t delayMillis, TwoWire &wirePort)
|
||||
|
||||
{
|
||||
uint8_t i2cResult;
|
||||
if (_wire != NULL) // If the sensor has been begun (_wire is not
|
||||
// NULL) then _wire is used
|
||||
{
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT >> 8); // MSB
|
||||
_wire->write(SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT & 0xFF); // LSB
|
||||
i2cResult = _wire->endTransmission();
|
||||
} else {
|
||||
// If the sensor has not been begun (_wire is NULL) then wirePort
|
||||
// is used (which will default to Wire)
|
||||
wirePort.beginTransmission(_addr);
|
||||
wirePort.write(SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT >> 8); // MSB
|
||||
wirePort.write(SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT & 0xFF); // LSB
|
||||
i2cResult = wirePort.endTransmission();
|
||||
}
|
||||
|
||||
if (i2cResult == 0) {
|
||||
periodicMeasurementsAreRunning = false;
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Get 9 bytes from SCD4X. See 3.5.2
|
||||
// Updates global variables with floats
|
||||
// Returns true if data is read successfully
|
||||
// Read sensor output. The measurement data can only be read out once per
|
||||
// signal update interval as the buffer is emptied upon read-out. If no data
|
||||
// is available in the buffer, the sensor returns a NACK. To avoid a NACK
|
||||
// response, the get_data_ready_status can be issued to check data status
|
||||
// (see chapter 3.8.2 for further details).
|
||||
bool SCD4X::readMeasurement(void) {
|
||||
// Verify we have data from the sensor
|
||||
if (getDataReadyStatus() == false) return (false);
|
||||
|
||||
scd4x_unsigned16Bytes_t tempCO2;
|
||||
tempCO2.unsigned16 = 0;
|
||||
scd4x_unsigned16Bytes_t tempHumidity;
|
||||
tempHumidity.unsigned16 = 0;
|
||||
scd4x_unsigned16Bytes_t tempTemperature;
|
||||
tempTemperature.unsigned16 = 0;
|
||||
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(SCD4x_COMMAND_READ_MEASUREMENT >> 8); // MSB
|
||||
_wire->write(SCD4x_COMMAND_READ_MEASUREMENT & 0xFF); // LSB
|
||||
if (_wire->endTransmission() != 0) return (false); // Sensor did not ACK
|
||||
|
||||
delay(1); // Datasheet specifies this
|
||||
|
||||
_wire->requestFrom((uint8_t)_addr, (uint8_t)9);
|
||||
bool error = false;
|
||||
if (_wire->available()) {
|
||||
byte bytesToCrc[2];
|
||||
for (byte x = 0; x < 9; x++) {
|
||||
byte incoming = _wire->read();
|
||||
|
||||
switch (x) {
|
||||
case 0:
|
||||
case 1:
|
||||
tempCO2.bytes[x == 0 ? 1 : 0] =
|
||||
incoming; // Store the two CO2 bytes in
|
||||
// little-endian format
|
||||
bytesToCrc[x] =
|
||||
incoming; // Calculate the CRC on the two CO2 bytes
|
||||
// in the order they arrive
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
tempTemperature.bytes[x == 3 ? 1 : 0] =
|
||||
incoming; // Store the two T bytes in little-endian
|
||||
// format
|
||||
bytesToCrc[x % 3] =
|
||||
incoming; // Calculate the CRC on the two T bytes
|
||||
// in the order they arrive
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
tempHumidity.bytes[x == 6 ? 1 : 0] =
|
||||
incoming; // Store the two RH bytes in
|
||||
// little-endian format
|
||||
bytesToCrc[x % 3] =
|
||||
incoming; // Calculate the CRC on the two RH bytes
|
||||
// in the order they arrive
|
||||
break;
|
||||
default: // x == 2, 5, 8
|
||||
// Validate CRC
|
||||
uint8_t foundCrc = computeCRC8(
|
||||
bytesToCrc, 2); // Calculate what the CRC should be
|
||||
// for these two bytes
|
||||
if (foundCrc != incoming) // Does this match the CRC
|
||||
// byte from the sensor?
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (false);
|
||||
}
|
||||
// Now copy the int16s into their associated floats
|
||||
co2 = (float)tempCO2.unsigned16;
|
||||
temperature = -45 + (((float)tempTemperature.unsigned16) * 175 / 65536);
|
||||
humidity = ((float)tempHumidity.unsigned16) * 100 / 65536;
|
||||
|
||||
// Mark our global variables as fresh
|
||||
co2HasBeenReported = false;
|
||||
humidityHasBeenReported = false;
|
||||
temperatureHasBeenReported = false;
|
||||
|
||||
return (true); // Success! New data available in globals.
|
||||
}
|
||||
|
||||
// Returns the latest available CO2 level
|
||||
// If the current level has already been reported, trigger a new read
|
||||
uint16_t SCD4X::getCO2(void) {
|
||||
if (co2HasBeenReported == true) // Trigger a new read
|
||||
readMeasurement(); // Pull in new co2, humidity, and temp into
|
||||
// global vars
|
||||
|
||||
co2HasBeenReported = true;
|
||||
|
||||
return (uint16_t)co2; // Cut off decimal as co2 is 0 to 10,000
|
||||
}
|
||||
|
||||
// Returns the latest available humidity
|
||||
// If the current level has already been reported, trigger a new read
|
||||
float SCD4X::getHumidity(void) {
|
||||
if (humidityHasBeenReported == true) // Trigger a new read
|
||||
readMeasurement(); // Pull in new co2, humidity, and temp into
|
||||
// global vars
|
||||
|
||||
humidityHasBeenReported = true;
|
||||
|
||||
return humidity;
|
||||
}
|
||||
|
||||
// Returns the latest available temperature
|
||||
// If the current level has already been reported, trigger a new read
|
||||
float SCD4X::getTemperature(void) {
|
||||
if (temperatureHasBeenReported == true) // Trigger a new read
|
||||
readMeasurement(); // Pull in new co2, humidity, and temp into
|
||||
// global vars
|
||||
|
||||
temperatureHasBeenReported = true;
|
||||
|
||||
return temperature;
|
||||
}
|
||||
|
||||
// Set the temperature offset (C). See 3.6.1
|
||||
// Max command duration: 1ms
|
||||
// The user can set delayMillis to zero f they want the function to return
|
||||
// immediately. The temperature offset has no influence on the SCD4X CO2
|
||||
// accuracy. Setting the temperature offset of the SCD4X inside the customer
|
||||
// device correctly allows the user to leverage the RH and T output signal.
|
||||
bool SCD4X::setTemperatureOffset(float offset, uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (offset < 0) {
|
||||
return (false);
|
||||
}
|
||||
if (offset >= 175) {
|
||||
return (false);
|
||||
}
|
||||
uint16_t offsetWord =
|
||||
(uint16_t)(offset * 65536 / 175); // Toffset [°C] * 2^16 / 175
|
||||
bool success =
|
||||
sendCommand(SCD4x_COMMAND_SET_TEMPERATURE_OFFSET, offsetWord);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Get the temperature offset. See 3.6.2
|
||||
float SCD4X::getTemperatureOffset(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (0.0);
|
||||
}
|
||||
|
||||
float offset;
|
||||
|
||||
getTemperatureOffset(&offset);
|
||||
|
||||
return (offset);
|
||||
}
|
||||
|
||||
// Get the temperature offset. See 3.6.2
|
||||
bool SCD4X::getTemperatureOffset(float *offset) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t offsetWord = 0; // offset will be zero if readRegister fails
|
||||
bool success =
|
||||
readRegister(SCD4x_COMMAND_GET_TEMPERATURE_OFFSET, &offsetWord, 1);
|
||||
*offset = ((float)offsetWord) * 175.0 / 65536.0;
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Set the sensor altitude (metres above sea level). See 3.6.3
|
||||
// Max command duration: 1ms
|
||||
// The user can set delayMillis to zero if they want the function to return
|
||||
// immediately. Reading and writing of the sensor altitude must be done
|
||||
// while the SCD4X is in idle mode. Typically, the sensor altitude is set
|
||||
// once after device installation. To save the setting to the EEPROM, the
|
||||
// persist setting (see chapter 3.9.1) command must be issued. Per default,
|
||||
// the sensor altitude is set to 0 meter above sea-level.
|
||||
bool SCD4X::setSensorAltitude(uint16_t altitude, uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_SET_SENSOR_ALTITUDE, altitude);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Get the sensor altitude. See 3.6.4
|
||||
uint16_t SCD4X::getSensorAltitude(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint16_t altitude = 0;
|
||||
|
||||
getSensorAltitude(&altitude);
|
||||
|
||||
return (altitude);
|
||||
}
|
||||
|
||||
// Get the sensor altitude. See 3.6.4
|
||||
bool SCD4X::getSensorAltitude(uint16_t *altitude) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (readRegister(SCD4x_COMMAND_GET_SENSOR_ALTITUDE, altitude, 1));
|
||||
}
|
||||
|
||||
// Set the ambient pressure (Pa). See 3.6.5
|
||||
// Max command duration: 1ms
|
||||
// The user can set delayMillis to zero if they want the function to return
|
||||
// immediately. The set_ambient_pressure command can be sent during periodic
|
||||
// measurements to enable continuous pressure compensation.
|
||||
// setAmbientPressure overrides setSensorAltitude
|
||||
bool SCD4X::setAmbientPressure(float pressure, uint16_t delayMillis) {
|
||||
if (pressure < 0) {
|
||||
return (false);
|
||||
}
|
||||
if (pressure > 6553500) {
|
||||
return (false);
|
||||
}
|
||||
uint16_t pressureWord = (uint16_t)(pressure / 100);
|
||||
bool success =
|
||||
sendCommand(SCD4x_COMMAND_SET_AMBIENT_PRESSURE, pressureWord);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Perform forced recalibration. See 3.7.1
|
||||
float SCD4X::performForcedRecalibration(uint16_t concentration) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (0.0);
|
||||
}
|
||||
|
||||
float correction = 0.0;
|
||||
|
||||
performForcedRecalibration(concentration, &correction);
|
||||
|
||||
return (correction);
|
||||
}
|
||||
|
||||
// Perform forced recalibration. See 3.7.1
|
||||
// To successfully conduct an accurate forced recalibration, the following
|
||||
// steps need to be carried out:
|
||||
// 1. Operate the SCD4X in the operation mode later used in normal sensor
|
||||
// operation (periodic measurement,
|
||||
// low power periodic measurement or single shot) for > 3 minutes in an
|
||||
// environment with homogenous and constant CO2 concentration.
|
||||
// 2. Issue stop_periodic_measurement. Wait 500 ms for the stop command to
|
||||
// complete.
|
||||
// 3. Subsequently issue the perform_forced_recalibration command and
|
||||
// optionally read out the FRC correction
|
||||
// (i.e. the magnitude of the correction) after waiting for 400 ms for
|
||||
// the command to complete.
|
||||
// A return value of 0xffff indicates that the forced recalibration has
|
||||
// failed.
|
||||
bool SCD4X::performForcedRecalibration(uint16_t concentration,
|
||||
float *correction) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t correctionWord;
|
||||
|
||||
bool success =
|
||||
sendCommand(SCD4x_COMMAND_PERFORM_FORCED_CALIBRATION, concentration);
|
||||
|
||||
if (success == false) return (false);
|
||||
|
||||
delay(400); // Datasheet specifies this
|
||||
|
||||
_wire->requestFrom((uint8_t)_addr, (uint8_t)3);
|
||||
bool error = false;
|
||||
if (_wire->available()) {
|
||||
byte bytesToCrc[2];
|
||||
bytesToCrc[0] = _wire->read();
|
||||
correctionWord = ((uint16_t)bytesToCrc[0]) << 8;
|
||||
bytesToCrc[1] = _wire->read();
|
||||
correctionWord |= (uint16_t)bytesToCrc[1];
|
||||
byte incomingCrc = _wire->read();
|
||||
uint8_t foundCrc = computeCRC8(bytesToCrc, 2);
|
||||
if (foundCrc != incomingCrc) {
|
||||
error = true;
|
||||
}
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
*correction = ((float)correctionWord) -
|
||||
32768; // FRC correction [ppm CO2] = word[0] – 0x8000
|
||||
|
||||
if (correctionWord == 0xffff) // A return value of 0xffff indicates that
|
||||
// the forced recalibration has failed
|
||||
return (false);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Enable/disable automatic self calibration. See 3.7.2
|
||||
// Set the current state (enabled / disabled) of the automatic
|
||||
// self-calibration. By default, ASC is enabled. To save the setting to the
|
||||
// EEPROM, the persist_setting (see chapter 3.9.1) command must be issued.
|
||||
bool SCD4X::setAutomaticSelfCalibrationEnabled(bool enabled,
|
||||
uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t enabledWord = enabled == true ? 0x0001 : 0x0000;
|
||||
bool success = sendCommand(
|
||||
SCD4x_COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED, enabledWord);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Check if automatic self calibration is enabled. See 3.7.3
|
||||
bool SCD4X::getAutomaticSelfCalibrationEnabled(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t enabled;
|
||||
bool success = getAutomaticSelfCalibrationEnabled(&enabled);
|
||||
if (success == false) {
|
||||
return (false);
|
||||
}
|
||||
return (enabled == 0x0001);
|
||||
}
|
||||
|
||||
// Check if automatic self calibration is enabled. See 3.7.3
|
||||
bool SCD4X::getAutomaticSelfCalibrationEnabled(uint16_t *enabled) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (readRegister(SCD4x_COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED,
|
||||
enabled, 1));
|
||||
}
|
||||
|
||||
// Start low power periodic measurements. See 3.8.1
|
||||
// Signal update interval will be 30 seconds instead of 5
|
||||
bool SCD4X::startLowPowerPeriodicMeasurement(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success =
|
||||
sendCommand(SCD4x_COMMAND_START_LOW_POWER_PERIODIC_MEASUREMENT);
|
||||
if (success) periodicMeasurementsAreRunning = true;
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Returns true when data is available. See 3.8.2
|
||||
bool SCD4X::getDataReadyStatus(void) {
|
||||
uint16_t response;
|
||||
bool success =
|
||||
readRegister(SCD4x_COMMAND_GET_DATA_READY_STATUS, &response, 1);
|
||||
|
||||
if (success == false) return (false);
|
||||
|
||||
// If the least significant 11 bits of word[0] are 0 → data not ready
|
||||
// else → data ready for read-out
|
||||
if ((response & 0x07ff) == 0x0000) return (false);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Persist settings: copy settings (e.g. temperature offset) from RAM to
|
||||
// EEPROM. See 3.9.1 Configuration settings such as the temperature offset,
|
||||
// sensor altitude and the ASC enabled/disabled parameter are by default
|
||||
// stored in the volatile memory (RAM) only and will be lost after a
|
||||
// power-cycle. The persist_settings command stores the current
|
||||
// configuration in the EEPROM of the SCD4X, making them persistent across
|
||||
// power-cycling. To avoid unnecessary wear of the EEPROM, the
|
||||
// persist_settings command should only be sent when persistence is required
|
||||
// and if actual changes to the configuration have been made. The EEPROM is
|
||||
// guaranteed to endure at least 2000 write cycles before failure.
|
||||
bool SCD4X::persistSettings(uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_PERSIST_SETTINGS);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Get 9 bytes from SCD4X. Convert 48-bit serial number to ASCII chars.
|
||||
// See 3.9.2 Returns true if serial number is read successfully Reading out
|
||||
// the serial number can be used to identify the chip and to verify the
|
||||
// presence of the sensor.
|
||||
bool SCD4X::getSerialNumber(char *serialNumber) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(SCD4x_COMMAND_GET_SERIAL_NUMBER >> 8); // MSB
|
||||
_wire->write(SCD4x_COMMAND_GET_SERIAL_NUMBER & 0xFF); // LSB
|
||||
if (_wire->endTransmission() != 0) return (false); // Sensor did not ACK
|
||||
|
||||
delay(1); // Datasheet specifies this
|
||||
|
||||
_wire->requestFrom((uint8_t)_addr, (uint8_t)9);
|
||||
bool error = false;
|
||||
if (_wire->available()) {
|
||||
byte bytesToCrc[2];
|
||||
int digit = 0;
|
||||
for (byte x = 0; x < 9; x++) {
|
||||
byte incoming = _wire->read();
|
||||
|
||||
switch (x) {
|
||||
case 0: // The serial number arrives as: two bytes, CRC,
|
||||
// two bytes, CRC, two bytes, CRC
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
case 7:
|
||||
serialNumber[digit++] = convertHexToASCII(
|
||||
incoming >> 4); // Convert each nibble to ASCII
|
||||
serialNumber[digit++] = convertHexToASCII(incoming & 0x0F);
|
||||
bytesToCrc[x % 3] = incoming;
|
||||
break;
|
||||
default: // x == 2, 5, 8
|
||||
// Validate CRC
|
||||
uint8_t foundCrc = computeCRC8(
|
||||
bytesToCrc, 2); // Calculate what the CRC should be
|
||||
// for these two bytes
|
||||
if (foundCrc != incoming) // Does this match the CRC
|
||||
// byte from the sensor?
|
||||
{
|
||||
error = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
serialNumber[digit] = 0; // NULL-terminate the string
|
||||
}
|
||||
} else {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true); // Success!
|
||||
}
|
||||
|
||||
// PRIVATE: Convert serial number digit to ASCII
|
||||
char SCD4X::convertHexToASCII(uint8_t digit) {
|
||||
if (digit <= 9)
|
||||
return (char(digit + 0x30));
|
||||
else
|
||||
return (char(digit + 0x41 - 10)); // Use upper case for A-F
|
||||
}
|
||||
|
||||
// Perform self test. Takes 10 seconds to complete. See 3.9.3
|
||||
// The perform_self_test feature can be used as an end-of-line test to check
|
||||
// sensor functionality and the customer power supply to the sensor.
|
||||
bool SCD4X::performSelfTest(void) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t response;
|
||||
|
||||
bool success =
|
||||
readRegister(SCD4x_COMMAND_PERFORM_SELF_TEST, &response, 10000);
|
||||
|
||||
return (success &&
|
||||
(response == 0x0000)); // word[0] = 0 → no malfunction detected
|
||||
}
|
||||
|
||||
// Peform factory reset. See 3.9.4
|
||||
// The perform_factory_reset command resets all configuration settings
|
||||
// stored in the EEPROM and erases the FRC and ASC algorithm history.
|
||||
bool SCD4X::performFactoryReset(uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_PERFORM_FACTORY_RESET);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Reinit. See 3.9.5
|
||||
// The reinit command reinitializes the sensor by reloading user settings
|
||||
// from EEPROM. Before sending the reinit command, the stop measurement
|
||||
// command must be issued. If the reinit command does not trigger the
|
||||
// desired re-initialization, a power-cycle should be applied to the SCD4X.
|
||||
bool SCD4X::reInit(uint16_t delayMillis) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_REINIT);
|
||||
if (delayMillis > 0) delay(delayMillis);
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Low Power Single Shot. See 3.10.1
|
||||
// In addition to periodic measurement modes, the SCD41 features a single
|
||||
// shot measurement mode, i.e. allows for on-demand measurements. The
|
||||
// typical communication sequence is as follows:
|
||||
// 1. The sensor is powered up.
|
||||
// 2. The I2C master sends a single shot command and waits for the indicated
|
||||
// max. command duration time.
|
||||
// 3. The I2C master reads out data with the read measurement sequence
|
||||
// (chapter 3.5.2).
|
||||
// 4. Steps 2-3 are repeated as required by the application.
|
||||
bool SCD4X::measureSingleShot(void) {
|
||||
if (_sensorType != SCD4x_SENSOR_SCD41) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_MEASURE_SINGLE_SHOT);
|
||||
|
||||
return (success);
|
||||
}
|
||||
|
||||
// On-demand measurement of relative humidity and temperature only.
|
||||
// The sensor output is read using the read_measurement command
|
||||
// (chapter 3.5.2). CO2 output is returned as 0 ppm.
|
||||
bool SCD4X::measureSingleShotRHTOnly(void) {
|
||||
if (_sensorType != SCD4x_SENSOR_SCD41) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
bool success = sendCommand(SCD4x_COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY);
|
||||
|
||||
return (success);
|
||||
}
|
||||
|
||||
scd4x_sensor_type_e SCD4X::getSensorType(void) {
|
||||
return _sensorType;
|
||||
}
|
||||
|
||||
void SCD4X::setSensorType(scd4x_sensor_type_e sensorType) {
|
||||
_sensorType = sensorType;
|
||||
}
|
||||
|
||||
bool SCD4X::getFeatureSetVersion(scd4x_sensor_type_e *sensorType) {
|
||||
if (periodicMeasurementsAreRunning) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
uint16_t featureSet;
|
||||
|
||||
bool success =
|
||||
readRegister(SCD4x_COMMAND_GET_FEATURE_SET_VERSION, &featureSet, 1);
|
||||
|
||||
uint8_t typeOfSensor = ((featureSet & 0x1000) >> 12);
|
||||
|
||||
if (typeOfSensor == 0) {
|
||||
*sensorType = SCD4x_SENSOR_SCD40;
|
||||
} else if (typeOfSensor == 1) {
|
||||
*sensorType = SCD4x_SENSOR_SCD41;
|
||||
} else {
|
||||
*sensorType = SCD4x_SENSOR_INVALID;
|
||||
success = false;
|
||||
}
|
||||
|
||||
return (success);
|
||||
}
|
||||
|
||||
// Sends a command along with arguments and CRC
|
||||
bool SCD4X::sendCommand(uint16_t command, uint16_t arguments) {
|
||||
uint8_t data[2];
|
||||
data[0] = arguments >> 8;
|
||||
data[1] = arguments & 0xFF;
|
||||
uint8_t crc = computeCRC8(
|
||||
data, 2); // Calc CRC on the arguments only, not the command
|
||||
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(command >> 8); // MSB
|
||||
_wire->write(command & 0xFF); // LSB
|
||||
_wire->write(arguments >> 8); // MSB
|
||||
_wire->write(arguments & 0xFF); // LSB
|
||||
_wire->write(crc);
|
||||
if (_wire->endTransmission() != 0) return (false); // Sensor did not ACK
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Sends just a command, no arguments, no CRC
|
||||
bool SCD4X::sendCommand(uint16_t command) {
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(command >> 8); // MSB
|
||||
_wire->write(command & 0xFF); // LSB
|
||||
if (_wire->endTransmission() != 0) return (false); // Sensor did not ACK
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Gets two bytes from SCD4X plus CRC.
|
||||
// Returns true if endTransmission returns zero _and_ the CRC check is valid
|
||||
bool SCD4X::readRegister(uint16_t registerAddress, uint16_t *response,
|
||||
uint16_t delayMillis) {
|
||||
_wire->beginTransmission(_addr);
|
||||
_wire->write(registerAddress >> 8); // MSB
|
||||
_wire->write(registerAddress & 0xFF); // LSB
|
||||
if (_wire->endTransmission() != 0) return (false); // Sensor did not ACK
|
||||
|
||||
delay(delayMillis);
|
||||
|
||||
_wire->requestFrom((uint8_t)_addr,
|
||||
(uint8_t)3); // Request data and CRC
|
||||
if (_wire->available()) {
|
||||
uint8_t data[2];
|
||||
data[0] = _wire->read();
|
||||
data[1] = _wire->read();
|
||||
uint8_t crc = _wire->read();
|
||||
*response = (uint16_t)data[0] << 8 | data[1];
|
||||
uint8_t expectedCRC = computeCRC8(data, 2);
|
||||
if (crc == expectedCRC) // Return true if CRC check is OK
|
||||
return (true);
|
||||
}
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Given an array and a number of bytes, this calculate CRC8 for those bytes
|
||||
// CRC is only calc'd on the data portion (two bytes) of the four bytes
|
||||
// being sent From:
|
||||
// http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html
|
||||
// Tested with: http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
|
||||
// x^8+x^5+x^4+1 = 0x31
|
||||
uint8_t SCD4X::computeCRC8(uint8_t data[], uint8_t len) {
|
||||
uint8_t crc = 0xFF; // Init with 0xFF
|
||||
|
||||
for (uint8_t x = 0; x < len; x++) {
|
||||
crc ^= data[x]; // XOR-in the next input byte
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if ((crc & 0x80) != 0)
|
||||
crc = (uint8_t)((crc << 1) ^ 0x31);
|
||||
else
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return crc; // No output reflection
|
||||
}
|
||||
233
libraries/M5Unit-ENV/src/SCD4X.h
Normal file
233
libraries/M5Unit-ENV/src/SCD4X.h
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
This is a library written for the SCD4X family of CO2 sensors
|
||||
SparkFun sells these at its website: www.sparkfun.com
|
||||
Do you like this library? Help support SparkFun. Buy a board!
|
||||
https://www.sparkfun.com/products/18365
|
||||
|
||||
Written by Paul Clark @ SparkFun Electronics, June 2nd, 2021
|
||||
Revision by Alex Brudner @ SparkFun Electronics
|
||||
|
||||
The SCD41 measures CO2 from 400ppm to 5000ppm with an accuracy of +/- 40ppm +
|
||||
5% of reading
|
||||
|
||||
This library handles the initialization of the SCD4X and outputs
|
||||
CO2 levels, relative humidty, and temperature.
|
||||
|
||||
https://github.com/sparkfun/SparkFun_SCD4x_Arduino_Library
|
||||
|
||||
Development environment specifics:
|
||||
Arduino IDE 1.8.13 and 2.1.0
|
||||
|
||||
SparkFun code, firmware, and software is released under the MIT License.
|
||||
Please see LICENSE.md for more details.
|
||||
*/
|
||||
|
||||
#ifndef __SCD4X_H__
|
||||
#define __SCD4X_H__
|
||||
|
||||
// Uncomment the next #define if using an Teensy >= 3 or Teensy LC and want to
|
||||
// use the dedicated I2C-Library for it Then you also have to include <i2c_t3.h>
|
||||
// on your application instead of <Wire.h>
|
||||
|
||||
// #define USE_TEENSY3_I2C_LIB
|
||||
|
||||
// Uncomment the next #define to EXclude any debug logging from the code, by
|
||||
// default debug logging code will be included
|
||||
|
||||
// #define SCD4x_ENABLE_DEBUGLOG 0 // OFF/disabled/excluded on demand
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "I2C_Class.h"
|
||||
|
||||
// The default I2C address for the SCD4X is 0x62.
|
||||
#define SCD4X_I2C_ADDR 0x62
|
||||
|
||||
// Available commands
|
||||
|
||||
// Basic Commands
|
||||
#define SCD4x_COMMAND_START_PERIODIC_MEASUREMENT 0x21b1
|
||||
#define SCD4x_COMMAND_READ_MEASUREMENT 0xec05 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_STOP_PERIODIC_MEASUREMENT 0x3f86 // execution time: 500ms
|
||||
|
||||
// On-chip output signal compensation
|
||||
#define SCD4x_COMMAND_SET_TEMPERATURE_OFFSET 0x241d // execution time: 1ms
|
||||
#define SCD4x_COMMAND_GET_TEMPERATURE_OFFSET 0x2318 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_SET_SENSOR_ALTITUDE 0x2427 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_GET_SENSOR_ALTITUDE 0x2322 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_SET_AMBIENT_PRESSURE 0xe000 // execution time: 1ms
|
||||
|
||||
// Field calibration
|
||||
#define SCD4x_COMMAND_PERFORM_FORCED_CALIBRATION \
|
||||
0x362f // execution time: 400ms
|
||||
#define SCD4x_COMMAND_SET_AUTOMATIC_SELF_CALIBRATION_ENABLED \
|
||||
0x2416 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_GET_AUTOMATIC_SELF_CALIBRATION_ENABLED \
|
||||
0x2313 // execution time: 1ms
|
||||
|
||||
// Low power
|
||||
#define SCD4x_COMMAND_START_LOW_POWER_PERIODIC_MEASUREMENT 0x21ac
|
||||
#define SCD4x_COMMAND_GET_DATA_READY_STATUS 0xe4b8 // execution time: 1ms
|
||||
|
||||
// Advanced features
|
||||
#define SCD4x_COMMAND_PERSIST_SETTINGS 0x3615 // execution time: 800ms
|
||||
#define SCD4x_COMMAND_GET_SERIAL_NUMBER 0x3682 // execution time: 1ms
|
||||
#define SCD4x_COMMAND_PERFORM_SELF_TEST 0x3639 // execution time: 10000ms
|
||||
#define SCD4x_COMMAND_PERFORM_FACTORY_RESET 0x3632 // execution time: 1200ms
|
||||
#define SCD4x_COMMAND_REINIT 0x3646 // execution time: 20ms
|
||||
#define SCD4x_COMMAND_GET_FEATURE_SET_VERSION 0x202F // execution time: 1ms
|
||||
|
||||
// Low power single shot - SCD41 only
|
||||
#define SCD4x_COMMAND_MEASURE_SINGLE_SHOT 0x219d // execution time: 5000ms
|
||||
#define SCD4x_COMMAND_MEASURE_SINGLE_SHOT_RHT_ONLY \
|
||||
0x2196 // execution time: 50ms
|
||||
|
||||
typedef union {
|
||||
int16_t signed16;
|
||||
uint16_t unsigned16;
|
||||
} scd4x_signedUnsigned16_t; // Avoid any ambiguity casting int16_t to uint16_t
|
||||
|
||||
typedef union {
|
||||
uint16_t unsigned16;
|
||||
uint8_t bytes[2];
|
||||
} scd4x_unsigned16Bytes_t; // Make it easy to convert 2 x uint8_t to uint16_t
|
||||
|
||||
typedef enum {
|
||||
SCD4x_SENSOR_SCD40 = 0,
|
||||
SCD4x_SENSOR_SCD41,
|
||||
SCD4x_SENSOR_INVALID
|
||||
} scd4x_sensor_type_e;
|
||||
|
||||
class SCD4X {
|
||||
private:
|
||||
TwoWire *_wire;
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
|
||||
public:
|
||||
SCD4X(scd4x_sensor_type_e sensorType = SCD4x_SENSOR_SCD40);
|
||||
|
||||
bool begin(TwoWire *wire = &Wire, uint8_t addr = SCD4X_I2C_ADDR,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U,
|
||||
bool measBegin = true, bool autoCalibrate = true,
|
||||
bool skipStopPeriodicMeasurements = false,
|
||||
bool pollAndSetDeviceType = true
|
||||
|
||||
);
|
||||
|
||||
bool update(void);
|
||||
|
||||
bool startPeriodicMeasurement(void); // Signal update interval is 5 seconds
|
||||
|
||||
// stopPeriodicMeasurement can be called before .begin if required
|
||||
// If the sensor has been begun (_i2cPort is not NULL) then _i2cPort is used
|
||||
// If the sensor has not been begun (_i2cPort is NULL) then wirePort and
|
||||
// address are used (which will default to Wire) Note that the sensor will
|
||||
// only respond to other commands after waiting 500 ms after issuing the
|
||||
// stop_periodic_measurement command.
|
||||
|
||||
bool stopPeriodicMeasurement(uint16_t delayMillis = 500,
|
||||
TwoWire &wirePort = Wire);
|
||||
|
||||
bool readMeasurement(void); // Check for fresh data; store it. Returns true
|
||||
// if fresh data is available
|
||||
|
||||
uint16_t getCO2(void); // Return the CO2 PPM. Automatically request fresh
|
||||
// data is the data is 'stale'
|
||||
float getHumidity(void); // Return the RH. Automatically request fresh data
|
||||
// is the data is 'stale'
|
||||
float getTemperature(void); // Return the temperature. Automatically
|
||||
// request fresh data is the data is 'stale'
|
||||
|
||||
// Define how warm the sensor is compared to ambient, so RH and T are
|
||||
// temperature compensated. Has no effect on the CO2 reading Default offset
|
||||
// is 4C
|
||||
bool setTemperatureOffset(
|
||||
float offset,
|
||||
uint16_t delayMillis = 1); // Returns true if I2C transfer was OK
|
||||
float getTemperatureOffset(void); // Will return zero if offset is invalid
|
||||
bool getTemperatureOffset(
|
||||
float *offset); // Returns true if offset is valid
|
||||
|
||||
// Define the sensor altitude in metres above sea level, so RH and CO2 are
|
||||
// compensated for atmospheric pressure Default altitude is 0m
|
||||
bool setSensorAltitude(uint16_t altitude, uint16_t delayMillis = 1);
|
||||
uint16_t getSensorAltitude(
|
||||
void); // Will return zero if altitude is invalid
|
||||
bool getSensorAltitude(
|
||||
uint16_t *altitude); // Returns true if altitude is valid
|
||||
|
||||
// Define the ambient pressure in Pascals, so RH and CO2 are compensated for
|
||||
// atmospheric pressure setAmbientPressure overrides setSensorAltitude
|
||||
bool setAmbientPressure(float pressure, uint16_t delayMillis = 1);
|
||||
|
||||
float performForcedRecalibration(
|
||||
uint16_t concentration); // Returns the FRC correction value
|
||||
bool performForcedRecalibration(
|
||||
uint16_t concentration,
|
||||
float *correction); // Returns true if FRC is successful
|
||||
|
||||
bool setAutomaticSelfCalibrationEnabled(bool enabled = true,
|
||||
uint16_t delayMillis = 1);
|
||||
bool getAutomaticSelfCalibrationEnabled(void);
|
||||
bool getAutomaticSelfCalibrationEnabled(uint16_t *enabled);
|
||||
|
||||
bool startLowPowerPeriodicMeasurement(
|
||||
void); // Start low power measurements - receive data every 30 seconds
|
||||
bool getDataReadyStatus(void); // Returns true if fresh data is available
|
||||
|
||||
bool persistSettings(
|
||||
uint16_t delayMillis = 800); // Copy sensor settings from RAM to EEPROM
|
||||
bool getSerialNumber(
|
||||
char *serialNumber); // Returns true if serial number is read correctly
|
||||
bool performSelfTest(void); // Takes 10 seconds to complete. Returns true
|
||||
// if the test is successful
|
||||
bool performFactoryReset(
|
||||
uint16_t delayMillis =
|
||||
1200); // Reset all settings to the factory values
|
||||
bool reInit(uint16_t delayMillis =
|
||||
20); // Re-initialize the sensor, load settings from EEPROM
|
||||
|
||||
bool measureSingleShot(void); // SCD41 only. Request a single measurement.
|
||||
// Data will be ready in 5 seconds
|
||||
bool measureSingleShotRHTOnly(void); // SCD41 only. Request RH and T data
|
||||
// only. Data will be ready in 50ms
|
||||
|
||||
bool sendCommand(uint16_t command, uint16_t arguments);
|
||||
bool sendCommand(uint16_t command);
|
||||
|
||||
bool readRegister(uint16_t registerAddress, uint16_t *response,
|
||||
uint16_t delayMillis = 1);
|
||||
|
||||
uint8_t computeCRC8(uint8_t data[], uint8_t len);
|
||||
|
||||
bool getFeatureSetVersion(scd4x_sensor_type_e *sensorType);
|
||||
scd4x_sensor_type_e getSensorType(
|
||||
void); // Get the sensor type stored in the struct.
|
||||
void setSensorType(
|
||||
scd4x_sensor_type_e sensorType); // Set the sensor type for the device.
|
||||
|
||||
private:
|
||||
// Sensor type
|
||||
scd4x_sensor_type_e _sensorType;
|
||||
|
||||
// Global main datums
|
||||
float co2 = 0;
|
||||
float temperature = 0;
|
||||
float humidity = 0;
|
||||
|
||||
// These track the staleness of the current data
|
||||
// This allows us to avoid calling readMeasurement() every time individual
|
||||
// datums are requested
|
||||
bool co2HasBeenReported = true;
|
||||
bool humidityHasBeenReported = true;
|
||||
bool temperatureHasBeenReported = true;
|
||||
|
||||
// Keep track of whether periodic measurements are in progress
|
||||
bool periodicMeasurementsAreRunning = false;
|
||||
|
||||
// Convert serial number digit to ASCII
|
||||
char convertHexToASCII(uint8_t digit);
|
||||
};
|
||||
|
||||
#endif
|
||||
43
libraries/M5Unit-ENV/src/SHT3X.cpp
Normal file
43
libraries/M5Unit-ENV/src/SHT3X.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#include "SHT3X.h"
|
||||
|
||||
bool SHT3X::begin(TwoWire* wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
_wire = wire;
|
||||
return _i2c.exist(_addr);
|
||||
}
|
||||
|
||||
bool SHT3X::update() {
|
||||
unsigned int data[6];
|
||||
|
||||
// Start I2C Transmission
|
||||
_wire->beginTransmission(_addr);
|
||||
// Send measurement command
|
||||
_wire->write(0x2C);
|
||||
_wire->write(0x06);
|
||||
// Stop I2C transmission
|
||||
if (_wire->endTransmission() != 0) return false;
|
||||
|
||||
delay(200);
|
||||
|
||||
// Request 6 bytes of data
|
||||
_wire->requestFrom(_addr, (uint8_t)6);
|
||||
|
||||
// Read 6 bytes of data
|
||||
// cTemp msb, cTemp lsb, cTemp crc, humidity msb, humidity lsb, humidity crc
|
||||
for (int i = 0; i < 6; i++) {
|
||||
data[i] = _wire->read();
|
||||
};
|
||||
|
||||
delay(50);
|
||||
|
||||
if (_wire->available() != 0) return false;
|
||||
|
||||
// Convert the data
|
||||
cTemp = ((((data[0] * 256.0) + data[1]) * 175) / 65535.0) - 45;
|
||||
fTemp = (cTemp * 1.8) + 32;
|
||||
humidity = ((((data[3] * 256.0) + data[4]) * 100) / 65535.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
25
libraries/M5Unit-ENV/src/SHT3X.h
Normal file
25
libraries/M5Unit-ENV/src/SHT3X.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef __SHT3X_H_
|
||||
#define __SHT3X_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "I2C_Class.h"
|
||||
#include "Wire.h"
|
||||
|
||||
#define SHT3X_I2C_ADDR 0x44
|
||||
|
||||
class SHT3X {
|
||||
public:
|
||||
bool begin(TwoWire* wire = &Wire, uint8_t addr = SHT3X_I2C_ADDR,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U);
|
||||
bool update(void);
|
||||
float cTemp = 0;
|
||||
float fTemp = 0;
|
||||
float humidity = 0;
|
||||
|
||||
private:
|
||||
TwoWire* _wire;
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
};
|
||||
|
||||
#endif
|
||||
96
libraries/M5Unit-ENV/src/SHT4X.cpp
Normal file
96
libraries/M5Unit-ENV/src/SHT4X.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
#include "SHT4X.h"
|
||||
|
||||
bool SHT4X::begin(TwoWire* wire, uint8_t addr, uint8_t sda, uint8_t scl,
|
||||
long freq) {
|
||||
_i2c.begin(wire, sda, scl, freq);
|
||||
_addr = addr;
|
||||
_wire = wire;
|
||||
return _i2c.exist(_addr);
|
||||
}
|
||||
|
||||
bool SHT4X::update() {
|
||||
uint8_t readbuffer[6];
|
||||
uint8_t cmd = SHT4x_NOHEAT_HIGHPRECISION;
|
||||
uint16_t duration = 10;
|
||||
|
||||
if (_heater == SHT4X_NO_HEATER) {
|
||||
if (_precision == SHT4X_HIGH_PRECISION) {
|
||||
cmd = SHT4x_NOHEAT_HIGHPRECISION;
|
||||
duration = 10;
|
||||
}
|
||||
if (_precision == SHT4X_MED_PRECISION) {
|
||||
cmd = SHT4x_NOHEAT_MEDPRECISION;
|
||||
duration = 5;
|
||||
}
|
||||
if (_precision == SHT4X_LOW_PRECISION) {
|
||||
cmd = SHT4x_NOHEAT_LOWPRECISION;
|
||||
duration = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (_heater == SHT4X_HIGH_HEATER_1S) {
|
||||
cmd = SHT4x_HIGHHEAT_1S;
|
||||
duration = 1100;
|
||||
}
|
||||
if (_heater == SHT4X_HIGH_HEATER_100MS) {
|
||||
cmd = SHT4x_HIGHHEAT_100MS;
|
||||
duration = 110;
|
||||
}
|
||||
|
||||
if (_heater == SHT4X_MED_HEATER_1S) {
|
||||
cmd = SHT4x_MEDHEAT_1S;
|
||||
duration = 1100;
|
||||
}
|
||||
if (_heater == SHT4X_MED_HEATER_100MS) {
|
||||
cmd = SHT4x_MEDHEAT_100MS;
|
||||
duration = 110;
|
||||
}
|
||||
|
||||
if (_heater == SHT4X_LOW_HEATER_1S) {
|
||||
cmd = SHT4x_LOWHEAT_1S;
|
||||
duration = 1100;
|
||||
}
|
||||
if (_heater == SHT4X_LOW_HEATER_100MS) {
|
||||
cmd = SHT4x_LOWHEAT_100MS;
|
||||
duration = 110;
|
||||
}
|
||||
|
||||
_i2c.writeByte(_addr, cmd, 1);
|
||||
|
||||
delay(duration);
|
||||
|
||||
_wire->requestFrom(_addr, (uint8_t)6);
|
||||
|
||||
for (uint16_t i = 0; i < 6; i++) {
|
||||
readbuffer[i] = _wire->read();
|
||||
}
|
||||
|
||||
if (readbuffer[2] != crc8(readbuffer, 2) ||
|
||||
readbuffer[5] != crc8(readbuffer + 3, 2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float t_ticks = (uint16_t)readbuffer[0] * 256 + (uint16_t)readbuffer[1];
|
||||
float rh_ticks = (uint16_t)readbuffer[3] * 256 + (uint16_t)readbuffer[4];
|
||||
|
||||
cTemp = -45 + 175 * t_ticks / 65535;
|
||||
humidity = -6 + 125 * rh_ticks / 65535;
|
||||
humidity = min(max(humidity, (float)0.0), (float)100.0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SHT4X::setPrecision(sht4x_precision_t prec) {
|
||||
_precision = prec;
|
||||
}
|
||||
|
||||
sht4x_precision_t SHT4X::getPrecision(void) {
|
||||
return _precision;
|
||||
}
|
||||
|
||||
void SHT4X::setHeater(sht4x_heater_t heat) {
|
||||
_heater = heat;
|
||||
}
|
||||
|
||||
sht4x_heater_t SHT4X::getHeater(void) {
|
||||
return _heater;
|
||||
}
|
||||
80
libraries/M5Unit-ENV/src/SHT4X.h
Normal file
80
libraries/M5Unit-ENV/src/SHT4X.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef __SHT4X_H_
|
||||
#define __SHT4X_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "I2C_Class.h"
|
||||
#include "Wire.h"
|
||||
#include "utility.h"
|
||||
|
||||
#define SHT40_I2C_ADDR_44 0x44
|
||||
#define SHT40_I2C_ADDR_45 0x45
|
||||
#define SHT41_I2C_ADDR_44 0x44
|
||||
#define SHT41_I2C_ADDR_45 0x45
|
||||
#define SHT45_I2C_ADDR_44 0x44
|
||||
#define SHT45_I2C_ADDR_45 0x45
|
||||
|
||||
#define SHT4x_DEFAULT_ADDR 0x44 /**< SHT4x I2C Address */
|
||||
#define SHT4x_NOHEAT_HIGHPRECISION \
|
||||
0xFD /**< High precision measurement, no heater */
|
||||
#define SHT4x_NOHEAT_MEDPRECISION \
|
||||
0xF6 /**< Medium precision measurement, no heater */
|
||||
#define SHT4x_NOHEAT_LOWPRECISION \
|
||||
0xE0 /**< Low precision measurement, no heater */
|
||||
|
||||
#define SHT4x_HIGHHEAT_1S \
|
||||
0x39 /**< High precision measurement, high heat for 1 sec */
|
||||
#define SHT4x_HIGHHEAT_100MS \
|
||||
0x32 /**< High precision measurement, high heat for 0.1 sec */
|
||||
#define SHT4x_MEDHEAT_1S \
|
||||
0x2F /**< High precision measurement, med heat for 1 sec */
|
||||
#define SHT4x_MEDHEAT_100MS \
|
||||
0x24 /**< High precision measurement, med heat for 0.1 sec */
|
||||
#define SHT4x_LOWHEAT_1S \
|
||||
0x1E /**< High precision measurement, low heat for 1 sec */
|
||||
#define SHT4x_LOWHEAT_100MS \
|
||||
0x15 /**< High precision measurement, low heat for 0.1 sec */
|
||||
|
||||
#define SHT4x_READSERIAL 0x89 /**< Read Out of Serial Register */
|
||||
#define SHT4x_SOFTRESET 0x94 /**< Soft Reset */
|
||||
|
||||
typedef enum {
|
||||
SHT4X_HIGH_PRECISION,
|
||||
SHT4X_MED_PRECISION,
|
||||
SHT4X_LOW_PRECISION,
|
||||
} sht4x_precision_t;
|
||||
|
||||
/** Optional pre-heater configuration setting */
|
||||
typedef enum {
|
||||
SHT4X_NO_HEATER,
|
||||
SHT4X_HIGH_HEATER_1S,
|
||||
SHT4X_HIGH_HEATER_100MS,
|
||||
SHT4X_MED_HEATER_1S,
|
||||
SHT4X_MED_HEATER_100MS,
|
||||
SHT4X_LOW_HEATER_1S,
|
||||
SHT4X_LOW_HEATER_100MS,
|
||||
} sht4x_heater_t;
|
||||
|
||||
class SHT4X {
|
||||
public:
|
||||
bool begin(TwoWire* wire = &Wire, uint8_t addr = SHT40_I2C_ADDR_44,
|
||||
uint8_t sda = 21, uint8_t scl = 22, long freq = 400000U);
|
||||
bool update(void);
|
||||
|
||||
float cTemp = 0;
|
||||
float humidity = 0;
|
||||
|
||||
void setPrecision(sht4x_precision_t prec);
|
||||
sht4x_precision_t getPrecision(void);
|
||||
void setHeater(sht4x_heater_t heat);
|
||||
sht4x_heater_t getHeater(void);
|
||||
|
||||
private:
|
||||
TwoWire* _wire;
|
||||
uint8_t _addr;
|
||||
I2C_Class _i2c;
|
||||
|
||||
sht4x_precision_t _precision = SHT4X_HIGH_PRECISION;
|
||||
sht4x_heater_t _heater = SHT4X_NO_HEATER;
|
||||
};
|
||||
|
||||
#endif
|
||||
1019
libraries/M5Unit-ENV/src/unit/unit_BME688.cpp
Normal file
1019
libraries/M5Unit-ENV/src/unit/unit_BME688.cpp
Normal file
File diff suppressed because it is too large
Load diff
1012
libraries/M5Unit-ENV/src/unit/unit_BME688.hpp
Normal file
1012
libraries/M5Unit-ENV/src/unit/unit_BME688.hpp
Normal file
File diff suppressed because it is too large
Load diff
594
libraries/M5Unit-ENV/src/unit/unit_BMP280.cpp
Normal file
594
libraries/M5Unit-ENV/src/unit/unit_BMP280.cpp
Normal file
|
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file unit_BMP280.cpp
|
||||
@brief BMP280 Unit for M5UnitUnified
|
||||
*/
|
||||
#include "unit_BMP280.hpp"
|
||||
#include <M5Utility.hpp>
|
||||
#include <limits> // NaN
|
||||
#include <array>
|
||||
|
||||
using namespace m5::utility::mmh3;
|
||||
using namespace m5::unit::types;
|
||||
using namespace m5::unit::bmp280;
|
||||
using namespace m5::unit::bmp280::command;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint8_t CHIP_IDENTIFIER{0x58};
|
||||
constexpr uint8_t RESET_VALUE{0xB6};
|
||||
constexpr uint32_t NOT_MEASURED{0x800000};
|
||||
|
||||
constexpr PowerMode mode_table[] = {PowerMode::Sleep, PowerMode::Forced, PowerMode::Forced, // duplicated
|
||||
PowerMode::Normal
|
||||
|
||||
};
|
||||
|
||||
constexpr Oversampling osrs_table[] = {
|
||||
Oversampling::Skipped, Oversampling::X1, Oversampling::X2, Oversampling::X4, Oversampling::X8, Oversampling::X16,
|
||||
Oversampling::X16, // duplicated
|
||||
Oversampling::X16, // duplicated
|
||||
};
|
||||
|
||||
constexpr Oversampling osrss_table[][2] = {
|
||||
// Pressure, Temperature
|
||||
{Oversampling::X1, Oversampling::X1}, {Oversampling::X2, Oversampling::X1}, {Oversampling::X4, Oversampling::X1},
|
||||
{Oversampling::X8, Oversampling::X1}, {Oversampling::X16, Oversampling::X2},
|
||||
};
|
||||
|
||||
constexpr Standby standby_table[] = {
|
||||
Standby::Time0_5ms, Standby::Time62_5ms, Standby::Time125ms, Standby::Time250ms,
|
||||
Standby::Time500ms, Standby::Time1sec, Standby::Time2sec, Standby::Time4sec,
|
||||
|
||||
};
|
||||
|
||||
constexpr uint32_t interval_table[] = {0, 62, 125, 250, 500, 1000, 2000, 4000};
|
||||
|
||||
constexpr Filter filter_table[] = {
|
||||
Filter::Off, Filter::Coeff2, Filter::Coeff4, Filter::Coeff8, Filter::Coeff16,
|
||||
};
|
||||
|
||||
struct UseCaseSetting {
|
||||
OversamplingSetting osrss;
|
||||
Filter filter;
|
||||
Standby st;
|
||||
};
|
||||
constexpr UseCaseSetting uc_table[] = {
|
||||
{OversamplingSetting::UltraHighResolution, Filter::Coeff4, Standby::Time62_5ms},
|
||||
{OversamplingSetting::StandardResolution, Filter::Coeff16, Standby::Time0_5ms},
|
||||
{OversamplingSetting::UltraLowPower, Filter::Off, Standby::Time4sec},
|
||||
{OversamplingSetting::StandardResolution, Filter::Coeff4, Standby::Time125ms},
|
||||
{OversamplingSetting::LowPower, Filter::Off, Standby::Time0_5ms},
|
||||
{OversamplingSetting::UltraHighResolution, Filter::Coeff16, Standby::Time0_5ms},
|
||||
};
|
||||
|
||||
struct CtrlMeas {
|
||||
//
|
||||
inline Oversampling osrs_p() const
|
||||
{
|
||||
return osrs_table[(value >> 2) & 0x07];
|
||||
}
|
||||
inline Oversampling osrs_t() const
|
||||
{
|
||||
return osrs_table[(value >> 5) & 0x07];
|
||||
}
|
||||
inline PowerMode mode() const
|
||||
{
|
||||
return mode_table[value & 0x03];
|
||||
}
|
||||
//
|
||||
inline void osrs_p(const Oversampling os)
|
||||
{
|
||||
value = (value & ~(0x07 << 2)) | ((m5::stl::to_underlying(os) & 0x07) << 2);
|
||||
}
|
||||
inline void osrs_t(const Oversampling os)
|
||||
{
|
||||
value = (value & ~(0x07 << 5)) | ((m5::stl::to_underlying(os) & 0x07) << 5);
|
||||
}
|
||||
inline void mode(const PowerMode m)
|
||||
{
|
||||
value = (value & ~0x03) | (m5::stl::to_underlying(m) & 0x03);
|
||||
}
|
||||
uint8_t value{};
|
||||
};
|
||||
|
||||
struct Config {
|
||||
//
|
||||
inline Standby standby() const
|
||||
{
|
||||
return standby_table[(value >> 5) & 0x07];
|
||||
}
|
||||
inline Filter filter() const
|
||||
{
|
||||
return filter_table[(value >> 2) & 0x07];
|
||||
}
|
||||
//
|
||||
inline void standby(const Standby s)
|
||||
{
|
||||
value = (value & ~(0x07 << 5)) | ((m5::stl::to_underlying(s) & 0x07) << 5);
|
||||
}
|
||||
inline void filter(const Filter f)
|
||||
{
|
||||
value = (value & ~(0x07 << 2)) | ((m5::stl::to_underlying(f) & 0x07) << 2);
|
||||
}
|
||||
uint8_t value{};
|
||||
};
|
||||
|
||||
struct Calculator {
|
||||
inline float temperature(const int32_t adc_P, const int32_t adc_T, const Trimming* t)
|
||||
{
|
||||
return t ? compensate_temperature_f(adc_T, *t) : std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
inline float pressure(const int32_t adc_P, const int32_t adc_T, const Trimming* t)
|
||||
{
|
||||
if (!t) {
|
||||
return std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
if (t_fine == 0) {
|
||||
(void)compensate_temperature_f(adc_T, *t); // For t_fine
|
||||
}
|
||||
return compensate_pressure_f(adc_P, *t);
|
||||
}
|
||||
|
||||
private:
|
||||
float compensate_temperature(const int32_t adc_T, const Trimming& trim)
|
||||
{
|
||||
int32_t var1{}, var2{};
|
||||
var1 = ((((adc_T >> 3) - ((int32_t)trim.dig_T1 << 1))) * ((int32_t)trim.dig_T2)) >> 11;
|
||||
var2 = (((((adc_T >> 4) - ((int32_t)trim.dig_T1)) * ((adc_T >> 4) - ((int32_t)trim.dig_T1))) >> 12) *
|
||||
((int32_t)trim.dig_T3)) >>
|
||||
14;
|
||||
t_fine = var1 + var2; // [*1]
|
||||
float T = (t_fine * 5 + 128) >> 8;
|
||||
return T * 0.01f;
|
||||
}
|
||||
|
||||
float compensate_pressure(const int32_t adc_P, const Trimming& trim)
|
||||
{
|
||||
int64_t var1{}, var2{}, p{};
|
||||
var1 = ((int64_t)t_fine) - 128000; // (*1) using it!
|
||||
var2 = var1 * var1 * (int64_t)trim.dig_P6;
|
||||
var2 = var2 + ((var1 * (int64_t)trim.dig_P5) << 17);
|
||||
var2 = var2 + (((int64_t)trim.dig_P4) << 35);
|
||||
var1 = ((var1 * var1 * (int64_t)trim.dig_P3) >> 8) + ((var1 * (int64_t)trim.dig_P2) << 12);
|
||||
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)trim.dig_P1) >> 33;
|
||||
if (var1) {
|
||||
p = 1048576 - adc_P;
|
||||
p = (((p << 31) - var2) * 3125) / var1;
|
||||
var1 = (((int64_t)trim.dig_P9) * (p >> 13) * (p >> 13)) >> 25;
|
||||
var2 = (((int64_t)trim.dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)trim.dig_P7) << 4);
|
||||
return p / 256.f;
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float compensate_temperature_f(const int32_t adc_T, const Trimming& trim)
|
||||
{
|
||||
float var1{}, var2{}, T{};
|
||||
var1 = (((float)adc_T) / 16384.0f - ((float)trim.dig_T1) / 1024.0f) * ((float)trim.dig_T2);
|
||||
var2 = ((((float)adc_T) / 131072.0f - ((float)trim.dig_T1) / 8192.0f) *
|
||||
(((float)adc_T) / 131072.0f - ((float)trim.dig_T1) / 8192.0f)) *
|
||||
((float)trim.dig_T3);
|
||||
t_fine = (int32_t)(var1 + var2); // [*2]
|
||||
T = (var1 + var2) / 5120.0f;
|
||||
return T;
|
||||
}
|
||||
|
||||
float compensate_pressure_f(const int32_t adc_P, const Trimming& trim)
|
||||
{
|
||||
float var1{}, var2{}, P{};
|
||||
var1 = ((float)t_fine / 2.0f) - 64000.0f; // (*2)
|
||||
var2 = var1 * var1 * ((float)trim.dig_P6) / 32768.0f;
|
||||
var2 = var2 + var1 * ((float)trim.dig_P5) * 2.0f;
|
||||
var2 = (var2 / 4.0f) + (((float)trim.dig_P4) * 65536.0f);
|
||||
var1 = (((float)trim.dig_P3) * var1 * var1 / 524288.0f + ((float)trim.dig_P2) * var1) / 524288.0f;
|
||||
var1 = (1.0f + var1 / 32768.0f) * ((float)trim.dig_P1);
|
||||
if (var1 == 0.0f) {
|
||||
return 0;
|
||||
}
|
||||
P = 1048576.0f - (float)adc_P;
|
||||
P = (P - (var2 / 4096.0f)) * 6250.0f / var1;
|
||||
var1 = ((float)trim.dig_P9) * P * P / 2147483648.0f;
|
||||
var2 = P * ((float)trim.dig_P8) / 32768.0f;
|
||||
P = P + (var1 + var2 + ((float)trim.dig_P7)) / 16.0f;
|
||||
return P;
|
||||
}
|
||||
|
||||
////
|
||||
|
||||
int32_t t_fine{};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace m5 {
|
||||
namespace unit {
|
||||
namespace bmp280 {
|
||||
|
||||
float Data::celsius() const
|
||||
{
|
||||
int32_t adc_P = (int32_t)(((uint32_t)raw[0] << 16) | ((uint32_t)raw[1] << 8) | ((uint32_t)raw[2]));
|
||||
int32_t adc_T = (int32_t)(((uint32_t)raw[3] << 16) | ((uint32_t)raw[4] << 8) | ((uint32_t)raw[5]));
|
||||
Calculator c{};
|
||||
|
||||
// adc_T is NOT_MEASURED if orsr Skipped (Not measured)
|
||||
return (adc_T != NOT_MEASURED) ? c.temperature(adc_P >> 4, adc_T >> 4, trimming)
|
||||
: std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
float Data::fahrenheit() const
|
||||
{
|
||||
return celsius() * 9.0f / 5.0f + 32.f;
|
||||
}
|
||||
|
||||
float Data::pressure() const
|
||||
{
|
||||
int32_t adc_P = (int32_t)(((uint32_t)raw[0] << 16) | ((uint32_t)raw[1] << 8) | ((uint32_t)raw[2]));
|
||||
int32_t adc_T = (int32_t)(((uint32_t)raw[3] << 16) | ((uint32_t)raw[4] << 8) | ((uint32_t)raw[5]));
|
||||
Calculator c{};
|
||||
|
||||
// adc_T/P is NOT_MEASURED if orsr Skipped (Not measured)
|
||||
return (adc_T != NOT_MEASURED && adc_P != NOT_MEASURED) ? c.pressure(adc_P >> 4, adc_T >> 4, trimming)
|
||||
: std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
|
||||
} // namespace bmp280
|
||||
|
||||
const char UnitBMP280::name[] = "UnitBMP280";
|
||||
const types::uid_t UnitBMP280::uid{"UnitBMP280"_mmh3};
|
||||
const types::attr_t UnitBMP280::attr{attribute::AccessI2C};
|
||||
|
||||
bool UnitBMP280::begin()
|
||||
{
|
||||
auto ssize = stored_size();
|
||||
assert(ssize && "stored_size must be greater than zero");
|
||||
if (ssize != _data->capacity()) {
|
||||
_data.reset(new m5::container::CircularBuffer<Data>(ssize));
|
||||
if (!_data) {
|
||||
M5_LIB_LOGE("Failed to allocate");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t id{};
|
||||
if (!softReset() || !readRegister8(CHIP_ID, id, 0) || id != CHIP_IDENTIFIER) {
|
||||
M5_LIB_LOGE("Can not detect BMP280 %02X", id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!read_trimming(_trimming)) {
|
||||
M5_LIB_LOGE("Failed to read trimming");
|
||||
return false;
|
||||
}
|
||||
|
||||
M5_LIB_LOGV(
|
||||
"Trimming\n"
|
||||
"T:%u/%d/%d\n"
|
||||
"P:%u/%d/%d/%d/%d/%d/%d/%d/%d",
|
||||
// T
|
||||
_trimming.dig_T1, _trimming.dig_T2, _trimming.dig_T3,
|
||||
// P
|
||||
_trimming.dig_P1, _trimming.dig_P2, _trimming.dig_P3, _trimming.dig_P4, _trimming.dig_P5, _trimming.dig_P6,
|
||||
_trimming.dig_P7, _trimming.dig_P8, _trimming.dig_P9);
|
||||
|
||||
return _cfg.start_periodic
|
||||
? startPeriodicMeasurement(_cfg.osrs_pressure, _cfg.osrs_temperature, _cfg.filter, _cfg.standby)
|
||||
: true;
|
||||
}
|
||||
|
||||
void UnitBMP280::update(const bool force)
|
||||
{
|
||||
_updated = false;
|
||||
if (inPeriodic()) {
|
||||
elapsed_time_t at{m5::utility::millis()};
|
||||
if (force || !_latest || at >= _latest + _interval) {
|
||||
Data d{};
|
||||
// _updated = is_data_ready() && read_measurement(d);
|
||||
_updated = read_measurement(d);
|
||||
if (_updated) {
|
||||
// auto dur = at - _latest;
|
||||
// M5_LIB_LOGW(">DUR:%ld\n", dur);
|
||||
_latest = at;
|
||||
_data->push_back(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UnitBMP280::start_periodic_measurement(const bmp280::Oversampling osrsPressure,
|
||||
const bmp280::Oversampling osrsTemperature, const bmp280::Filter filter,
|
||||
const bmp280::Standby st)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
Config c{};
|
||||
c.standby(st);
|
||||
c.filter(filter);
|
||||
CtrlMeas cm{};
|
||||
cm.osrs_p(osrsPressure);
|
||||
cm.osrs_t(osrsTemperature);
|
||||
|
||||
return writeRegister8(CONFIG, c.value) && writeRegister8(CONTROL_MEASUREMENT, cm.value) &&
|
||||
start_periodic_measurement();
|
||||
}
|
||||
|
||||
bool UnitBMP280::start_periodic_measurement()
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
Config c{};
|
||||
_periodic = readRegister8(CONFIG, c.value, 0) && writePowerMode(PowerMode::Normal);
|
||||
if (_periodic) {
|
||||
_latest = 0;
|
||||
_interval = interval_table[m5::stl::to_underlying(c.standby())];
|
||||
}
|
||||
return _periodic;
|
||||
}
|
||||
|
||||
bool UnitBMP280::stop_periodic_measurement()
|
||||
{
|
||||
if (inPeriodic() && writePowerMode(PowerMode::Sleep)) {
|
||||
_periodic = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::measureSingleshot(bmp280::Data& d, const bmp280::Oversampling osrsPressure,
|
||||
const bmp280::Oversampling osrsTemperature, const bmp280::Filter filter)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
if (osrsTemperature == Oversampling::Skipped) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Config c{};
|
||||
c.filter(filter);
|
||||
CtrlMeas cm{};
|
||||
cm.osrs_p(osrsPressure);
|
||||
cm.osrs_t(osrsTemperature);
|
||||
return writeRegister8(CONFIG, c.value) && writeRegister8(CONTROL_MEASUREMENT, cm.value) && measure_singleshot(d);
|
||||
}
|
||||
|
||||
bool UnitBMP280::measure_singleshot(bmp280::Data& d)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (writePowerMode(PowerMode::Forced)) {
|
||||
auto start_at = m5::utility::millis();
|
||||
auto timeout_at = start_at + 2 * 1000; // 2sec
|
||||
bool done{};
|
||||
do {
|
||||
PowerMode pm{};
|
||||
done = readPowerMode(pm) && (pm == PowerMode::Sleep) && is_data_ready();
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
m5::utility::delay(1);
|
||||
} while (!done && m5::utility::millis() <= timeout_at);
|
||||
return done && read_measurement(d);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::readOversampling(Oversampling& osrsPressure, Oversampling& osrsTemperature)
|
||||
{
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
osrsPressure = cm.osrs_p();
|
||||
osrsTemperature = cm.osrs_t();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeOversampling(const Oversampling osrsPressure, const Oversampling osrsTemperature)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
cm.osrs_p(osrsPressure);
|
||||
cm.osrs_t(osrsTemperature);
|
||||
return writeRegister8(CONTROL_MEASUREMENT, cm.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeOversamplingPressure(const Oversampling osrsPressure)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
cm.osrs_p(osrsPressure);
|
||||
return writeRegister8(CONTROL_MEASUREMENT, cm.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeOversamplingTemperature(const Oversampling osrsTemperature)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
cm.osrs_t(osrsTemperature);
|
||||
return writeRegister8(CONTROL_MEASUREMENT, cm.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeOversampling(const bmp280::OversamplingSetting osrss)
|
||||
{
|
||||
auto idx = m5::stl::to_underlying(osrss);
|
||||
return writeOversampling(osrss_table[idx][0], osrss_table[idx][1]);
|
||||
}
|
||||
|
||||
bool UnitBMP280::readPowerMode(PowerMode& m)
|
||||
{
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
m = cm.mode();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writePowerMode(const PowerMode m)
|
||||
{
|
||||
CtrlMeas cm{};
|
||||
if (readRegister8(CONTROL_MEASUREMENT, cm.value, 0)) {
|
||||
cm.mode(m);
|
||||
|
||||
// Datasheet says
|
||||
// If the device is currently performing ameasurement,
|
||||
// execution of mode switching commands is delayed until the end of the currentlyrunning measurement period
|
||||
bool can{};
|
||||
auto timeout_at = m5::utility::millis() + 1000;
|
||||
do {
|
||||
can = is_data_ready();
|
||||
if (can) {
|
||||
break;
|
||||
}
|
||||
m5::utility::delay(1);
|
||||
} while (!can && m5::utility::millis() <= timeout_at);
|
||||
|
||||
return can && writeRegister8(CONTROL_MEASUREMENT, cm.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::readFilter(Filter& f)
|
||||
{
|
||||
Config c{};
|
||||
if (readRegister8(CONFIG, c.value, 0)) {
|
||||
f = c.filter();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeFilter(const Filter& f)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
PowerMode pm{};
|
||||
if (!readPowerMode(pm) || pm != PowerMode::Sleep) {
|
||||
// Datasheet says
|
||||
// Writes to the config register in normal mode may be ignored. In sleep mode writes are not ignored
|
||||
M5_LIB_LOGE("Invalid power mode %02X", pm);
|
||||
return false;
|
||||
}
|
||||
|
||||
Config c{};
|
||||
if (readRegister8(CONFIG, c.value, 0)) {
|
||||
c.filter(f);
|
||||
return writeRegister8(CONFIG, c.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::readStandbyTime(Standby& s)
|
||||
{
|
||||
Config c{};
|
||||
if (readRegister8(CONFIG, c.value, 0)) {
|
||||
s = c.standby();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeStandbyTime(const Standby s)
|
||||
{
|
||||
if (inPeriodic()) {
|
||||
M5_LIB_LOGD("Periodic measurements are running");
|
||||
return false;
|
||||
}
|
||||
|
||||
Config c{};
|
||||
if (readRegister8(CONFIG, c.value, 0)) {
|
||||
c.standby(s);
|
||||
return writeRegister8(CONFIG, c.value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitBMP280::writeUseCaseSetting(const bmp280::UseCase uc)
|
||||
{
|
||||
const auto& tbl = uc_table[m5::stl::to_underlying(uc)];
|
||||
return writeOversampling(tbl.osrss) && writeFilter(tbl.filter) && writeStandbyTime(tbl.st);
|
||||
}
|
||||
|
||||
bool UnitBMP280::softReset()
|
||||
{
|
||||
if (writeRegister8(SOFT_RESET, RESET_VALUE)) {
|
||||
auto timeout_at = m5::utility::millis() + 100; // 100ms
|
||||
uint8_t s{0xFF};
|
||||
do {
|
||||
if (readRegister8(GET_STATUS, s, 0) && (s & 0x01 /* im update */) == 0x00) {
|
||||
_periodic = false;
|
||||
return true;
|
||||
}
|
||||
} while ((s & 0x01) && m5::utility::millis() < timeout_at);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
bool UnitBMP280::read_trimming(Trimming& t)
|
||||
{
|
||||
return readRegister(TRIMMING_DIG, t.value, m5::stl::size(t.value), 0);
|
||||
}
|
||||
|
||||
bool UnitBMP280::is_data_ready()
|
||||
{
|
||||
uint8_t s{0xFF};
|
||||
return readRegister8(GET_STATUS, s, 0) && ((s & 0x09 /* Measuring, im update */) == 0x00);
|
||||
}
|
||||
|
||||
bool UnitBMP280::read_measurement(bmp280::Data& d)
|
||||
{
|
||||
d.trimming = nullptr;
|
||||
|
||||
// Datasheet says
|
||||
// Shadowing will only work if all data registers are read in a single burst read.
|
||||
// Therefore, the user must use burst reads if he does not synchronize data readout with themeasurement cycle
|
||||
if (readRegister(GET_MEASUREMENT, d.raw.data(), d.raw.size(), 0)) {
|
||||
d.trimming = &_trimming;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace unit
|
||||
} // namespace m5
|
||||
434
libraries/M5Unit-ENV/src/unit/unit_BMP280.hpp
Normal file
434
libraries/M5Unit-ENV/src/unit/unit_BMP280.hpp
Normal file
|
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file unit_BMP280.hpp
|
||||
@brief BMP280 Unit for M5UnitUnified
|
||||
*/
|
||||
#ifndef M5_UNIT_ENV_UNIT_BNP280_HPP
|
||||
#define M5_UNIT_ENV_UNIT_BNP280_HPP
|
||||
|
||||
#include <M5UnitComponent.hpp>
|
||||
#include <m5_utility/container/circular_buffer.hpp>
|
||||
#include <limits> // NaN
|
||||
|
||||
namespace m5 {
|
||||
namespace unit {
|
||||
|
||||
/*!
|
||||
@namespace bmp280
|
||||
@brief For BMP280
|
||||
*/
|
||||
namespace bmp280 {
|
||||
|
||||
/*!
|
||||
@enum PowerMode
|
||||
@brief Operation mode
|
||||
*/
|
||||
enum class PowerMode : uint8_t {
|
||||
Sleep, //!< No measurements are performed
|
||||
Forced, //!< Single measurements are performed
|
||||
Normal = 0x03, //!< Periodic measurements are performed
|
||||
};
|
||||
|
||||
/*!
|
||||
@enum Oversampling
|
||||
@brief Oversampling factor
|
||||
*/
|
||||
enum class Oversampling : uint8_t {
|
||||
Skipped, //!< Skipped (No measurements are performed)
|
||||
X1, //!< x1
|
||||
X2, //!< x2
|
||||
X4, //!< x4
|
||||
X8, //!< x8
|
||||
X16, //!< x16
|
||||
};
|
||||
|
||||
/*!
|
||||
@enum OversamplingSetting
|
||||
@brief Oversampling Settings
|
||||
*/
|
||||
enum class OversamplingSetting : uint8_t {
|
||||
UltraLowPower, //!< 16 bit / 2.62 Pa, 16 bit / 0.0050 C
|
||||
LowPower, //!< 17 bit / 1.31 Pa, 16 bit / 0.0050 C
|
||||
StandardResolution, //!< 18 bit / 0.66 Pa, 16 bit / 0.0050 C
|
||||
HighResolution, //!< 19 bit / 0.33 Pa, 16 bit / 0.0050 C
|
||||
UltraHighResolution, //!< 20 bit / 0.16 Pa, 17 bit / 0.0025 C
|
||||
};
|
||||
|
||||
/*!
|
||||
@enum Filter
|
||||
@brief Filter setting
|
||||
*/
|
||||
enum class Filter : uint8_t {
|
||||
Off, //!< Off filter
|
||||
Coeff2, //!< co-efficient 2
|
||||
Coeff4, //!< co-efficient 4
|
||||
Coeff8, //!< co-efficient 8
|
||||
Coeff16, //!< co-efficient 16
|
||||
};
|
||||
|
||||
/*!
|
||||
@enum Standby
|
||||
@brief Measurement standby time for power mode Normal
|
||||
*/
|
||||
enum class Standby : uint8_t {
|
||||
Time0_5ms, //!< 0.5 ms
|
||||
Time62_5ms, //!< 62.5 ms
|
||||
Time125ms, //!< 125 ms
|
||||
Time250ms, //!< 250 ms
|
||||
Time500ms, //!< 500 ms
|
||||
Time1sec, //!< 1 second
|
||||
Time2sec, //!< 2 seconds
|
||||
Time4sec, //!< 4 seconds
|
||||
};
|
||||
|
||||
/*!
|
||||
@enum UseCase
|
||||
@brief Preset settings
|
||||
*/
|
||||
enum class UseCase : uint8_t {
|
||||
LowPower, //!< Handheld device low-power
|
||||
Dynamic, //!< Handheld device dynamic
|
||||
Weather, //!< Weather monitoring
|
||||
Elevator, //!< Elevator / floor change detection
|
||||
Drop, //!< Drop detection
|
||||
Indoor, //!< Indoor navigation
|
||||
};
|
||||
|
||||
/*!
|
||||
@union Trimmming
|
||||
@brief Trimming parameter
|
||||
*/
|
||||
union Trimming {
|
||||
uint8_t value[12 * 2]{};
|
||||
struct {
|
||||
//
|
||||
uint16_t dig_T1;
|
||||
int16_t dig_T2;
|
||||
int16_t dig_T3;
|
||||
//
|
||||
uint16_t dig_P1;
|
||||
int16_t dig_P2;
|
||||
int16_t dig_P3;
|
||||
int16_t dig_P4;
|
||||
int16_t dig_P5;
|
||||
int16_t dig_P6;
|
||||
int16_t dig_P7;
|
||||
int16_t dig_P8;
|
||||
int16_t dig_P9;
|
||||
// uint16_t reserved;
|
||||
} __attribute__((packed));
|
||||
};
|
||||
|
||||
/*!
|
||||
@struct Data
|
||||
@brief Measurement data group
|
||||
*/
|
||||
struct Data {
|
||||
std::array<uint8_t, 6> raw{}; //!< RAW data [0,1,2]:pressure [3,4,5]:temperature
|
||||
const Trimming* trimming{}; //!< For calculate
|
||||
|
||||
//! temperature (Celsius)
|
||||
inline float temperature() const
|
||||
{
|
||||
return celsius();
|
||||
}
|
||||
float celsius() const; //!< temperature (Celsius)
|
||||
float fahrenheit() const; //!< temperature (Fahrenheit)
|
||||
float pressure() const; //!< pressure (Pa)
|
||||
};
|
||||
|
||||
} // namespace bmp280
|
||||
|
||||
/*!
|
||||
@class UnitBMP280
|
||||
@brief Pressure and temperature sensor unit
|
||||
*/
|
||||
class UnitBMP280 : public Component, public PeriodicMeasurementAdapter<UnitBMP280, bmp280::Data> {
|
||||
M5_UNIT_COMPONENT_HPP_BUILDER(UnitBMP280, 0x76);
|
||||
|
||||
public:
|
||||
/*!
|
||||
@struct config_t
|
||||
@brief Settings for begin
|
||||
*/
|
||||
struct config_t {
|
||||
//! Start periodic measurement on begin?
|
||||
bool start_periodic{true};
|
||||
//! Pressure oversampling if start on begin
|
||||
bmp280::Oversampling osrs_pressure{bmp280::Oversampling::X16};
|
||||
//! Temperature oversampling if start on begin
|
||||
bmp280::Oversampling osrs_temperature{bmp280::Oversampling::X2};
|
||||
//! Filter if start on begin
|
||||
bmp280::Filter filter{bmp280::Filter::Coeff16};
|
||||
//! Standby time if start on begin
|
||||
bmp280::Standby standby{bmp280::Standby::Time1sec};
|
||||
};
|
||||
|
||||
explicit UnitBMP280(const uint8_t addr = DEFAULT_ADDRESS)
|
||||
: Component(addr), _data{new m5::container::CircularBuffer<bmp280::Data>(1)}
|
||||
{
|
||||
auto ccfg = component_config();
|
||||
ccfg.clock = 400 * 1000U;
|
||||
component_config(ccfg);
|
||||
}
|
||||
virtual ~UnitBMP280()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool begin() override;
|
||||
virtual void update(const bool force = false) override;
|
||||
|
||||
///@name Settings for begin
|
||||
///@{
|
||||
/*! @brief Gets the configration */
|
||||
inline config_t config()
|
||||
{
|
||||
return _cfg;
|
||||
}
|
||||
//! @brief Set the configration
|
||||
inline void config(const config_t& cfg)
|
||||
{
|
||||
_cfg = cfg;
|
||||
}
|
||||
///@}
|
||||
|
||||
///@name Measurement data by periodic
|
||||
///@{
|
||||
//! @brief Oldest measured temperature (Celsius)
|
||||
inline float temperature() const
|
||||
{
|
||||
return !empty() ? oldest().temperature() : std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
//! @brief Oldest measured temperature (Celsius)
|
||||
inline float celsius() const
|
||||
{
|
||||
return !empty() ? oldest().celsius() : std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
//! @brief Oldest measured temperature (Fahrenheit)
|
||||
inline float fahrenheit() const
|
||||
{
|
||||
return !empty() ? oldest().fahrenheit() : std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
//! @brief Oldest measured pressure (Pa)
|
||||
inline float pressure() const
|
||||
{
|
||||
return !empty() ? oldest().pressure() : std::numeric_limits<float>::quiet_NaN();
|
||||
}
|
||||
///@}
|
||||
|
||||
///@name Periodic measurement
|
||||
///@{
|
||||
/*!
|
||||
@brief Start periodic measurement
|
||||
@param osrsPressure Oversampling factor for pressure
|
||||
@param osrsTemperature Oversampling factor for temperature
|
||||
@param filter Filter coeff
|
||||
@param st Standby time
|
||||
@return True if successful
|
||||
@warning Measuring pressure requires measuring temperature
|
||||
*/
|
||||
inline bool startPeriodicMeasurement(const bmp280::Oversampling osrsPressure,
|
||||
const bmp280::Oversampling osrsTemperature, const bmp280::Filter filter,
|
||||
const bmp280::Standby st)
|
||||
{
|
||||
return PeriodicMeasurementAdapter<UnitBMP280, bmp280::Data>::startPeriodicMeasurement(
|
||||
osrsPressure, osrsTemperature, filter, st);
|
||||
}
|
||||
//! @brief Start periodic measurement using current settings
|
||||
inline bool startPeriodicMeasurement()
|
||||
{
|
||||
return PeriodicMeasurementAdapter<UnitBMP280, bmp280::Data>::startPeriodicMeasurement();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Stop periodic measurement
|
||||
@return True if successful
|
||||
*/
|
||||
inline bool stopPeriodicMeasurement()
|
||||
{
|
||||
return PeriodicMeasurementAdapter<UnitBMP280, bmp280::Data>::stopPeriodicMeasurement();
|
||||
}
|
||||
///@}
|
||||
|
||||
///@name Single shot measurement
|
||||
///@{
|
||||
/*!
|
||||
@brief Measurement single shot
|
||||
@param[out] data Measuerd data
|
||||
@param osrsPressure Oversampling factor for pressure
|
||||
@param osrsTemperature Oversampling factor for temperature
|
||||
@param filter Filter coeff
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
@warning Measuring pressure requires measuring temperature
|
||||
@warning Each setting is overwritten
|
||||
*/
|
||||
bool measureSingleshot(bmp280::Data& d, const bmp280::Oversampling osrsPressure,
|
||||
const bmp280::Oversampling osrsTemperature, const bmp280::Filter filter);
|
||||
//! @brief Measurement single shot using current settings
|
||||
inline bool measureSingleshot(bmp280::Data& d)
|
||||
{
|
||||
return measure_singleshot(d);
|
||||
}
|
||||
///@}
|
||||
|
||||
///@name Settings
|
||||
///@{
|
||||
/*!
|
||||
@brief Read the oversampling conditions
|
||||
@param[out] osrsPressure Oversampling for pressure
|
||||
@param[out] osrsTemperature Oversampling for temperature
|
||||
@return True if successful
|
||||
*/
|
||||
bool readOversampling(bmp280::Oversampling& osrsPressure, bmp280::Oversampling& osrsTemperature);
|
||||
/*!
|
||||
@brief Write the oversampling conditions
|
||||
@param osrsPressure Oversampling for pressure
|
||||
@param osrsTemperature Oversampling for temperature
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeOversampling(const bmp280::Oversampling osrsPressure, const bmp280::Oversampling osrsTemperature);
|
||||
/*!
|
||||
@brief Write the oversampling conditions for pressure
|
||||
@param osrsPressure Oversampling for pressure
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeOversamplingPressure(const bmp280::Oversampling osrsPressure);
|
||||
/*!
|
||||
@brief Write the oversampling conditions for temperature
|
||||
@param osrsTemperature Oversampling for temperature
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeOversamplingTemperature(const bmp280::Oversampling osrsTemperature);
|
||||
/*!
|
||||
@brief Write the oversampling by OversamplingSetting
|
||||
@param osrss OversamplingSetting
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeOversampling(const bmp280::OversamplingSetting osrss);
|
||||
/*!
|
||||
@brief Read the IIR filter co-efficient
|
||||
@param[out] f filter
|
||||
@return True if successful
|
||||
*/
|
||||
bool readFilter(bmp280::Filter& f);
|
||||
/*!
|
||||
@brief Write the IIR filter co-efficient
|
||||
@param f filter
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeFilter(const bmp280::Filter& f);
|
||||
/*!
|
||||
@brief Read the standby time
|
||||
@param[out] s standby time
|
||||
@return True if successful
|
||||
*/
|
||||
bool readStandbyTime(bmp280::Standby& s);
|
||||
/*!
|
||||
@brief Write the standby time
|
||||
@param s standby time
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeStandbyTime(const bmp280::Standby s);
|
||||
/*!
|
||||
@brief Read the power mode
|
||||
@param[out] m Power mode
|
||||
@return True if successful
|
||||
*/
|
||||
bool readPowerMode(bmp280::PowerMode& m);
|
||||
/*!
|
||||
@brief Write the power mode
|
||||
@param m Power mode
|
||||
@return True if successful
|
||||
@warning Note that the measurement mode is changed
|
||||
@warning It is recommended to use start/stopPeriodicMeasurement or similar to change the measurement mode
|
||||
*/
|
||||
bool writePowerMode(const bmp280::PowerMode m);
|
||||
/*!
|
||||
@brief Write the settings based on use cases
|
||||
@param uc UseCase
|
||||
@return True if successful
|
||||
@warning During periodic detection runs, an error is returned
|
||||
*/
|
||||
bool writeUseCaseSetting(const bmp280::UseCase uc);
|
||||
///@}
|
||||
|
||||
/*!
|
||||
@brief Soft reset
|
||||
@return True if successful
|
||||
*/
|
||||
bool softReset();
|
||||
|
||||
protected:
|
||||
bool start_periodic_measurement(const bmp280::Oversampling osrsPressure, const bmp280::Oversampling osrsTemperature,
|
||||
const bmp280::Filter filter, const bmp280::Standby st);
|
||||
bool start_periodic_measurement();
|
||||
bool stop_periodic_measurement();
|
||||
bool read_measurement(bmp280::Data& d);
|
||||
bool measure_singleshot(bmp280::Data& d);
|
||||
|
||||
bool read_trimming(bmp280::Trimming& t);
|
||||
bool is_data_ready();
|
||||
|
||||
M5_UNIT_COMPONENT_PERIODIC_MEASUREMENT_ADAPTER_HPP_BUILDER(UnitBMP280, bmp280::Data);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<m5::container::CircularBuffer<bmp280::Data>> _data{};
|
||||
config_t _cfg{};
|
||||
bmp280::Trimming _trimming{};
|
||||
};
|
||||
|
||||
///@cond
|
||||
namespace bmp280 {
|
||||
namespace command {
|
||||
|
||||
constexpr uint8_t CHIP_ID{0xD0};
|
||||
// constexpr uint8_t CHIP_VERSION{0xD1};
|
||||
constexpr uint8_t SOFT_RESET{0xE0};
|
||||
constexpr uint8_t GET_STATUS{0xF3};
|
||||
constexpr uint8_t CONTROL_MEASUREMENT{0xF4};
|
||||
constexpr uint8_t CONFIG{0xF5};
|
||||
|
||||
constexpr uint8_t GET_MEASUREMENT{0XF7}; // 6bytes
|
||||
constexpr uint8_t GET_PRESSURE{0xF7}; // 3byts
|
||||
constexpr uint8_t GET_PRESSURE_MSB{0xF7}; // 7:0
|
||||
constexpr uint8_t GET_PRESSURE_LSB{0xF8}; // 7:0
|
||||
constexpr uint8_t GET_PRESSURE_XLSB{0xF9}; // 7:4
|
||||
constexpr uint8_t GET_TEMPERATURE{0XFA}; // 3 bytes
|
||||
constexpr uint8_t GET_TEMPERATURE_MSB{0XFA}; // 7:0
|
||||
constexpr uint8_t GET_TEMPERATURE_LSB{0XFB}; // 7:0
|
||||
constexpr uint8_t GET_TEMPERATURE_XLSB{0XFC}; // 7:4
|
||||
|
||||
constexpr uint8_t TRIMMING_DIG{0x88}; // 12 bytes
|
||||
constexpr uint8_t TRIMMING_DIG_T1{0x88};
|
||||
constexpr uint8_t TRIMMING_DIG_T2{0x8A};
|
||||
constexpr uint8_t TRIMMING_DIG_T3{0x8C};
|
||||
constexpr uint8_t TRIMMING_DIG_P1{0x8E};
|
||||
constexpr uint8_t TRIMMING_DIG_P2{0x90};
|
||||
constexpr uint8_t TRIMMING_DIG_P3{0x92};
|
||||
constexpr uint8_t TRIMMING_DIG_P4{0x94};
|
||||
constexpr uint8_t TRIMMING_DIG_P5{0x96};
|
||||
constexpr uint8_t TRIMMING_DIG_P6{0x98};
|
||||
constexpr uint8_t TRIMMING_DIG_P7{0x9A};
|
||||
constexpr uint8_t TRIMMING_DIG_P8{0x9C};
|
||||
constexpr uint8_t TRIMMING_DIG_P9{0x9A};
|
||||
constexpr uint8_t TRIMMING_DIG_RESERVED{0xA0};
|
||||
|
||||
} // namespace command
|
||||
} // namespace bmp280
|
||||
///@endcond
|
||||
|
||||
} // namespace unit
|
||||
} // namespace m5
|
||||
|
||||
#endif
|
||||
48
libraries/M5Unit-ENV/src/unit/unit_ENV3.cpp
Normal file
48
libraries/M5Unit-ENV/src/unit/unit_ENV3.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file unit_ENV3.cpp
|
||||
@brief ENV III Unit for M5UnitUnified
|
||||
*/
|
||||
#include "unit_ENV3.hpp"
|
||||
#include <M5Utility.hpp>
|
||||
|
||||
namespace m5 {
|
||||
namespace unit {
|
||||
|
||||
using namespace m5::utility::mmh3;
|
||||
using namespace m5::unit::types;
|
||||
|
||||
const char UnitENV3::name[] = "UnitENV3";
|
||||
const types::uid_t UnitENV3::uid{"UnitENV3"_mmh3};
|
||||
const types::attr_t UnitENV3::attr{attribute::AccessI2C};
|
||||
|
||||
UnitENV3::UnitENV3(const uint8_t addr) : Component(addr)
|
||||
{
|
||||
// Form a parent-child relationship
|
||||
auto cfg = component_config();
|
||||
cfg.max_children = 2;
|
||||
component_config(cfg);
|
||||
_valid = add(sht30, 0) && add(qmp6988, 1);
|
||||
}
|
||||
|
||||
std::shared_ptr<Adapter> UnitENV3::ensure_adapter(const uint8_t ch)
|
||||
{
|
||||
if (ch > 2) {
|
||||
M5_LIB_LOGE("Invalid channel %u", ch);
|
||||
return std::make_shared<Adapter>(); // Empty adapter
|
||||
}
|
||||
auto unit = child(ch);
|
||||
if (!unit) {
|
||||
M5_LIB_LOGE("Not exists unit %u", ch);
|
||||
return std::make_shared<Adapter>(); // Empty adapter
|
||||
}
|
||||
auto ad = asAdapter<AdapterI2C>(Adapter::Type::I2C);
|
||||
return ad ? std::shared_ptr<Adapter>(ad->duplicate(unit->address())) : std::make_shared<Adapter>();
|
||||
}
|
||||
|
||||
} // namespace unit
|
||||
} // namespace m5
|
||||
53
libraries/M5Unit-ENV/src/unit/unit_ENV3.hpp
Normal file
53
libraries/M5Unit-ENV/src/unit/unit_ENV3.hpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
/*!
|
||||
@file unit_ENV3.hpp
|
||||
@brief ENV III Unit for M5UnitUnified
|
||||
*/
|
||||
#ifndef M5_UNIT_ENV_UNIT_ENV3_HPP
|
||||
#define M5_UNIT_ENV_UNIT_ENV3_HPP
|
||||
|
||||
#include <M5UnitComponent.hpp>
|
||||
#include "unit_SHT30.hpp"
|
||||
#include "unit_QMP6988.hpp"
|
||||
|
||||
namespace m5 {
|
||||
namespace unit {
|
||||
|
||||
/*!
|
||||
@class UnitENV3
|
||||
@brief ENV III is an environmental sensor that integrates SHT30 and QMP6988
|
||||
@details This unit itself has no I/O, but holds SHT30 and QMP6988 instance
|
||||
*/
|
||||
class UnitENV3 : public Component {
|
||||
// Must not be 0x00 for ensure and assign adapter to children
|
||||
M5_UNIT_COMPONENT_HPP_BUILDER(UnitENV3, 0xFF /* Dummy address */);
|
||||
|
||||
public:
|
||||
UnitSHT30 sht30; //!< @brief SHT30 instance
|
||||
UnitQMP6988 qmp6988; //!< @brief QMP6988 instance
|
||||
|
||||
explicit UnitENV3(const uint8_t addr = DEFAULT_ADDRESS);
|
||||
virtual ~UnitENV3()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool begin() override
|
||||
{
|
||||
return _valid;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<Adapter> ensure_adapter(const uint8_t ch);
|
||||
|
||||
private:
|
||||
bool _valid{}; // Did the constructor correctly add the child unit?
|
||||
Component* _children[2]{&sht30, &qmp6988};
|
||||
};
|
||||
|
||||
} // namespace unit
|
||||
} // namespace m5
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue