From 3833ef40fa7c05196fe64bb87c8ee44d8e752295 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 10 Feb 2026 19:21:33 +0900 Subject: [PATCH 01/22] Fixes bug,typo. Add more core devices --- .../workflows/arduino-esp-v2-build-check.yml | 8 +- .../workflows/arduino-esp-v3-build-check.yml | 13 ++- .github/workflows/arduino-m5-build-check.yml | 22 ++-- .github/workflows/doxygen-gh-pages.yml | 2 + .github/workflows/platformio-build-check.yml | 41 +------ .../PlotToSerial/main/PlotToSerial.cpp | 67 ++++++----- .../PlotToSerial/main/PlotToSerial.cpp | 70 +++++++----- .../PlotToSerial/main/PlotToSerial.cpp | 108 +++++++++--------- .../PlotToSerial/main/PlotToSerial.cpp | 82 ++++++++++--- .../PlotToSerial/main/PlotToSerial.cpp | 59 ++++++++-- .../PlotToSerial/main/PlotToSerial.cpp | 56 +++++++-- platformio.ini | 51 ++++++++- src/idf_component.yml | 2 + src/idf_component.yml.orig | 2 + src/unit/unit_BME688.cpp | 4 +- src/unit/unit_BME688.hpp | 14 ++- src/unit/unit_BMP280.hpp | 10 +- src/unit/unit_ENV3.cpp | 2 +- src/unit/unit_ENV4.cpp | 2 +- src/unit/unit_QMP6988.cpp | 38 +++--- src/unit/unit_QMP6988.hpp | 11 +- src/unit/unit_SCD40.cpp | 12 +- src/unit/unit_SCD40.hpp | 8 +- src/unit/unit_SCD41.hpp | 4 +- src/unit/unit_SGP30.cpp | 2 - src/unit/unit_SGP30.hpp | 6 +- src/unit/unit_SHT30.cpp | 4 +- src/unit/unit_SHT30.hpp | 4 +- src/unit/unit_SHT40.cpp | 12 +- src/unit/unit_SHT40.hpp | 4 +- unit_co2_env.ini | 103 ++++++++++------- unit_env3_env.ini | 71 ++++++++---- unit_env4_env.ini | 50 ++++---- unit_envpro_env.ini | 51 +++++---- unit_tvoc_env.ini | 50 ++++---- 35 files changed, 640 insertions(+), 405 deletions(-) create mode 100644 src/idf_component.yml create mode 100644 src/idf_component.yml.orig diff --git a/.github/workflows/arduino-esp-v2-build-check.yml b/.github/workflows/arduino-esp-v2-build-check.yml index 313a864..4ce8b52 100644 --- a/.github/workflows/arduino-esp-v2-build-check.yml +++ b/.github/workflows/arduino-esp-v2-build-check.yml @@ -2,7 +2,7 @@ name: Build(arduino-esp32:2.x) env: SKETCH_NAMES_FIND_START: ./examples/UnitUnified - REQUIRED_LIBRARIES: M5Unified,M5UnitUnified,BME68x Sensor library,Bsec2 + REQUIRED_LIBRARIES: M5Unified,M5UnitUnified,BME68x Sensor library,bsec2 on: push: @@ -48,11 +48,11 @@ jobs: build: name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}} runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 12 strategy: fail-fast: false - #max-parallel: 1 + max-parallel: 20 matrix: platform-url: - https://espressif.github.io/arduino-esp32/package_esp32_index.json @@ -89,8 +89,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} # Build - name: Compile examples diff --git a/.github/workflows/arduino-esp-v3-build-check.yml b/.github/workflows/arduino-esp-v3-build-check.yml index b75ebf8..579b5c4 100644 --- a/.github/workflows/arduino-esp-v3-build-check.yml +++ b/.github/workflows/arduino-esp-v3-build-check.yml @@ -48,11 +48,11 @@ jobs: build: name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}} runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 12 strategy: fail-fast: false - #max-parallel: 1 + max-parallel: 20 matrix: platform-url: - https://espressif.github.io/arduino-esp32/package_esp32_index.json @@ -69,15 +69,17 @@ jobs: - UnitENVPro board: + - arduino_nesso_n1 - m5stack_atom - m5stack_atoms3 - m5stack_capsule -# - m5stack_cardputer + - m5stack_cardputer - m5stack_core - m5stack_core2 - m5stack_coreink - m5stack_cores3 - m5stack_dial + - m5stack_dinmeter - m5stack_fire - m5stack_nanoc6 - m5stack_paper @@ -89,13 +91,14 @@ jobs: # - m5stack_stickc - m5stack_stickc_plus - m5stack_stickc_plus2 + - m5stack_tab5 # - m5stack_timer_cam # - m5stack_tough # - m5stack_unit_cam # - m5stack_unit_cams3 platform-version: - - 3.0.4 + - 3.3.6 platform: - esp32 @@ -106,8 +109,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} # Build - name: Compile examples diff --git a/.github/workflows/arduino-m5-build-check.yml b/.github/workflows/arduino-m5-build-check.yml index 207da75..100166b 100644 --- a/.github/workflows/arduino-m5-build-check.yml +++ b/.github/workflows/arduino-m5-build-check.yml @@ -48,11 +48,11 @@ jobs: build: name: ${{ matrix.unit }}:${{ matrix.sketch }}:${{matrix.board}}@${{matrix.platform-version}} runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 12 strategy: fail-fast: false -# max-parallel: 1 + max-parallel: 20 matrix: platform-url: - https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json @@ -69,11 +69,13 @@ jobs: - UnitENVPro board: + - arduino_nesso_n1 - m5stack_atom - m5stack_atoms3 - m5stack_atoms3r - m5stack_capsule -# - m5stack_cardputer + - m5stack_cardputer +# - m5stack_chain_dualkey - m5stack_core - m5stack_core2 - m5stack_coreink @@ -81,22 +83,30 @@ jobs: - m5stack_dial - m5stack_dinmeter - m5stack_fire + - m5stack_nano_c6 +# - m5stack_nano_h2 - m5stack_paper +# - m5stack_papers3 # - m5stack_poe_cam +# - m5stack_powerhub # - m5stack_stamp_c3 # - m5stack_stamp_pico - m5stack_stamp_s3 +# - m5stack_stamplc # - m5stack_station -# - m5stack_stickc + - m5stack_stickc - m5stack_stickc_plus - m5stack_stickc_plus2 + - m5stack_sticks3 + - m5stack_tab5 # - m5stack_timer_cam # - m5stack_tough +# - m5stack_unit_c6l # - m5stack_unit_cam # - m5stack_unit_cams3 platform-version: - - 3.2.1 + - 3.2.5 platform: - m5stack @@ -107,8 +117,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} # Build - name: Compile examples diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml index 83c1c96..9554f74 100644 --- a/.github/workflows/doxygen-gh-pages.yml +++ b/.github/workflows/doxygen-gh-pages.yml @@ -3,6 +3,8 @@ on: [release, workflow_dispatch] # branches: # - main # - master +permissions: + contents: write defaults: run: shell: bash diff --git a/.github/workflows/platformio-build-check.yml b/.github/workflows/platformio-build-check.yml index 41f67fc..2579f40 100644 --- a/.github/workflows/platformio-build-check.yml +++ b/.github/workflows/platformio-build-check.yml @@ -46,11 +46,11 @@ jobs: build: name: ${{ matrix.unit }}:${{ matrix.example }}@${{ matrix.board }}:${{ matrix.framework }}:${{ matrix.espressif32 }} runs-on: ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 12 strategy: fail-fast: false - #max-parallel: 1 + max-parallel: 20 matrix: example: @@ -79,50 +79,19 @@ jobs: - StickCPlus2 - Paper - CoreInk + - Cardputer + - Tab5 + - NessoN1 framework: - Arduino espressif32: - latest -# - '5_4_0' -# - '4_4_0' - -# exclude: -# - board: CoreS3 -# espressif32: '5_4_0' -# - board: CoreS3 -# espressif32: '4_4_0' -# - board: StampS3 -# espressif32: '5_4_0' -# - board: StampS3 -# espressif32: '4_4_0' -# - board: AtomS3 -# espressif32: '5_4_0' -# - board: AtomS3 -# espressif32: '4_4_0' -# - board: Dial -# espressif32: '5_4_0' -# - board: Dial -# espressif32: '4_4_0' -# - board: NanoC6 -# espressif32: '5_4_0' -# - board: NanoC6 -# espressif32: '4_4_0' -# - board: StickCPlus -# espressif32: '5_4_0' -# - board: StickCPlus -# espressif32: '4_4_0' -# - board: Paper -# espressif32: '5_4_0' -# - board: Paper -# espressif32: '4_4_0' steps: - name: Checkout uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - name: Build examples uses: karniv00l/platformio-run-action@v1 diff --git a/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp index 1af26ad..486046f 100644 --- a/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp @@ -6,10 +6,10 @@ /* Example using M5UnitUnified for UnitCO2 */ -// #define USING_M5HAL // When using M5HAL #include #include #include +#include // For NessoN1 namespace { auto& lcd = M5.Display; @@ -20,38 +20,46 @@ m5::unit::UnitCO2 unit; void setup() { M5.begin(); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } 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); + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); + 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); + } else { + // Using TwoWire + 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); + } } } -#endif M5_LOGI("M5UnitUnified has been begun"); M5_LOGI("%s", Units.debugInfo().c_str()); @@ -95,5 +103,10 @@ void loop() // 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()); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 3, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("CO2:%u\nTemperature:%2.2f\nHumidity:%2.2f", unit.co2(), unit.temperature(), unit.humidity()); + lcd.endWrite(); } } diff --git a/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp index 5cd33c6..feb67b8 100644 --- a/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp @@ -6,10 +6,10 @@ /* Example using M5UnitUnified for UnitCO2L */ -// #define USING_M5HAL // When using M5HAL #include #include #include +#include // For NessoN1 namespace { auto& lcd = M5.Display; @@ -23,38 +23,46 @@ using namespace m5::unit::scd4x; void setup() { M5.begin(); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } 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); + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); + 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); + } else { + // Using TwoWire + 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); + } } } -#endif M5_LOGI("M5UnitUnified has been begun"); M5_LOGI("%s", Units.debugInfo().c_str()); @@ -99,7 +107,6 @@ void setup() void loop() { M5.update(); - auto touch = M5.Touch.getDetail(); // Periodic Units.update(); @@ -107,10 +114,15 @@ void loop() // 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()); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 3, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("CO2:%u\nTemperature:%2.2f\nHumidity:%2.2f", unit.co2(), unit.temperature(), unit.humidity()); + lcd.endWrite(); } // Single shot - if (M5.BtnA.wasClicked() || touch.wasClicked()) { + if (M5.BtnA.wasClicked()) { static bool all{}; // false: RHT only all = !all; M5.Log.printf("Try single shot %u, waiting measurement...\n", all); diff --git a/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp index 3956e0e..b57ab58 100644 --- a/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp @@ -9,8 +9,7 @@ #include #include #include - -// #define USING_M5HAL // When using M5HAL +#include // For NessoN1 // Using single shot measurement If defined // #define USING_SINGLE_SHOT @@ -43,10 +42,11 @@ auto& qmp6988 = unitQMP6988; 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); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } #if defined(USING_SINGLE_SHOT) { @@ -61,62 +61,50 @@ void setup() } #endif + 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); + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); #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); - } - } + if (!Units.add(unitENV3, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { #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); - } - } + if (!Units.add(unitSHT30, i2c_bus ? i2c_bus.value() : nullptr) || + !Units.add(unitQMP6988, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { #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); + M5_LOGE("Failed to begin"); + lcd.clear(TFT_RED); + while (true) { + m5::utility::delay(10000); + } } - } + } else { + // Using TwoWire + 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 defined(USING_ENV3) + if (!Units.add(unitENV3, Wire) || !Units.begin()) { #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); + if (!Units.add(unitSHT30, Wire) || !Units.add(unitQMP6988, Wire) || !Units.begin()) { +#endif + M5_LOGE("Failed to begin"); + M5_LOGW("%s", Units.debugInfo().c_str()); + 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()); @@ -145,9 +133,19 @@ void loop() #else if (sht30.updated()) { M5.Log.printf(">SHT30Temp:%2.2f\n>Humidity:%2.2f\n", sht30.temperature(), sht30.humidity()); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 3, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("SHT30\nTemp:%2.2f\nHumidity:%2.2f", sht30.temperature(), sht30.humidity()); + lcd.endWrite(); } if (qmp6988.updated()) { M5.Log.printf(">QMP6988Temp:%2.2f\n>Pressure:%.2f\n", qmp6988.temperature(), qmp6988.pressure() * 0.01f); + lcd.startWrite(); + lcd.fillRect(0, lcd.fontHeight() * 3, lcd.width(), lcd.fontHeight() * 3, TFT_BLACK); + lcd.setCursor(0, lcd.fontHeight() * 3); + lcd.printf("QMP6988\nTemp:%2.2f\nPressure:%.2f", qmp6988.temperature(), qmp6988.pressure() * 0.01f); + lcd.endWrite(); } #endif } diff --git a/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp index 00b05b9..92d5ed3 100644 --- a/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp @@ -9,8 +9,10 @@ #include #include #include +#include // For NessoN1 #include +// Using combined unit if defined #define USING_ENV4 namespace { @@ -44,10 +46,14 @@ float calculate_altitude(const float pressure, const float seaLvhPa = 1013.25f) void setup() { M5.begin(); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } 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; @@ -59,28 +65,47 @@ void setup() bmp280.config(cfg); } + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); #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); + if (!Units.add(unitENV4, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { +#else + if (!Units.add(unitSHT40, i2c_bus ? i2c_bus.value() : nullptr) || + !Units.add(unitBMP280, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { +#endif + M5_LOGE("Failed to begin"); + lcd.clear(TFT_RED); + while (true) { + m5::utility::delay(10000); + } } - } + } else { + // Using TwoWire + 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 defined(USING_ENV4) + if (!Units.add(unitENV4, Wire) || !Units.begin()) { #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); + if (!Units.add(unitSHT40, Wire) || !Units.add(unitBMP280, Wire) || !Units.begin()) { +#endif + 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()); @@ -97,6 +122,16 @@ void loop() ">SHT40Temp:%.4f\n" ">Humidity:%.4f\n", sht40.temperature(), sht40.humidity()); + + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 3, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf( + "SHT40\n" + "Temp:%.4f\n" + "Humidity:%.4f", + sht40.temperature(), sht40.humidity()); + lcd.endWrite(); } if (bmp280.updated()) { auto p = bmp280.pressure(); @@ -105,5 +140,16 @@ void loop() ">Pressure:%.4f\n" ">Altitude:%.4f\n", bmp280.temperature(), p * 0.01f /* To hPa */, calculate_altitude(p)); + + lcd.startWrite(); + lcd.fillRect(0, lcd.fontHeight() * 3, lcd.width(), lcd.fontHeight() * 4, TFT_BLACK); + lcd.setCursor(0, lcd.fontHeight() * 3); + lcd.printf( + "BMP280\n" + "Temp:%.4f\n" + "Pressure:%.4f\n" + "Altitude:%.4f", + bmp280.temperature(), p * 0.01f /* To hPa */, calculate_altitude(p)); + lcd.endWrite(); } } diff --git a/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp index a7ff756..ab92c59 100644 --- a/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp @@ -9,6 +9,7 @@ #include #include #include +#include // For NessoN1 namespace { auto& lcd = M5.Display; @@ -19,18 +20,44 @@ m5::unit::UnitENVPro unit; void setup() { M5.begin(); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } 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); + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); + 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 { + // Using TwoWire + 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); + } } } @@ -47,10 +74,22 @@ void loop() #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()); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 5, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("IAQ:%.2f\nTemperature:%.2f\nPressure:%.2f\nHumidity:%.2f\nGAS:%.2f", unit.iaq(), unit.temperature(), + unit.pressure(), unit.humidity(), unit.gas()); + lcd.endWrite(); #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); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 4, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("Temperature:%.2f\nPressure:%.2f\nHumidity:%.2f\nGAS:%.2f", unit.temperature(), unit.pressure(), + unit.humidity(), unit.gas()); + lcd.endWrite(); + // m5::utility::delay(1000); #endif } } diff --git a/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp index 2564b25..25427c5 100644 --- a/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include // For NessoN1 namespace { auto& lcd = M5.Display; @@ -21,26 +21,53 @@ m5::unit::UnitTVOC unit; void setup() { M5.begin(); + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } 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); + // For NessoN1 GROVE + if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { + // Port A of the NessoN1 is QWIIC, then use portB (GROVE) + pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); + // Wire is used internally, so SoftwareI2C handles the unit + 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); + M5_LOGI("Bus:%d", i2c_bus.has_value()); + 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 { + // Using TwoWire + 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); + M5.Log.printf("SGP30 measurement starts 15 seconds after begin\n"); + lcd.printf("SGP30 measurement starts 15 seconds after begin"); } void loop() @@ -51,6 +78,11 @@ void loop() // 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()); + M5.Log.printf(">CO2eq:%u\n>TVOC:%u\n", unit.co2eq(), unit.tvoc()); + lcd.startWrite(); + lcd.fillRect(0, 0, lcd.width(), lcd.fontHeight() * 2, TFT_BLACK); + lcd.setCursor(0, 0); + lcd.printf("CO2eq:%u\nTVOC:%u", unit.co2eq(), unit.tvoc()); + lcd.endWrite(); } } diff --git a/platformio.ini b/platformio.ini index a1aca77..2c03920 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,12 +67,14 @@ lib_deps = ${env.lib_deps} m5stack/M5Dial [AtomMatrix] +;include AtomLite extends = m5base board = m5stack-atom lib_deps = ${env.lib_deps} ${bsec2.lib_deps} [AtomS3] +;include AtomEchoS3R extends = m5base board = m5stack-atoms3 lib_deps = ${env.lib_deps} @@ -89,12 +91,8 @@ lib_deps = ${env.lib_deps} [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} +board_build.partitions = default.csv [StickCPlus] extends = m5base @@ -121,6 +119,34 @@ board = m5stack-coreink lib_deps = ${env.lib_deps} ${bsec2.lib_deps} +[Cardputer] +extends = m5base +board = esp32-s3-devkitc-1 +build_flags = + -DESP32S3 + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 +lib_deps = ${env.lib_deps} + ${bsec2.lib_deps} + + +[Tab5] +extends = m5base +board = esp32-p4-evboard +board_build.mcu = esp32p4 +board_build.flash_mode = qio +build_flags = + -DBOARD_HAS_PSRAM + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 +lib_deps = ${env.lib_deps} + +[NessoN1] +extends = m5base +board = arduino_nesso_n1 +lib_deps = ${env.lib_deps} + + [sdl] build_flags = -O3 -xc++ -std=c++14 -lSDL2 -arch arm64 ; for arm mac @@ -136,6 +162,10 @@ lib_deps = ${env.lib_deps} ; -------------------------------- ;Choose framework [arduino_latest] +platform = espressif32 @ 6.12.0 +framework = arduino + +[arduino_6_8_1] platform = espressif32 @ 6.8.1 framework = arduino @@ -159,6 +189,17 @@ framework = arduino ;platform = espressif32 @ 3.5.0 ;framework = arduino +[nanoc6_latest] +platform = espressif32 @ 6.12.0 +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 +framework = arduino + +[pioarduino_latest] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip@55.3.36 +framework = arduino + [esp-idf] platform = espressif32 @ 6.8.1 framework = espidf diff --git a/src/idf_component.yml b/src/idf_component.yml new file mode 100644 index 0000000..d752765 --- /dev/null +++ b/src/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/src/idf_component.yml.orig b/src/idf_component.yml.orig new file mode 100644 index 0000000..d752765 --- /dev/null +++ b/src/idf_component.yml.orig @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/src/unit/unit_BME688.cpp b/src/unit/unit_BME688.cpp index 6e3b32e..63947be 100644 --- a/src/unit/unit_BME688.cpp +++ b/src/unit/unit_BME688.cpp @@ -527,8 +527,8 @@ bool UnitBME688::writeCalibration(const bme688::bme68xCalibration& c) array2[CALIBRATION_RES_HEAT_VAL - CALIBRATION_GROUP_2] = c.res_heat_val; return writeRegister(CALIBRATION_GROUP_0, array0.data(), array0.size()) && - writeRegister(CALIBRATION_GROUP_1, array0.data(), array1.size()) && - writeRegister(CALIBRATION_GROUP_2, array0.data(), array2.size()); + writeRegister(CALIBRATION_GROUP_1, array1.data(), array1.size()) && + writeRegister(CALIBRATION_GROUP_2, array2.data(), array2.size()); } bool UnitBME688::readTPHSetting(bme688::bme68xConf& s) diff --git a/src/unit/unit_BME688.hpp b/src/unit/unit_BME688.hpp index dff9c50..f810e37 100644 --- a/src/unit/unit_BME688.hpp +++ b/src/unit/unit_BME688.hpp @@ -430,7 +430,7 @@ class UnitBME688 : public Component, public PeriodicMeasurementAdapter #include @@ -185,7 +185,7 @@ class UnitBMP280 : public Component, public PeriodicMeasurementAdapter UnitENV3::ensure_adapter(const uint8_t ch) { - if (ch > 2) { + if (ch >= 2) { M5_LIB_LOGE("Invalid channel %u", ch); return std::make_shared(); // Empty adapter } diff --git a/src/unit/unit_ENV4.cpp b/src/unit/unit_ENV4.cpp index 75c63d9..7a0da9a 100644 --- a/src/unit/unit_ENV4.cpp +++ b/src/unit/unit_ENV4.cpp @@ -31,7 +31,7 @@ UnitENV4::UnitENV4(const uint8_t addr) : Component(addr) std::shared_ptr UnitENV4::ensure_adapter(const uint8_t ch) { - if (ch > 2) { + if (ch >= 2) { M5_LIB_LOGE("Invalid channel %u", ch); return std::make_shared(); // Empty adapter } diff --git a/src/unit/unit_QMP6988.cpp b/src/unit/unit_QMP6988.cpp index f317df3..290381f 100644 --- a/src/unit/unit_QMP6988.cpp +++ b/src/unit/unit_QMP6988.cpp @@ -20,8 +20,8 @@ using namespace m5::unit::qmp6988::command; namespace { constexpr uint8_t chip_id{0x5C}; -constexpr size_t calibration_length{25}; -constexpr uint32_t sub_raw{8388608}; // 2^23 +constexpr size_t CALIBRATION_LENGTH{25}; +constexpr uint32_t SUB_RAW{8388608}; // 2^23 constexpr Oversampling osrss_table[][2] = { // Pressure, Temperature @@ -129,8 +129,6 @@ int32_t convert_pressure16(const int32_t dp, const int16_t tx, const Calibration return p16; } -} // namespace - struct CtrlMeas { Oversampling osrs_t() const { @@ -171,6 +169,8 @@ struct IOSetup { uint8_t value{}; }; +} // namespace + namespace m5 { namespace unit { @@ -179,7 +179,7 @@ float Data::celsius() const { uint32_t rt = (((uint32_t)raw[3]) << 16) | (((uint32_t)raw[4]) << 8) | ((uint32_t)raw[5]); if (calib && rt) { - int32_t dt = (int32_t)(rt - sub_raw); + int32_t dt = (int32_t)(rt - SUB_RAW); int16_t t256 = convert_temperature256(dt, *calib); return (float)t256 / 256.f; } @@ -197,15 +197,15 @@ float Data::pressure() const uint32_t rp = (((uint32_t)raw[0]) << 16) | (((uint32_t)raw[1]) << 8) | ((uint32_t)raw[2]); if (calib && rt && rp) { - int32_t dt = (int32_t)(rt - sub_raw); + int32_t dt = (int32_t)(rt - SUB_RAW); int16_t t256 = convert_temperature256(dt, *calib); - int32_t dp = (int32_t)(rp - sub_raw); + int32_t dp = (int32_t)(rp - SUB_RAW); int32_t p16 = convert_pressure16(dp, t256, *calib); return (float)p16 / 16.0f; } return std::numeric_limits::quiet_NaN(); } -}; // namespace qmp6988 +} // namespace qmp6988 // const char UnitQMP6988::name[] = "UnitQMP6988"; @@ -249,6 +249,7 @@ bool UnitQMP6988::begin() M5_LIB_LOGE("This unit is NOT QMP6988 %x", id); return false; } + M5_LIB_LOGE("ChipID:%02X", id); if (!softReset()) { M5_LIB_LOGE("Failed to reset"); @@ -514,14 +515,18 @@ bool UnitQMP6988::softReset() { constexpr uint8_t v{0xE6}; // When inputting "E6h", a soft-reset will be occurred - auto ret = writeRegister8(SOFT_RESET, v); - M5_LIB_LOGD("Reset causes a NO ACK or timeout error, but ignore it"); - (void)ret; + // Reset causes a NO ACK or timeout error, but ignore it + (void)writeRegister8(SOFT_RESET, v); m5::utility::delay(10); // Need delay - if (writeRegister(SOFT_RESET, 0x00)) { - _periodic = false; - return true; - } + + auto timeout_at = m5::utility::millis() + 1000; + do { + uint8_t id{}; + if (readRegister8(CHIP_ID, id, 0) && id == chip_id) { + return true; + } + m5::utility::delay(1); + } while (m5::utility::millis() <= timeout_at); return false; } @@ -551,7 +556,8 @@ bool UnitQMP6988::read_calibration(qmp6988::Calibration& c) using namespace m5::utility; // unsigned_to_signed using namespace m5::types; // big_uint16_t - uint8_t rbuf[calibration_length]{}; + uint8_t rbuf[CALIBRATION_LENGTH]{}; + if (!readRegister(READ_COMPENSATION_COEFFICIENT, rbuf, sizeof(rbuf), 0)) { return false; } diff --git a/src/unit/unit_QMP6988.hpp b/src/unit/unit_QMP6988.hpp index 44f11a3..c1c59a8 100644 --- a/src/unit/unit_QMP6988.hpp +++ b/src/unit/unit_QMP6988.hpp @@ -59,7 +59,7 @@ enum class OversamplingSetting : uint8_t { /*! @enum Filter - @brief Filtter setting + @brief Filter setting */ enum class Filter : uint8_t { Off, //!< Off filter @@ -122,7 +122,7 @@ struct Data { const Calibration* calib{}; }; -}; // namespace qmp6988 +} // namespace qmp6988 /*! @class UnitQMP6988 @@ -153,7 +153,8 @@ class UnitQMP6988 : public Component, public PeriodicMeasurementAdapter(1)} { auto ccfg = component_config(); - ccfg.clock = 400 * 1000U; + ccfg.clock = 100 * 1000U; + // QMP6988 datasheet: if bus >400 kbit/s and shared, wait >=1 ms before access component_config(ccfg); } virtual ~UnitQMP6988() @@ -166,7 +167,7 @@ class UnitQMP6988 : public Component, public PeriodicMeasurementAdapter BUF_SIZE || !readRegister(reg, tmp, rlen + 1, duration)) { return false; } @@ -509,15 +510,16 @@ bool UnitSCD40::read_register(const uint16_t reg, uint8_t* rbuf, const uint32_t bool UnitSCD40::write_register(const uint16_t reg, uint8_t* wbuf, const uint32_t wlen) { - uint8_t buf[wlen + 1]{}; - if (!wbuf || !wlen) { + constexpr uint32_t BUF_SIZE{16}; + uint8_t buf[BUF_SIZE + 1]{}; + if (!wbuf || !wlen || wlen > BUF_SIZE) { return false; } memcpy(buf, wbuf, wlen); m5::utility::CRC8_Checksum crc{}; auto crc8 = crc.range(wbuf, wlen); buf[wlen] = crc8; - return writeRegister(reg, buf, sizeof(buf)); + return writeRegister(reg, buf, wlen + 1); } bool UnitSCD40::delay_true(const uint32_t duration) diff --git a/src/unit/unit_SCD40.hpp b/src/unit/unit_SCD40.hpp index 59acc4f..365205d 100644 --- a/src/unit/unit_SCD40.hpp +++ b/src/unit/unit_SCD40.hpp @@ -187,7 +187,7 @@ class UnitSCD40 : public Component, public PeriodicMeasurementAdapter>>>>> %u", inceptive_tvoc); - m5::utility::CRC8_Checksum crc; std::array buf{}; m5::types::big_uint16_t tt(inceptive_tvoc); diff --git a/src/unit/unit_SGP30.hpp b/src/unit/unit_SGP30.hpp index 019bdd6..8999129 100644 --- a/src/unit/unit_SGP30.hpp +++ b/src/unit/unit_SGP30.hpp @@ -51,9 +51,9 @@ struct Feature { } /*! @brief product version - @note Please note that the last 5 bits of the productversion (bits 12-16 + @note Please note that the last 5 bits of the product version (bits 12-16 of the LSB) are subject to change - @note This is used to track new features added tothe SGP multi-pixel + @note This is used to track new features added to the SGP multi-pixel platform */ uint8_t productVersion() const @@ -274,7 +274,7 @@ class UnitSGP30 : public Component, public PeriodicMeasurementAdapter MAX_HEATER_DUTY) { - M5_LIB_LOGW("duty range is invalid %f. duty (0.0, 0.05]"); + M5_LIB_LOGW("duty range is invalid %f. duty (0.0, 0.05]", duty); return false; } diff --git a/src/unit/unit_SHT40.hpp b/src/unit/unit_SHT40.hpp index 2061507..1729aa8 100644 --- a/src/unit/unit_SHT40.hpp +++ b/src/unit/unit_SHT40.hpp @@ -103,7 +103,7 @@ class UnitSHT40 : public Component, public PeriodicMeasurementAdapter -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> -[env:UnitCO2_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> - -[env:UnitCO2_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> - [env:UnitCO2_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> -[env:UnitCO2_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> - -[env:UnitCO2_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> - [env:UnitCO2_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> @@ -224,7 +245,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> [env:UnitCO2_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> [env:UnitCO2_PlotToSerial_StickCPlus_Arduino_latest] @@ -247,39 +268,28 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/Plot extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> -[env:UnitCO2_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitCO2_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> + +[env:UnitCO2_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> -[env:UnitCO2_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitCO2_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> + ; UnitCO2L [env:UnitCO2L_PlotToSerial_Core_Arduino_latest] extends=Core, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> -[env:UnitCO2L_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> - -[env:UnitCO2L_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> - [env:UnitCO2L_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> -[env:UnitCO2L_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> - -[env:UnitCO2L_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> - [env:UnitCO2L_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> @@ -305,7 +315,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> [env:UnitCO2L_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> [env:UnitCO2L_PlotToSerial_StickCPlus_Arduino_latest] @@ -328,10 +338,15 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/Plo extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> -[env:UnitCO2L_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitCO2L_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> -[env:UnitCO2L_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitCO2L_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> + +[env:UnitCO2L_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> + diff --git a/unit_env3_env.ini b/unit_env3_env.ini index 4472049..d45d4c1 100644 --- a/unit_env3_env.ini +++ b/unit_env3_env.ini @@ -58,7 +58,7 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_sht30 [env:test_SHT30_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht30 @@ -87,6 +87,24 @@ lib_deps = ${CoreInk.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht30 +[env:test_SHT30_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + +[env:test_SHT30_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + +[env:test_SHT30_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + ; QMP6988 [env:test_QMP6988_Core] extends=Core, option_release, arduino_latest @@ -144,7 +162,7 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_qmp6988 [env:test_QMP6988_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 @@ -173,32 +191,34 @@ lib_deps = ${CoreInk.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 +[env:test_QMP6988_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + +[env:test_QMP6988_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + +[env:test_QMP6988_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + ;Examples ;;Unit ENVIII [env:UnitENVIII_PlotToSerial_Core_Arduino_latest] extends=Core, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> -[env:UnitENVIII_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> - -[env:UnitENVIII_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> - [env:UnitENVIII_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> -[env:UnitENVIII_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> - -[env:UnitENVIII_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> - [env:UnitENVIII_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> @@ -224,7 +244,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> [env:UnitENVIII_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> [env:UnitENVIII_PlotToSerial_StickCPlus_Arduino_latest] @@ -247,10 +267,15 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/P extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> -[env:UnitENVIII_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitENVIII_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> -[env:UnitENVIII_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitENVIII_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> + +[env:UnitENVIII_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> + diff --git a/unit_env4_env.ini b/unit_env4_env.ini index d2bd905..33d7709 100644 --- a/unit_env4_env.ini +++ b/unit_env4_env.ini @@ -144,7 +144,7 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_bmp280 [env:test_BMP280_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bmp280 @@ -173,31 +173,33 @@ lib_deps = ${CoreInk.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bmp280 +[env:test_BMP280_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bmp280 + +[env:test_BMP280_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bmp280 + +[env:test_BMP280_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bmp280 + ;Examples [env:UnitENVIV_PlotToSerial_Core_Arduino_latest] extends=Core, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> -[env:UnitENVIV_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> - -[env:UnitENVIV_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> - [env:UnitENVIV_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> -[env:UnitENVIV_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> - -[env:UnitENVIV_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> - [env:UnitENVIV_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> @@ -223,7 +225,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> [env:UnitENVIV_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> [env:UnitENVIV_PlotToSerial_StickCPlus_Arduino_latest] @@ -246,11 +248,15 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/Pl extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> -[env:UnitENVIV_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitENVIV_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> + +[env:UnitENVIV_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> -[env:UnitENVIV_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitENVIV_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> diff --git a/unit_envpro_env.ini b/unit_envpro_env.ini index e189bef..82daf91 100644 --- a/unit_envpro_env.ini +++ b/unit_envpro_env.ini @@ -58,7 +58,7 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_bme688 [env:test_BME688_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bme688 @@ -87,32 +87,34 @@ lib_deps = ${CoreInk.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bme688 +[env:test_BME688_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bme688 + +[env:test_BME688_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bme688 + +[env:test_BME688_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bme688 + ;Examples ; UnitENVPro [env:UnitENVPro_PlotToSerial_Core_Arduino_latest] extends=Core, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> -[env:UnitENVPro_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> - -[env:UnitENVPro_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> - [env:UnitENVPro_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> -[env:UnitENVPro_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> - -[env:UnitENVPro_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> - [env:UnitENVPro_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> @@ -138,7 +140,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> [env:UnitENVPro_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> [env:UnitENVPro_PlotToSerial_StickCPlus_Arduino_latest] @@ -161,10 +163,15 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/P extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> -[env:UnitENVPro_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitENVPro_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> -[env:UnitENVPro_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitENVPro_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> + +[env:UnitENVPro_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> + diff --git a/unit_tvoc_env.ini b/unit_tvoc_env.ini index 8b1f0f7..5ebfefa 100644 --- a/unit_tvoc_env.ini +++ b/unit_tvoc_env.ini @@ -56,7 +56,7 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_sgp30 [env:test_SGP30_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sgp30 @@ -85,31 +85,33 @@ lib_deps = ${CoreInk.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sgp30 +[env:test_SGP30_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sgp30 + +[env:test_SGP30_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sgp30 + +[env:test_SGP30_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sgp30 + ;Examples [env:UnitTVOC_PlotToSerial_Core_Arduino_latest] extends=Core, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> -[env:UnitTVOC_PlotToSerial_Core_Arduino_5_4_0] -extends=Core, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> - -[env:UnitTVOC_PlotToSerial_Core_Arduino_4_4_0] -extends=Core, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> - [env:UnitTVOC_PlotToSerial_Core2_Arduino_latest] extends=Core2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> -[env:UnitTVOC_PlotToSerial_Core2_Arduino_5_4_0] -extends=Core2, option_release, arduino_5_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> - -[env:UnitTVOC_PlotToSerial_Core2_Arduino_4_4_0] -extends=Core2, option_release, arduino_4_4_0 -build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> - [env:UnitTVOC_PlotToSerial_CoreS3_Arduino_latest] extends=CoreS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> @@ -137,7 +139,7 @@ extends=Dial, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> [env:UnitTVOC_PlotToSerial_NanoC6_Arduino_latest] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> [env:UnitTVOC_PlotToSerial_StickCPlus_Arduino_latest] @@ -160,11 +162,15 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/Plo extends=Fire, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> -[env:UnitTVOC_PlotToSerial_Fire_Arduino_5_4_0] -extends=Fire, option_release, arduino_5_4_0 +[env:UnitTVOC_PlotToSerial_Cardputer_Arduino_latest] +extends=Cardputer, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> + +[env:UnitTVOC_PlotToSerial_Tab5_Arduino_latest] +extends=Tab5, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> -[env:UnitTVOC_PlotToSerial_Fire_Arduino_4_4_0] -extends=Fire, option_release, arduino_4_4_0 +[env:UnitTVOC_PlotToSerial_NessoN1_Arduino_latest] +extends=NessoN1, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> From 146e89a9605f2bb0b185750c4a2f917f54e02cdb Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 10 Feb 2026 19:22:06 +0900 Subject: [PATCH 02/22] Delete junk files --- src/idf_component.yml | 2 -- src/idf_component.yml.orig | 2 -- 2 files changed, 4 deletions(-) delete mode 100644 src/idf_component.yml delete mode 100644 src/idf_component.yml.orig diff --git a/src/idf_component.yml b/src/idf_component.yml deleted file mode 100644 index d752765..0000000 --- a/src/idf_component.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - idf: '>=5.1' diff --git a/src/idf_component.yml.orig b/src/idf_component.yml.orig deleted file mode 100644 index d752765..0000000 --- a/src/idf_component.yml.orig +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - idf: '>=5.1' From 5276d5305d16c47d93b615cd34b28dd5803f676c Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 10 Feb 2026 21:05:27 +0900 Subject: [PATCH 03/22] Add an example for the SHT30 built into the M5Paper --- .../workflows/arduino-esp-v3-build-check.yml | 11 ++ .github/workflows/arduino-m5-build-check.yml | 11 ++ .github/workflows/platformio-build-check.yml | 11 ++ examples/UnitUnified/Paper/Paper.ino | 9 ++ examples/UnitUnified/Paper/main/Paper.cpp | 144 ++++++++++++++++++ unit_env3_env.ini | 4 + 6 files changed, 190 insertions(+) create mode 100644 examples/UnitUnified/Paper/Paper.ino create mode 100644 examples/UnitUnified/Paper/main/Paper.cpp diff --git a/.github/workflows/arduino-esp-v3-build-check.yml b/.github/workflows/arduino-esp-v3-build-check.yml index 579b5c4..bfbad5b 100644 --- a/.github/workflows/arduino-esp-v3-build-check.yml +++ b/.github/workflows/arduino-esp-v3-build-check.yml @@ -106,6 +106,17 @@ jobs: archi: - esp32 + include: + # Specific sketches + # Paper + - sketch: Paper + platform-url: https://espressif.github.io/arduino-esp32/package_esp32_index.json + platform: esp32 + archi: esp32 + platform-version: 3.3.6 + board: m5stack_paper + unit: '' + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/arduino-m5-build-check.yml b/.github/workflows/arduino-m5-build-check.yml index 100166b..a656baa 100644 --- a/.github/workflows/arduino-m5-build-check.yml +++ b/.github/workflows/arduino-m5-build-check.yml @@ -114,6 +114,17 @@ jobs: archi: - esp32 + include: + # Specific sketches + # Paper + - sketch: Paper + platform-url: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json + platform: m5stack + archi: esp32 + platform-version: 3.2.5 + board: m5stack_paper + unit: '' + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/platformio-build-check.yml b/.github/workflows/platformio-build-check.yml index 2579f40..781dcef 100644 --- a/.github/workflows/platformio-build-check.yml +++ b/.github/workflows/platformio-build-check.yml @@ -89,6 +89,17 @@ jobs: espressif32: - latest + + include: + # Specific sketches + # Paper + - example: Paper + unit: BuiltinSHT30 + board: Paper + framework: Arduino + espressif32: latest + + steps: - name: Checkout uses: actions/checkout@v4 diff --git a/examples/UnitUnified/Paper/Paper.ino b/examples/UnitUnified/Paper/Paper.ino new file mode 100644 index 0000000..954cb58 --- /dev/null +++ b/examples/UnitUnified/Paper/Paper.ino @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ +/* + Example of Using the M5UnitUnified for SHT30 Built into M5Paper +*/ +#include "main/Paper.cpp" diff --git a/examples/UnitUnified/Paper/main/Paper.cpp b/examples/UnitUnified/Paper/main/Paper.cpp new file mode 100644 index 0000000..cc20b1c --- /dev/null +++ b/examples/UnitUnified/Paper/main/Paper.cpp @@ -0,0 +1,144 @@ +/* + * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ +/* + Example of Using the M5UnitUnified for SHT30 Built into M5Paper +*/ +#include +#include +#include +#include + +namespace { +auto& lcd = M5.Display; +m5::unit::UnitUnified Units; +m5::unit::UnitSHT30 sht30; +float latest_temperature{}; +float latest_humidity{}; +bool has_measurement{}; +uint32_t last_lcd_update_ms{}; + +void draw_dashboard(const float temperature, const float humidity) +{ + char temp_text[32]; + char hum_text[32]; + std::snprintf(temp_text, sizeof(temp_text), "%.2f C", temperature); + std::snprintf(hum_text, sizeof(hum_text), "%.2f %%", humidity); + + const int w = lcd.width(); + const int h = lcd.height(); + + constexpr int value_x = 220; + constexpr int temp_value_y = 130; + const int humid_value_y = h / 2 + 58; + const int value_width = w - value_x - 24; + constexpr int value_height = 56; + + static bool initialized{}; + lcd.startWrite(); + if (!initialized) { + lcd.fillScreen(TFT_WHITE); + lcd.drawRoundRect(12, 12, w - 24, h - 24, 16, TFT_BLACK); + lcd.drawFastHLine(28, 88, w - 56, TFT_BLACK); + lcd.drawFastHLine(28, h / 2 + 20, w - 56, TFT_BLACK); + + lcd.setTextColor(TFT_BLACK, TFT_WHITE); + lcd.setTextSize(1); + lcd.setCursor(40, 28); + lcd.print("M5PAPER SHT30 MONITOR"); + + lcd.setCursor(40, 116); + lcd.print("TEMP"); + lcd.setCursor(40, h / 2 + 44); + lcd.print("HUMID"); + + lcd.setTextSize(1); + lcd.setCursor(w - 440, h - 44); + lcd.print("refresh:touch or 60s"); + initialized = true; + } + + lcd.fillRect(value_x, temp_value_y - 12, value_width, value_height, TFT_WHITE); + lcd.fillRect(value_x, humid_value_y - 12, value_width, value_height, TFT_WHITE); + lcd.setTextColor(TFT_BLACK, TFT_WHITE); + lcd.setTextSize(3.5f); + lcd.setCursor(value_x, temp_value_y); + lcd.print(temp_text); + lcd.setCursor(value_x, humid_value_y); + lcd.print(hum_text); + lcd.endWrite(); +} +} // namespace + +void setup() +{ + { + auto cfg = sht30.config(); + cfg.mps = m5::unit::sht30::MPS::Half; // 0.5Hz (about every 2 seconds) + sht30.config(cfg); + } + + M5.begin(); + if (M5.getBoard() != m5::board_t::board_M5Paper) { + M5_LOGE("This example is for the SHT30 sensor built into the M5Paper"); + lcd.fillScreen(TFT_RED); + while (true) { + m5::utility::delay(10000); + } + } + + M5.setTouchButtonHeightByRatio(100); + // The screen shall be in landscape mode + if (lcd.height() > lcd.width()) { + lcd.setRotation(1); + } + lcd.setFont(&fonts::Orbitron_Light_32); + + auto pin_num_sda = M5.getPin(m5::pin_name_t::in_i2c_sda); + auto pin_num_scl = M5.getPin(m5::pin_name_t::in_i2c_scl); + + M5_LOGI("Using TwoWire adapter"); + Wire.end(); + Wire.begin(pin_num_sda, pin_num_scl, 100 * 1000U); + if (!Units.add(sht30, Wire) || !Units.begin()) { + M5_LOGE("Failed to begin"); + M5_LOGW("%s", Units.debugInfo().c_str()); + lcd.fillScreen(TFT_RED); + while (true) { + m5::utility::delay(10000); + } + } + + M5_LOGI("M5UnitUnified has been begun"); + M5_LOGI("%s", Units.debugInfo().c_str()); + lcd.fillScreen(TFT_WHITE); + last_lcd_update_ms = m5::utility::millis() - 60 * 1000U; +} + +void loop() +{ + M5.update(); + Units.update(); + const auto now = m5::utility::millis(); + bool touch_redraw{}; + + if (M5.Touch.getCount()) { + const auto td = M5.Touch.getDetail(0); + touch_redraw = td.wasPressed() || td.wasClicked(); + } + + if (sht30.updated()) { + latest_temperature = sht30.temperature(); + latest_humidity = sht30.humidity(); + has_measurement = true; + + M5.Log.printf(">SHT30Temp:%2.2f\n>Humidity:%2.2f\n", latest_temperature, latest_humidity); + } + + if (has_measurement && (now - last_lcd_update_ms >= 60 * 1000U || touch_redraw)) { + draw_dashboard(latest_temperature, latest_humidity); + last_lcd_update_ms = now; + } +} diff --git a/unit_env3_env.ini b/unit_env3_env.ini index d45d4c1..87c70b0 100644 --- a/unit_env3_env.ini +++ b/unit_env3_env.ini @@ -279,3 +279,7 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/P extends=NessoN1, option_release, pioarduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> +; This example is for the SHT30 sensor built into the M5Paper +[env:BuiltinSHT30_Paper_Paper_Arduino_latest] +extends=Paper, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/Paper> From 9a53b7303f7e2797954ef7958f9d66fd2a252d6e Mon Sep 17 00:00:00 2001 From: GOB Date: Thu, 12 Feb 2026 12:43:17 +0900 Subject: [PATCH 04/22] Add more device --- .github/workflows/arduino-m5-build-check.yml | 2 +- .github/workflows/clang-format-check.yml | 2 - .github/workflows/platformio-build-check.yml | 5 +- platformio.ini | 27 ++++++++--- unit_co2_env.ini | 48 ++++++++++++++++---- unit_env3_env.ini | 44 +++++++++++++----- unit_env4_env.ini | 38 ++++++++++++---- unit_envpro_env.ini | 24 ++++++++-- unit_tvoc_env.ini | 24 ++++++++-- 9 files changed, 163 insertions(+), 51 deletions(-) diff --git a/.github/workflows/arduino-m5-build-check.yml b/.github/workflows/arduino-m5-build-check.yml index a656baa..7ce94ec 100644 --- a/.github/workflows/arduino-m5-build-check.yml +++ b/.github/workflows/arduino-m5-build-check.yml @@ -86,7 +86,7 @@ jobs: - m5stack_nano_c6 # - m5stack_nano_h2 - m5stack_paper -# - m5stack_papers3 + - m5stack_papers3 # - m5stack_poe_cam # - m5stack_powerhub # - m5stack_stamp_c3 diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 3453b52..e7d8938 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -56,8 +56,6 @@ jobs: steps: - name: Checkout # When pull_request is used, include it in the checkout https://zenn.dev/hkusu/articles/c731862051438b uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - name: Run clang-format style check for C/C++/Protobuf programs. uses: jidicula/clang-format-action@v4.10.2 # Using include-regex 10.x or later diff --git a/.github/workflows/platformio-build-check.yml b/.github/workflows/platformio-build-check.yml index 781dcef..0b8c48f 100644 --- a/.github/workflows/platformio-build-check.yml +++ b/.github/workflows/platformio-build-check.yml @@ -61,8 +61,8 @@ jobs: - UnitCO2L - UnitENVIII - UnitENVIV - - UnitTVOC - UnitENVPro + - UnitTVOC board: - Core @@ -71,12 +71,13 @@ jobs: - Fire - StampS3 - Dial - - AtomMatrix + - Atom - AtomS3 - AtomS3R - NanoC6 - StickCPlus - StickCPlus2 + - StickS3 - Paper - CoreInk - Cardputer diff --git a/platformio.ini b/platformio.ini index 2c03920..ee221f4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,10 +27,7 @@ test_ignore= native/* [Core] extends = m5base -board = m5stack-grey -;m5stack-grey -;m5stack-core-esp32-16M ;;6.8.0 or later -;m5stack-core-esp32 +board = m5stack-core-esp32-16M lib_deps = ${env.lib_deps} ${bsec2.lib_deps} @@ -66,15 +63,15 @@ lib_deps = ${env.lib_deps} ${bsec2.lib_deps} m5stack/M5Dial -[AtomMatrix] -;include AtomLite +[Atom] +;include AtomMatrix,AtomLite,AtomU extends = m5base board = m5stack-atom lib_deps = ${env.lib_deps} ${bsec2.lib_deps} [AtomS3] -;include AtomEchoS3R +;include AtomEchoS3R,AtomS3Lite,AtomS3U extends = m5base board = m5stack-atoms3 lib_deps = ${env.lib_deps} @@ -107,6 +104,21 @@ board = m5stick-cplus2 lib_deps = ${env.lib_deps} ${bsec2.lib_deps} +[StickS3] +extends = m5base +board = esp32-s3-devkitc-1 +board_build.arduino.partitions = default_8MB.csv +board_build.arduino.memory_type = qio_opi +build_flags = + -DESP32S3 + -DBOARD_HAS_PSRAM + -mfix-esp32-psram-cache-issue + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 +lib_deps = ${env.lib_deps} + ${bsec2.lib_deps} + + [Paper] extends = m5base board = m5stack-fire @@ -200,6 +212,7 @@ framework = arduino platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip@55.3.36 framework = arduino + [esp-idf] platform = espressif32 @ 6.8.1 framework = espidf diff --git a/unit_co2_env.ini b/unit_co2_env.ini index aac21dd..4580c0a 100644 --- a/unit_co2_env.ini +++ b/unit_co2_env.ini @@ -39,9 +39,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_scd40 -[env:test_SCD40_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_SCD40_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_scd40 @@ -75,6 +75,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_scd40 +[env:test_SCD40_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_scd40 + [env:test_SCD40_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -143,9 +151,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_scd41 -[env:test_SCD41_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_SCD41_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_scd41 @@ -179,6 +187,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_scd41 +[env:test_SCD41_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_scd41 + [env:test_SCD41_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -228,8 +244,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/Plot extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> -[env:UnitCO2_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitCO2_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> [env:UnitCO2_PlotToSerial_AtomS3_Arduino_latest] @@ -256,6 +272,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/Plot extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> +[env:UnitCO2_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitCO2_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> @@ -298,8 +320,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/Plo extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> -[env:UnitCO2L_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitCO2L_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> [env:UnitCO2L_PlotToSerial_AtomS3_Arduino_latest] @@ -326,6 +348,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/Plo extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> +[env:UnitCO2L_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitCO2L_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> diff --git a/unit_env3_env.ini b/unit_env3_env.ini index 87c70b0..7fd404c 100644 --- a/unit_env3_env.ini +++ b/unit_env3_env.ini @@ -39,9 +39,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_sht30 -[env:test_SHT30_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_SHT30_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht30 @@ -75,6 +75,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht30 +[env:test_SHT30_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht30 + [env:test_SHT30_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -143,9 +151,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_qmp6988 -[env:test_QMP6988_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_QMP6988_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 @@ -179,6 +187,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 +[env:test_QMP6988_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_qmp6988 + [env:test_QMP6988_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -195,19 +211,19 @@ test_filter= embedded/test_qmp6988 extends=Cardputer, option_release, arduino_latest lib_deps = ${Cardputer.lib_deps} ${test_fw.lib_deps} -test_filter= embedded/test_sht30 +test_filter= embedded/test_qmp6988 [env:test_QMP6988_Tab5] extends=Tab5, option_release, pioarduino_latest lib_deps = ${Tab5.lib_deps} ${test_fw.lib_deps} -test_filter= embedded/test_sht30 +test_filter= embedded/test_qmp6988 [env:test_QMP6988_NessoN1] extends=NessoN1, option_release, pioarduino_latest lib_deps = ${NessoN1.lib_deps} ${test_fw.lib_deps} -test_filter= embedded/test_sht30 +test_filter= embedded/test_qmp6988 ;Examples ;;Unit ENVIII @@ -227,8 +243,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/P extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> -[env:UnitENVIII_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitENVIII_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> [env:UnitENVIII_PlotToSerial_AtomS3_Arduino_latest] @@ -255,6 +271,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/P extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> +[env:UnitENVIII_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitENVIII_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> diff --git a/unit_env4_env.ini b/unit_env4_env.ini index 33d7709..1f079b1 100644 --- a/unit_env4_env.ini +++ b/unit_env4_env.ini @@ -39,9 +39,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_sht40 -[env:test_SHT40_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_SHT40_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht40 @@ -75,6 +75,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht40 +[env:test_SHT40_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht40 + [env:test_SHT40_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -125,9 +133,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_bmp280 -[env:test_BMP280_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_BMP280_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bmp280 @@ -161,6 +169,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bmp280 +[env:test_BMP280_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bmp280 + [env:test_BMP280_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -208,8 +224,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/Pl extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> -[env:UnitENVIV_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitENVIV_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> [env:UnitENVIV_PlotToSerial_AtomS3_Arduino_latest] @@ -236,6 +252,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/Pl extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> +[env:UnitENVIV_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitENVIV_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> diff --git a/unit_envpro_env.ini b/unit_envpro_env.ini index 82daf91..ac88f73 100644 --- a/unit_envpro_env.ini +++ b/unit_envpro_env.ini @@ -39,9 +39,9 @@ lib_deps = ${StampS3.lib_deps} m5stack/M5Dial test_filter= embedded/test_bme688 -[env:test_BME688_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_BME688_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bme688 @@ -75,6 +75,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_bme688 +[env:test_BME688_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_bme688 + [env:test_BME688_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -123,8 +131,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/P extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> -[env:UnitENVPro_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitENVPro_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> [env:UnitENVPro_PlotToSerial_AtomS3_Arduino_latest] @@ -151,6 +159,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/P extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> +[env:UnitENVPro_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitENVPro_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> diff --git a/unit_tvoc_env.ini b/unit_tvoc_env.ini index 5ebfefa..1caa0df 100644 --- a/unit_tvoc_env.ini +++ b/unit_tvoc_env.ini @@ -37,9 +37,9 @@ lib_deps = ${Dial.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sgp30 -[env:test_SGP30_AtomMatrix] -extends=AtomMatrix, option_release, arduino_latest -lib_deps = ${AtomMatrix.lib_deps} +[env:test_SGP30_Atom] +extends=Atom, option_release, arduino_latest +lib_deps = ${Atom.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sgp30 @@ -73,6 +73,14 @@ lib_deps = ${StickCPlus2.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sgp30 +[env:test_SGP30_StickS3] +extends=StickS3, option_release, arduino_latest +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} +lib_deps = ${StickS3.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sgp30 + [env:test_SGP30_Paper] extends=Paper, option_release, arduino_latest lib_deps = ${Paper.lib_deps} @@ -120,8 +128,8 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/Plo extends=StampS3, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> -[env:UnitTVOC_PlotToSerial_AtomMatrix_Arduino_latest] -extends=AtomMatrix, option_release, arduino_latest +[env:UnitTVOC_PlotToSerial_Atom_Arduino_latest] +extends=Atom, option_release, arduino_latest build_flags = ${option_release.build_flags} -DARDUINO_USB_CDC_ON_BOOT=0 build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> @@ -150,6 +158,12 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/Plo extends=StickCPlus2, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> +[env:UnitTVOC_PlotToSerial_StickS3_Arduino_latest] +extends=StickS3, option_release, arduino_latest +build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> +build_flags = ${StickS3.build_flags} + ${option_release.build_flags} + [env:UnitTVOC_PlotToSerial_Paper_Arduino_latest] extends=Paper, option_release, arduino_latest build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> From 63f4d485648e6d58622fb06607eb4d89414b6ee5 Mon Sep 17 00:00:00 2001 From: GOB Date: Thu, 12 Feb 2026 13:19:51 +0900 Subject: [PATCH 05/22] Fixes pin down the pioarduino version --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index ee221f4..906e557 100644 --- a/platformio.ini +++ b/platformio.ini @@ -209,7 +209,7 @@ platform_packages = framework = arduino [pioarduino_latest] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip@55.3.36 +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip framework = arduino From f128c5e7f345b18a199598282e6ed7e3a95ea330 Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 13 Feb 2026 18:25:46 +0900 Subject: [PATCH 06/22] Update clang-format-action to v4.16.0 --- .github/workflows/clang-format-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index e7d8938..9fbec79 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -58,7 +58,7 @@ jobs: uses: actions/checkout@v4 - name: Run clang-format style check for C/C++/Protobuf programs. - uses: jidicula/clang-format-action@v4.10.2 # Using include-regex 10.x or later + uses: jidicula/clang-format-action@v4.16.0 # Using include-regex 10.x or later with: clang-format-version: '13' check-path: ${{ matrix.path['check'] }} From 9340b8317c843427e0ac6e2b007c7c4c9ea727ce Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 16:25:53 +0900 Subject: [PATCH 07/22] Add no-arg startPeriodicMeasurement for SHT30/SHT40, I2C_Class guards, and fix typos --- src/idf_component.yml | 2 ++ src/idf_component.yml.orig | 2 ++ src/unit/unit_BME688.cpp | 4 ++-- src/unit/unit_BME688.hpp | 12 ++++++------ src/unit/unit_BMP280.hpp | 10 +++++++--- src/unit/unit_QMP6988.cpp | 1 + src/unit/unit_QMP6988.hpp | 10 +++++++--- src/unit/unit_SCD40.cpp | 2 +- src/unit/unit_SCD40.hpp | 8 ++++---- src/unit/unit_SCD41.cpp | 2 +- src/unit/unit_SGP30.hpp | 24 ++++++++++++------------ src/unit/unit_SHT30.cpp | 15 +++++++++++++++ src/unit/unit_SHT30.hpp | 29 ++++++++++++++++++++++++----- src/unit/unit_SHT40.cpp | 6 ++++++ src/unit/unit_SHT40.hpp | 24 ++++++++++++++++++++---- 15 files changed, 110 insertions(+), 41 deletions(-) create mode 100644 src/idf_component.yml create mode 100644 src/idf_component.yml.orig diff --git a/src/idf_component.yml b/src/idf_component.yml new file mode 100644 index 0000000..d752765 --- /dev/null +++ b/src/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/src/idf_component.yml.orig b/src/idf_component.yml.orig new file mode 100644 index 0000000..d752765 --- /dev/null +++ b/src/idf_component.yml.orig @@ -0,0 +1,2 @@ +dependencies: + idf: '>=5.1' diff --git a/src/unit/unit_BME688.cpp b/src/unit/unit_BME688.cpp index 63947be..3c43954 100644 --- a/src/unit/unit_BME688.cpp +++ b/src/unit/unit_BME688.cpp @@ -278,7 +278,7 @@ void UnitBME688::update(const bool force) } #if defined(UNIT_BME688_USING_BSEC2) -// Using BSEC2 library and configration and state +// Using BSEC2 library and configuration and state void UnitBME688::update_bsec2(const bool force) { auto now = m5::utility::millis(); @@ -955,7 +955,7 @@ bool UnitBME688::fetch_data() bool UnitBME688::process_data(bsecOutputs& outputs, const int64_t ns, const bme688::bme68xData& data) { - bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]{}; /* Temp, Pres, Hum & Gas */ + bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]{}; /* Temp, Pressure, Hum & Gas */ uint8_t nInputs{0}; /* Checks all the required sensor inputs, required for the BSEC library for * the requested outputs */ diff --git a/src/unit/unit_BME688.hpp b/src/unit/unit_BME688.hpp index f810e37..ad78f56 100644 --- a/src/unit/unit_BME688.hpp +++ b/src/unit/unit_BME688.hpp @@ -171,7 +171,7 @@ struct GasWait { } ///@} - //! @brief Conversion from duration to register value for Force/Sequencial + //! @brief Conversion from duration to register value for Force/Sequential //! mode static uint8_t from(const uint16_t duration) { @@ -183,7 +183,7 @@ struct GasWait { } return (f <= 0x03) ? ((uint8_t)d | (f << 6)) : 0xFF; } - //! @brief Conversion from register value to duration for Force/Sequencial + //! @brief Conversion from register value to duration for Force/Sequential //! mode static uint16_t to(const uint8_t v) { @@ -205,7 +205,7 @@ enum class SampleRate : uint8_t { Disabled, //!< Sample rate of a disabled sensor LowPower, //!< Sample rate in case of Low Power Mode (0.33Hz) interval 3 sec. UltraLowPower, //!< Sample rate in case of Ultra Low Power Mode (3.3 mHz) interval 300 sec. - UltraLowPowerMeasurementOnDemand, //!< Input value used to trigger an extra measurment (ULP plus) (0.33Hz + UltraLowPowerMeasurementOnDemand, //!< Input value used to trigger an extra measurement (ULP plus) (0.33Hz //!< [T,p,h] 3.3mHz [IAQ]) Scan, //!< Sample rate in case of scan mode (1/10.8 s) Continuous, //!< Sample rate in case of Continuous Mode (1Hz) interval 1 sec. @@ -429,12 +429,12 @@ class UnitBME688 : public Component, public PeriodicMeasurementAdapter::startPeriodicMeasurement( osrsPressure, osrsTemperature, filter, st); } - //! @brief Start periodic measurement using current settings + /*! + @brief Start periodic measurement using current register settings + @return True if successful + @note Reads the current standby time from sensor registers and sets PowerMode to Normal + */ inline bool startPeriodicMeasurement() { return PeriodicMeasurementAdapter::startPeriodicMeasurement(); diff --git a/src/unit/unit_QMP6988.cpp b/src/unit/unit_QMP6988.cpp index 290381f..a6f41fb 100644 --- a/src/unit/unit_QMP6988.cpp +++ b/src/unit/unit_QMP6988.cpp @@ -337,6 +337,7 @@ bool UnitQMP6988::measureSingleshot(qmp6988::Data& d, const qmp6988::Oversamplin // Need temperature for measure pressure (Only temperature measurement is acceptable) if (osrsTemperature == Oversampling::Skipped) { + M5_LIB_LOGW("osrsTemperature == Oversampling::Skipped cannot measure"); return false; } return writeOversampling(osrsPressure, osrsTemperature) && writeFilter(f) && measureSingleshot(d); diff --git a/src/unit/unit_QMP6988.hpp b/src/unit/unit_QMP6988.hpp index c1c59a8..52c49ba 100644 --- a/src/unit/unit_QMP6988.hpp +++ b/src/unit/unit_QMP6988.hpp @@ -166,12 +166,12 @@ class UnitQMP6988 : public Component, public PeriodicMeasurementAdapter::startPeriodicMeasurement(osrsPressure, osrsTemperature, f, st); } - //! @brief Start periodic measurement using current settings + /*! + @brief Start periodic measurement using current register settings + @return True if successful + @note Reads the current standby time from sensor registers and sets PowerMode to Normal + */ inline bool startPeriodicMeasurement() { return PeriodicMeasurementAdapter::startPeriodicMeasurement(); diff --git a/src/unit/unit_SCD40.cpp b/src/unit/unit_SCD40.cpp index f040bca..4b899b4 100644 --- a/src/unit/unit_SCD40.cpp +++ b/src/unit/unit_SCD40.cpp @@ -262,7 +262,7 @@ bool UnitSCD40::performForcedRecalibration(const uint16_t concentration, int16_t { // 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 + // shot) for > 3 minutes in an environment with homogeneous and constant CO2 // concentration. // 2. Issue stop_periodic_measurement. Wait 500 ms for the stop command to // complete. diff --git a/src/unit/unit_SCD40.hpp b/src/unit/unit_SCD40.hpp index 365205d..2eee392 100644 --- a/src/unit/unit_SCD40.hpp +++ b/src/unit/unit_SCD40.hpp @@ -111,12 +111,12 @@ class UnitSCD40 : public Component, public PeriodicMeasurementAdapter raw{}; //!< RAW data uint16_t co2eq() const; //!< Co2Eq (ppm) - uint16_t tvoc() const; //!< TVOC (pbb) + uint16_t tvoc() const; //!< TVOC (ppb) }; } // namespace sgp30 @@ -94,7 +94,7 @@ class UnitSGP30 : public Component, public PeriodicMeasurementAdapter +#include #include // NaN #include @@ -122,6 +123,9 @@ bool UnitSHT30::begin() M5_LIB_LOGE("Failed to heater %d", _cfg.start_heater); return false; } + + _mps = _cfg.mps; + _rep = _cfg.repeatability; return _cfg.start_periodic ? startPeriodicMeasurement(_cfg.mps, _cfg.repeatability) : true; } @@ -167,6 +171,15 @@ bool UnitSHT30::measureSingleshot(Data& d, const sht30::Repeatability rep, const return false; } + // m5::I2C_Class does not support clock stretching + if (stretch) { + auto ad = asAdapter(Adapter::Type::I2C); + if (ad && ad->implType() == AdapterI2C::ImplType::I2CClass) { + M5_LIB_LOGE("Clock stretching is not supported with I2C_Class"); + return false; + } + } + uint32_t idx = m5::stl::to_underlying(rep) + (stretch ? 0 : 3); if (idx >= m5::stl::size(cmd)) { M5_LIB_LOGE("Invalid arg : %u", (int)rep); @@ -189,6 +202,8 @@ bool UnitSHT30::start_periodic_measurement(const sht30::MPS mps, const sht30::Re _periodic = writeRegister(periodic_cmd[m5::stl::to_underlying(mps) * 3 + m5::stl::to_underlying(rep)]); if (_periodic) { + _mps = mps; + _rep = rep; _interval = interval_table[m5::stl::to_underlying(mps)]; m5::utility::delay(16); return true; diff --git a/src/unit/unit_SHT30.hpp b/src/unit/unit_SHT30.hpp index 6760503..5edbfb0 100644 --- a/src/unit/unit_SHT30.hpp +++ b/src/unit/unit_SHT30.hpp @@ -73,7 +73,7 @@ struct Status { { return value & (1U << 4); } - //! @brief Command staus + //! @brief Command status inline bool command() const { return value & (1U << 1); @@ -143,12 +143,12 @@ class UnitSHT30 : public Component, public PeriodicMeasurementAdapter::startPeriodicMeasurement(mps, rep); } + /*! + @brief Start periodic measurement using previous settings + @return True if successful + @note Uses the MPS and repeatability settings from the last successful startPeriodicMeasurement or begin + */ + inline bool startPeriodicMeasurement() + { + return PeriodicMeasurementAdapter::startPeriodicMeasurement(); + } /*! @brief Stop periodic measurement @return True if successful @@ -210,11 +219,13 @@ class UnitSHT30 : public Component, public PeriodicMeasurementAdapter> _data{}; config_t _cfg{}; + sht30::MPS _mps{}; + sht30::Repeatability _rep{}; }; ///@cond diff --git a/src/unit/unit_SHT40.cpp b/src/unit/unit_SHT40.cpp index 4cba2a3..dec63b1 100644 --- a/src/unit/unit_SHT40.cpp +++ b/src/unit/unit_SHT40.cpp @@ -96,6 +96,9 @@ bool UnitSHT40::begin() return false; } + _precision = _cfg.precision; + _heater = _cfg.heater; + _duty = _cfg.heater_duty; return _cfg.start_periodic ? startPeriodicMeasurement(_cfg.precision, _cfg.heater, _cfg.heater_duty) : true; } @@ -148,6 +151,9 @@ bool UnitSHT40::start_periodic_measurement(const sht40::Precision precision, con _periodic = writeRegister(_cmd); if (_periodic) { + _precision = precision; + _heater = heater; + _duty = duty; _duration_heater = interval_table[m5::stl::to_underlying(precision) * 3 + m5::stl::to_underlying(heater)]; _duration_measure = interval_table[m5::stl::to_underlying(precision) * 3 + m5::stl::to_underlying(Heater::None)]; diff --git a/src/unit/unit_SHT40.hpp b/src/unit/unit_SHT40.hpp index 1729aa8..77a4ab8 100644 --- a/src/unit/unit_SHT40.hpp +++ b/src/unit/unit_SHT40.hpp @@ -102,12 +102,12 @@ class UnitSHT40 : public Component, public PeriodicMeasurementAdapter::startPeriodicMeasurement(precision, heater, duty); } + /*! + @brief Start periodic measurement using previous settings + @return True if successful + @note Uses the precision, heater, and duty settings from the last successful startPeriodicMeasurement or begin + */ + inline bool startPeriodicMeasurement() + { + return startPeriodicMeasurement(_precision, _heater, _duty); + } /*! @brief Stop periodic measurement @return True if successful @@ -194,6 +203,8 @@ class UnitSHT40 : public Component, public PeriodicMeasurementAdapter> _data{}; - config_t _cfg{}; uint8_t _cmd{}, _measureCmd{}; types::elapsed_time_t _latest_heater{}, _interval_heater{}; uint32_t _duration_measure{}, _duration_heater{}; + +private: + config_t _cfg{}; + sht40::Precision _precision{sht40::Precision::High}; + sht40::Heater _heater{sht40::Heater::None}; + float _duty{0.05f}; }; ///@cond From a4d7542e7fb41787d5e2549101b8ae716a98bc72 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 16:27:51 +0900 Subject: [PATCH 08/22] Migrate tests to new test_template API and unify periodic measurement validation --- test/embedded/scd4x_test.inl | 60 ++--------- test/embedded/test_bme688/bme688_test.cpp | 64 +++++++----- test/embedded/test_bmp280/bmp280_test.cpp | 80 ++++----------- test/embedded/test_qmp6988/qmp6988_test.cpp | 85 ++++------------ test/embedded/test_scd40/scd40_test.cpp | 12 +-- test/embedded/test_scd41/scd41_test.cpp | 19 +--- test/embedded/test_sgp30/sgp30_test.cpp | 38 +++---- test/embedded/test_sht30/sht30_test.cpp | 105 ++++++++++++++------ test/embedded/test_sht40/sht40_test.cpp | 101 +++++++++---------- 9 files changed, 241 insertions(+), 323 deletions(-) diff --git a/test/embedded/scd4x_test.inl b/test/embedded/scd4x_test.inl index 9ce601c..92758af 100644 --- a/test/embedded/scd4x_test.inl +++ b/test/embedded/scd4x_test.inl @@ -14,49 +14,10 @@ constexpr uint16_t float_to_uint16(const float f) return f * 65536 / 175; } -constexpr Mode mode_table[] = {Mode::Normal, Mode::LowPower}; -constexpr uint32_t interval_table[] = { - 5 * 1000, - 30 * 1000, -}; - -template -elapsed_time_t test_periodic(U* unit, const uint32_t times, const uint32_t measure_duration = 0) -{ - auto tm = unit->interval(); - auto timeout_at = m5::utility::millis() + 10 * 1000; - - do { - unit->update(); - if (unit->updated()) { - break; - } - std::this_thread::yield(); - } while (!unit->updated() && m5::utility::millis() <= timeout_at); - // timeout - if (!unit->updated()) { - return 0; - } - - // - uint32_t measured{}; - auto start_at = m5::utility::millis(); - timeout_at = start_at + (times * (tm + measure_duration) * 2); - - do { - unit->update(); - measured += unit->updated() ? 1 : 0; - if (measured >= times) { - break; - } - m5::utility::delay(1); - - } while (measured < times && m5::utility::millis() <= timeout_at); - return (measured == times) ? m5::utility::millis() - start_at : 0; -} +constexpr Mode mode_table[] = {Mode::Normal, Mode::LowPower}; } // namespace -TEST_P(TestSCD4x, BasicCommand) +TEST_F(TestSCD4x, BasicCommand) { SCOPED_TRACE(ustr); @@ -119,7 +80,7 @@ TEST_P(TestSCD4x, BasicCommand) } } -TEST_P(TestSCD4x, OnChipOutputSignalCompensation) +TEST_F(TestSCD4x, OnChipOutputSignalCompensation) { SCOPED_TRACE(ustr); @@ -159,7 +120,7 @@ TEST_P(TestSCD4x, OnChipOutputSignalCompensation) } } -TEST_P(TestSCD4x, FieldCalibration) +TEST_F(TestSCD4x, FieldCalibration) { SCOPED_TRACE(ustr); @@ -188,7 +149,7 @@ TEST_P(TestSCD4x, FieldCalibration) } } -TEST_P(TestSCD4x, AdvancedFeatures) +TEST_F(TestSCD4x, AdvancedFeatures) { SCOPED_TRACE(ustr); @@ -284,13 +245,12 @@ TEST_P(TestSCD4x, AdvancedFeatures) EXPECT_TRUE(enabled); } -TEST_P(TestSCD4x, Periodic) +TEST_F(TestSCD4x, Periodic) { SCOPED_TRACE(ustr); EXPECT_TRUE(unit->performFactoryReset()); // Reset EEPROM - uint32_t idx{}; for (auto&& m : mode_table) { auto s = m5::utility::formatString("Mode:%u", m); SCOPED_TRACE(s); @@ -301,14 +261,14 @@ TEST_P(TestSCD4x, Periodic) EXPECT_TRUE(unit->inPeriodic()); EXPECT_EQ(unit->updatedMillis(), 0); - auto it = interval_table[idx]; - auto elapsed = test_periodic(unit.get(), STORED_SIZE, it); + auto r = collect_periodic_measurements(unit.get(), STORED_SIZE); EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); - EXPECT_NE(elapsed, 0); - EXPECT_GE(elapsed, STORED_SIZE * it); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, STORED_SIZE); + EXPECT_LE(r.median(), r.expected_interval + 1); // EXPECT_EQ(unit->available(), STORED_SIZE); diff --git a/test/embedded/test_bme688/bme688_test.cpp b/test/embedded/test_bme688/bme688_test.cpp index a98ae15..cab7d21 100644 --- a/test/embedded/test_bme688/bme688_test.cpp +++ b/test/embedded/test_bme688/bme688_test.cpp @@ -24,9 +24,7 @@ using namespace m5::unit::bme688; using namespace m5::unit::bme688::bsec2; #endif -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - -class TestBME688 : public ComponentTestBase { +class TestBME688 : public I2CComponentTestBase { protected: virtual UnitBME688* get_instance() override { @@ -36,21 +34,11 @@ class TestBME688 : public ComponentTestBase { ptr->component_config(ccfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestBME688, -// ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestBME688, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestBME688, ::testing::Values(false)); - namespace { constexpr Oversampling os_table[] = { - Oversampling::None, Oversampling::x1, Oversampling::x1, Oversampling::x2, - Oversampling::x4, Oversampling::x8, Oversampling::x16, + Oversampling::None, Oversampling::x1, Oversampling::x2, Oversampling::x4, Oversampling::x8, Oversampling::x16, }; constexpr Filter filter_table[] = { Filter::None, Filter::Coeff_1, Filter::Coeff_3, Filter::Coeff_7, @@ -104,7 +92,7 @@ void check_measurement_values(UnitBME688* u) } // namespace -TEST_P(TestBME688, Misc) +TEST_F(TestBME688, Misc) { #if defined(UNIT_BME688_USING_BSEC2) for (auto&& v : vs_table) { @@ -132,7 +120,7 @@ TEST_P(TestBME688, Misc) #endif } -TEST_P(TestBME688, Settings) +TEST_F(TestBME688, Settings) { SCOPED_TRACE(ustr); @@ -223,7 +211,7 @@ TEST_P(TestBME688, Settings) } #if defined(UNIT_BME688_USING_BSEC2) -TEST_P(TestBME688, BSEC2) +TEST_F(TestBME688, BSEC2) { SCOPED_TRACE(ustr); @@ -290,7 +278,13 @@ TEST_P(TestBME688, BSEC2) EXPECT_EQ(unit->bsec2Subscription(), bits); #if 1 - test_periodic_measurement(unit.get(), 8, 8, (unit->interval() * 2) * 8, check_measurement_values, false); + { + auto timeout = (unit->interval() * 2) * 8; + auto r = collect_periodic_measurements(unit.get(), 8, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 8U); + EXPECT_LE(r.median(), r.expected_interval + 8); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -415,7 +409,7 @@ TEST_P(TestBME688, BSEC2) } #endif -TEST_P(TestBME688, SingleShot) +TEST_F(TestBME688, SingleShot) { SCOPED_TRACE(ustr); @@ -456,7 +450,7 @@ TEST_P(TestBME688, SingleShot) #endif } -TEST_P(TestBME688, PeriodicForced) +TEST_F(TestBME688, PeriodicForced) { SCOPED_TRACE(ustr); @@ -490,7 +484,13 @@ TEST_P(TestBME688, PeriodicForced) EXPECT_TRUE(unit->empty()); EXPECT_FALSE(unit->full()); - test_periodic_measurement(unit.get(), 8, 8, (unit->interval() * 2) * 8, check_measurement_values, false); + { + auto timeout = (unit->interval() * 2) * 8; + auto r = collect_periodic_measurements(unit.get(), 8, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 8U); + EXPECT_LE(r.median(), r.expected_interval + 8); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -521,7 +521,7 @@ TEST_P(TestBME688, PeriodicForced) EXPECT_FALSE(unit->full()); } -TEST_P(TestBME688, PeriodicParallel) +TEST_F(TestBME688, PeriodicParallel) { SCOPED_TRACE(ustr); @@ -560,7 +560,13 @@ TEST_P(TestBME688, PeriodicParallel) EXPECT_FALSE(unit->full()); // TODO : What are the measurement intervals in the parallel mode datasheet? - test_periodic_measurement(unit.get(), 8, 1, (unit->interval() * 10) * 10, check_measurement_values, false); + { + auto timeout = (unit->interval() * 10) * 10; + auto r = collect_periodic_measurements(unit.get(), 8, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 8U); + EXPECT_LE(r.median(), r.expected_interval + 1); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -591,7 +597,7 @@ TEST_P(TestBME688, PeriodicParallel) EXPECT_FALSE(unit->full()); } -TEST_P(TestBME688, PeriodiSequential) +TEST_F(TestBME688, PeriodicSequential) { SCOPED_TRACE(ustr); @@ -624,14 +630,20 @@ TEST_P(TestBME688, PeriodiSequential) EXPECT_TRUE(unit->inPeriodic()); EXPECT_EQ(unit->mode(), Mode::Sequential); - test_periodic_measurement(unit.get(), 8, 1, (unit->interval() * 2) * 8, check_measurement_values, false); + { + auto timeout = (unit->interval() * 2) * 8; + auto r = collect_periodic_measurements(unit.get(), 8, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 8U); + EXPECT_LE(r.median(), r.expected_interval + 1); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); EXPECT_EQ(unit->mode(), Mode::Sleep); } -TEST_P(TestBME688, SelfTest) +TEST_F(TestBME688, SelfTest) { SCOPED_TRACE(ustr); EXPECT_TRUE(unit->selfTest()); diff --git a/test/embedded/test_bmp280/bmp280_test.cpp b/test/embedded/test_bmp280/bmp280_test.cpp index 74817e5..43fc4da 100644 --- a/test/embedded/test_bmp280/bmp280_test.cpp +++ b/test/embedded/test_bmp280/bmp280_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,9 +26,7 @@ using m5::unit::types::elapsed_time_t; constexpr uint32_t STORED_SIZE{8}; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - -class TestBMP280 : public ComponentTestBase { +class TestBMP280 : public I2CComponentTestBase { protected: virtual UnitBMP280* get_instance() override { @@ -37,10 +36,6 @@ class TestBMP280 : public ComponentTestBase { ptr->component_config(ccfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; void print_ctrl_measurement(const char* msg = "") { @@ -56,11 +51,6 @@ class TestBMP280 : public ComponentTestBase { } }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestBMP280, -// ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestBMP280, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestBMP280, ::testing::Values(false)); - namespace { constexpr Oversampling os_table[] = { @@ -115,44 +105,6 @@ constexpr UseCaseSetting uc_val_table[] = { {OversamplingSetting::UltraHighResolution, Filter::Coeff16, Standby::Time0_5ms}, }; -template -elapsed_time_t test_periodic(U* unit, const uint32_t times, const uint32_t measure_duration = 0) -{ - auto tm = unit->interval(); - auto timeout_at = m5::utility::millis() + 10 * 1000; - - do { - unit->update(); - if (unit->updated()) { - break; - } - std::this_thread::yield(); - } while (!unit->updated() && m5::utility::millis() <= timeout_at); - // timeout - if (!unit->updated()) { - return 0; - } - - // - uint32_t measured{}; - auto start_at = m5::utility::millis(); - timeout_at = start_at + (times * (tm + measure_duration) * 2); - - do { - unit->update(); - measured += unit->updated() ? 1 : 0; - if (measured >= times) { - break; - } - std::this_thread::yield(); - // m5::utility::delay(1); - - } while (measured < times && m5::utility::millis() <= timeout_at); - return (measured == times) ? m5::utility::millis() - start_at : 0; - - // return (measured == times) ? unit->updatedMillis() - start_at : 0; -} - uint32_t calculate_measure_time(const Oversampling osrsP, const Oversampling osrsT, const Filter f) { uint32_t px = ((1U << m5::stl::to_underlying(osrsP) >> 1)); @@ -173,7 +125,7 @@ uint32_t calculate_measure_time(const Oversampling osrsP, const Oversampling osr } // namespace -TEST_P(TestBMP280, Settings) +TEST_F(TestBMP280, Settings) { SCOPED_TRACE(ustr); @@ -322,7 +274,7 @@ TEST_P(TestBMP280, Settings) } } -TEST_P(TestBMP280, UseCase) +TEST_F(TestBMP280, UseCase) { SCOPED_TRACE(ustr); EXPECT_TRUE(unit->inPeriodic()); @@ -360,7 +312,7 @@ TEST_P(TestBMP280, UseCase) } } -TEST_P(TestBMP280, Reset) +TEST_F(TestBMP280, Reset) { SCOPED_TRACE(ustr); @@ -395,7 +347,7 @@ TEST_P(TestBMP280, Reset) EXPECT_EQ(pm, PowerMode::Sleep); } -TEST_P(TestBMP280, SingleShot) +TEST_F(TestBMP280, SingleShot) { SCOPED_TRACE(ustr); @@ -461,10 +413,13 @@ TEST_P(TestBMP280, SingleShot) } } -TEST_P(TestBMP280, Periodic) +TEST_F(TestBMP280, Periodic) { SCOPED_TRACE(ustr); + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_bus = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::Bus; + EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -482,20 +437,23 @@ TEST_P(TestBMP280, Periodic) tm = standby_time_table[m5::stl::to_underlying(val.st)]; } + M5_LOGI("Periodic: %s interval:%lu ms", s.c_str(), (unsigned long)tm); + EXPECT_TRUE(unit->writeUseCaseSetting(uc)); EXPECT_TRUE(unit->startPeriodicMeasurement()); EXPECT_TRUE(unit->inPeriodic()); - auto elapsed = test_periodic(unit.get(), STORED_SIZE, tm); + // interval() can be 0 for short standby; use actual cycle time to ensure non-zero timeout + uint32_t cycle = std::max(tm, unit->interval()); + uint32_t timeout = is_bus ? std::max(cycle, (uint32_t)500) * (STORED_SIZE + 1) * 4 : cycle * (STORED_SIZE + 1); + auto r = collect_periodic_measurements(unit.get(), STORED_SIZE, timeout); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, STORED_SIZE); + EXPECT_LE(r.median(), cycle + (is_bus ? 5U : 1U)); EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); - // M5_LOGW("E:%ld tm:%ld/%ld", elapsed, tm, tm * STORED_SIZE); - - EXPECT_NE(elapsed, 0); - EXPECT_LE(elapsed, STORED_SIZE * tm); - // EXPECT_EQ(unit->available(), STORED_SIZE); EXPECT_FALSE(unit->empty()); diff --git a/test/embedded/test_qmp6988/qmp6988_test.cpp b/test/embedded/test_qmp6988/qmp6988_test.cpp index ad8f315..9c41226 100644 --- a/test/embedded/test_qmp6988/qmp6988_test.cpp +++ b/test/embedded/test_qmp6988/qmp6988_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -23,11 +24,9 @@ using namespace m5::unit::qmp6988; using namespace m5::unit::qmp6988::command; using m5::unit::types::elapsed_time_t; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - constexpr uint32_t STORED_SIZE{8}; -class TestQMP6988 : public ComponentTestBase { +class TestQMP6988 : public I2CComponentTestBase { protected: virtual UnitQMP6988* get_instance() override { @@ -37,17 +36,8 @@ class TestQMP6988 : public ComponentTestBase { ptr->component_config(ccfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestQMP6988, -// ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestQMP6988, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestQMP6988, ::testing::Values(false)); - namespace { constexpr Oversampling os_table[] = { Oversampling::Skipped, Oversampling::X1, Oversampling::X2, Oversampling::X4, @@ -98,49 +88,9 @@ constexpr UseCaseSetting uc_val_table[] = { {OversamplingSetting::UltraHightAccuracy, Filter::Coeff32}, }; -template -elapsed_time_t test_periodic(U* unit, const uint32_t times, const uint32_t measure_duration = 0) -{ - auto tm = unit->interval(); - auto timeout_at = m5::utility::millis() + 8 * 1000; - // First measured - do { - unit->update(); - if (unit->updated()) { - break; - } - std::this_thread::yield(); - } while (!unit->updated() && m5::utility::millis() <= timeout_at); - // timeout - if (!unit->updated()) { - return 0; - } - - // - uint32_t measured{}; - auto start_at = m5::utility::millis(); - timeout_at = start_at + (times * (tm + measure_duration) * 2); - do { - unit->update(); - measured += unit->updated() ? 1 : 0; - if (measured >= times) { - break; - } - std::this_thread::yield(); - // m5::utility::delay(1); - - } while (measured < times && m5::utility::millis() <= timeout_at); - - if (measured == times) { - return m5::utility::millis() - start_at; - } - M5_LOGE("measured:%u", measured); - return -1; -} - } // namespace -TEST_P(TestQMP6988, Settings) +TEST_F(TestQMP6988, Settings) { SCOPED_TRACE(ustr); @@ -289,7 +239,7 @@ TEST_P(TestQMP6988, Settings) } } -TEST_P(TestQMP6988, UseCase) +TEST_F(TestQMP6988, UseCase) { SCOPED_TRACE(ustr); EXPECT_TRUE(unit->inPeriodic()); @@ -324,7 +274,7 @@ TEST_P(TestQMP6988, UseCase) } } -TEST_P(TestQMP6988, Reset) +TEST_F(TestQMP6988, Reset) { SCOPED_TRACE(ustr); @@ -359,7 +309,7 @@ TEST_P(TestQMP6988, Reset) EXPECT_EQ(pm, PowerMode::Sleep); } -TEST_P(TestQMP6988, SingleShot) +TEST_F(TestQMP6988, SingleShot) { SCOPED_TRACE(ustr); @@ -424,10 +374,13 @@ TEST_P(TestQMP6988, SingleShot) } } -TEST_P(TestQMP6988, Periodic) +TEST_F(TestQMP6988, Periodic) { SCOPED_TRACE(ustr); + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_bus = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::Bus; + EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -436,8 +389,6 @@ TEST_P(TestQMP6988, Periodic) auto s = m5::utility::formatString("UC:%u ST:%u", uc, st); SCOPED_TRACE(s); - // M5_LOGW("%s", s.c_str()); - const auto& val = uc_val_table[m5::stl::to_underlying(uc)]; const auto& osrrs = osrss_table[m5::stl::to_underlying(val.osrss)]; @@ -445,17 +396,19 @@ TEST_P(TestQMP6988, Periodic) EXPECT_TRUE(unit->writeStandbyTime(st)); EXPECT_TRUE(unit->startPeriodicMeasurement()); EXPECT_TRUE(unit->inPeriodic()); - auto tm = unit->interval(); - auto elapsed = test_periodic(unit.get(), STORED_SIZE, (int)st == 0 ? ((uint32_t)uc + 1) * 2 : 0); + + // interval() can be as small as 1ms for short standby + M5_LOGI("Periodic: %s interval:%lu ms", s.c_str(), unit->interval()); + uint32_t timeout = is_bus ? std::max(unit->interval(), 500) * (STORED_SIZE + 1) * 4 + : unit->interval() * (STORED_SIZE + 1); + auto r = collect_periodic_measurements(unit.get(), STORED_SIZE, timeout); EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); - // M5_LOGW("E:(%u) %ld", tm == 1 ? (uint32_t)uc * 2 : 0, elapsed); - - EXPECT_NE(elapsed, 0); - EXPECT_NE(elapsed, -1); - EXPECT_GE(elapsed, STORED_SIZE * tm - 1); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, STORED_SIZE); + EXPECT_LE(r.median(), r.expected_interval + (is_bus ? 5U : 1U)); Oversampling t; Oversampling p; diff --git a/test/embedded/test_scd40/scd40_test.cpp b/test/embedded/test_scd40/scd40_test.cpp index 8304d28..366e924 100644 --- a/test/embedded/test_scd40/scd40_test.cpp +++ b/test/embedded/test_scd40/scd40_test.cpp @@ -21,11 +21,9 @@ using namespace m5::unit; using namespace m5::unit::scd4x; using m5::unit::types::elapsed_time_t; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - constexpr uint32_t STORED_SIZE{4}; -class TestSCD4x : public ComponentTestBase { +class TestSCD4x : public I2CComponentTestBase { protected: virtual UnitSCD40* get_instance() override { @@ -38,16 +36,8 @@ class TestSCD4x : public ComponentTestBase { ptr->config(cfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(false)); - namespace { } // namespace diff --git a/test/embedded/test_scd41/scd41_test.cpp b/test/embedded/test_scd41/scd41_test.cpp index 741c7b0..d464600 100644 --- a/test/embedded/test_scd41/scd41_test.cpp +++ b/test/embedded/test_scd41/scd41_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -20,11 +21,9 @@ using namespace m5::unit; using namespace m5::unit::scd4x; using m5::unit::types::elapsed_time_t; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - constexpr uint32_t STORED_SIZE{4}; -class TestSCD4x : public ComponentTestBase { +class TestSCD4x : public I2CComponentTestBase { protected: virtual UnitSCD41* get_instance() override { @@ -37,22 +36,14 @@ class TestSCD4x : public ComponentTestBase { ptr->config(cfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestSCD4x, ::testing::Values(false)); - namespace { } // namespace #include "../scd4x_test.inl" -TEST_P(TestSCD4x, Singleshot) +TEST_F(TestSCD4x, Singleshot) { SCOPED_TRACE(ustr); { @@ -93,7 +84,7 @@ TEST_P(TestSCD4x, Singleshot) } } -TEST_P(TestSCD4x, PowerMode) +TEST_F(TestSCD4x, PowerMode) { SCOPED_TRACE(ustr); @@ -115,7 +106,7 @@ TEST_P(TestSCD4x, PowerMode) EXPECT_TRUE(unit->reInit()); } -TEST_P(TestSCD4x, ASC) +TEST_F(TestSCD4x, ASC) { SCOPED_TRACE(ustr); diff --git a/test/embedded/test_sgp30/sgp30_test.cpp b/test/embedded/test_sgp30/sgp30_test.cpp index b12eaf0..1660617 100644 --- a/test/embedded/test_sgp30/sgp30_test.cpp +++ b/test/embedded/test_sgp30/sgp30_test.cpp @@ -13,14 +13,13 @@ #include #include #include +#include using namespace m5::unit::googletest; using namespace m5::unit; using namespace m5::unit::sgp30; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - -class TestSGP30 : public ComponentTestBase { +class TestSGP30 : public I2CComponentTestBase { protected: virtual UnitSGP30* get_instance() override { @@ -36,16 +35,8 @@ class TestSGP30 : public ComponentTestBase { } return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSGP30, ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSGP30, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestSGP30, ::testing::Values(false)); - namespace { void check_measurement_values(UnitSGP30* u) { @@ -69,7 +60,7 @@ void wait15sec() } // namespace -TEST_P(TestSGP30, FeatureSet) +TEST_F(TestSGP30, FeatureSet) { SCOPED_TRACE(ustr); @@ -84,7 +75,7 @@ TEST_P(TestSGP30, FeatureSet) EXPECT_EQ(unit->productVersion(), f.productVersion()); } -TEST_P(TestSGP30, selfTest) +TEST_F(TestSGP30, selfTest) { SCOPED_TRACE(ustr); @@ -93,7 +84,7 @@ TEST_P(TestSGP30, selfTest) EXPECT_EQ(result, 0xD400); } -TEST_P(TestSGP30, serialNumber) +TEST_F(TestSGP30, serialNumber) { SCOPED_TRACE(ustr); // Read direct [MSB] SNB_3, SNB_2, CRC, SNB_1, SNB_0, CRC [LSB] @@ -128,10 +119,18 @@ TEST_P(TestSGP30, serialNumber) EXPECT_STREQ(s.c_str(), ssno); } -TEST_P(TestSGP30, generalReset) +TEST_F(TestSGP30, generalReset) { SCOPED_TRACE(ustr); + // I2C_Class hangs on generalReset (bus stuck after general call reset) + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_i2cclass = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::I2CClass; + if (is_i2cclass) { + M5_LOGW("Skip GeneralReset: I2C_Class does not recover from general call reset"); + GTEST_SKIP(); + } + EXPECT_TRUE(unit->startPeriodicMeasurement(0x1234, 0x5678, 0x9ABC)); M5_LOGW("SGP30 measurement starts 15 seconds after begin"); EXPECT_TRUE(unit->inPeriodic()); @@ -158,7 +157,7 @@ TEST_P(TestSGP30, generalReset) // EXPECT_EQ(inceptive_tvoc, 0x0000); } -TEST_P(TestSGP30, Periodic) +TEST_F(TestSGP30, Periodic) { SCOPED_TRACE(ustr); @@ -177,7 +176,12 @@ TEST_P(TestSGP30, Periodic) EXPECT_TRUE(unit->inPeriodic()); wait15sec(); - test_periodic_measurement(unit.get(), 4, check_measurement_values); + { + auto r = collect_periodic_measurements(unit.get(), 4, 0, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 4U); + EXPECT_LE(r.median(), r.expected_interval + 1); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); diff --git a/test/embedded/test_sht30/sht30_test.cpp b/test/embedded/test_sht30/sht30_test.cpp index e0e6310..79c9ca9 100644 --- a/test/embedded/test_sht30/sht30_test.cpp +++ b/test/embedded/test_sht30/sht30_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,9 +26,7 @@ using namespace m5::unit::sht30::command; constexpr size_t STORED_SIZE{4}; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - -class TestSHT30 : public ComponentTestBase { +class TestSHT30 : public I2CComponentTestBase { protected: virtual UnitSHT30* get_instance() override { @@ -37,17 +36,8 @@ class TestSHT30 : public ComponentTestBase { ptr->component_config(ccfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT30, -// ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT30, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT30, ::testing::Values(false)); - namespace { // flot t uu int16 (temperature) constexpr uint16_t float_to_uint16(const float f) @@ -70,11 +60,14 @@ void check_measurement_values(UnitSHT30* u) } // namespace -TEST_P(TestSHT30, SingleShot) +TEST_F(TestSHT30, SingleShot) { SCOPED_TRACE(ustr); EXPECT_TRUE(unit->stopPeriodicMeasurement()); + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_i2cclass = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::I2CClass; + for (auto&& e : ss_table) { const char* s{}; Repeatability rep; @@ -82,20 +75,29 @@ TEST_P(TestSHT30, SingleShot) std::tie(s, rep, stretch) = e; SCOPED_TRACE(s); - int cnt{10}; // repeat 10 times - while (cnt--) { + if (stretch && is_i2cclass) { + // I2C_Class does not support clock stretching sht30::Data d{}; - EXPECT_TRUE(unit->measureSingleshot(d, rep, stretch)) << (int)rep << " : " << stretch; - EXPECT_TRUE(std::isfinite(d.temperature())); - EXPECT_TRUE(std::isfinite(d.humidity())); + EXPECT_FALSE(unit->measureSingleshot(d, rep, stretch)); + } else { + int cnt{10}; // repeat 10 times + while (cnt--) { + sht30::Data d{}; + EXPECT_TRUE(unit->measureSingleshot(d, rep, stretch)) << (int)rep << " : " << stretch; + EXPECT_TRUE(std::isfinite(d.temperature())); + EXPECT_TRUE(std::isfinite(d.humidity())); + } } } } -TEST_P(TestSHT30, Periodic) +TEST_F(TestSHT30, Periodic) { SCOPED_TRACE(ustr); + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_bus = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::Bus; + EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -132,6 +134,8 @@ TEST_P(TestSHT30, Periodic) EXPECT_TRUE(unit->startPeriodicMeasurement(mps, rep)); EXPECT_TRUE(unit->inPeriodic()); + M5_LOGI("Periodic: %s interval:%lu ms", s, unit->interval()); + // Cannot call all singleshot in periodic for (auto&& e : ss_table) { const char* s{}; @@ -143,7 +147,14 @@ TEST_P(TestSHT30, Periodic) SCOPED_TRACE(s); EXPECT_FALSE(unit->measureSingleshot(d, rep, stretch)); } - test_periodic_measurement(unit.get(), 4, 1, check_measurement_values); + { + uint32_t timeout = + is_bus ? std::max(unit->interval(), 500) * (4 + 1) * 4 : unit->interval() * (4 + 1); + auto r = collect_periodic_measurements(unit.get(), 4, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 4U); + EXPECT_LE(r.median(), r.expected_interval + (is_bus ? 5U : 1U)); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -196,7 +207,15 @@ TEST_P(TestSHT30, Periodic) EXPECT_FALSE(unit->measureSingleshot(d, rep, stretch)); } - test_periodic_measurement(unit.get(), 4, 1, check_measurement_values); + { + // ART = 4 mps = 250ms interval + uint32_t timeout = + is_bus ? std::max(unit->interval(), 500) * (4 + 1) * 4 : unit->interval() * (4 + 1); + auto r = collect_periodic_measurements(unit.get(), 4, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 4U); + EXPECT_LE(r.median(), r.expected_interval + (is_bus ? 5U : 1U)); + } EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -217,13 +236,36 @@ TEST_P(TestSHT30, Periodic) EXPECT_TRUE(unit->empty()); EXPECT_FALSE(unit->full()); + // startPeriodicMeasurement() no-arg: uses cached MPS and Repeatability + { + EXPECT_TRUE(unit->startPeriodicMeasurement(MPS::Four, Repeatability::Low)); + EXPECT_TRUE(unit->inPeriodic()); + EXPECT_TRUE(unit->stopPeriodicMeasurement()); + EXPECT_FALSE(unit->inPeriodic()); + + // No-arg version should use cached settings (Four, Low) + EXPECT_TRUE(unit->startPeriodicMeasurement()); + EXPECT_TRUE(unit->inPeriodic()); + + uint32_t timeout = + is_bus ? std::max(unit->interval(), 500) * (4 + 1) * 4 : unit->interval() * (4 + 1); + auto r = collect_periodic_measurements(unit.get(), 4, timeout, check_measurement_values); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, 4U); + // Four = 250ms interval + EXPECT_LE(r.median(), 250 + (is_bus ? 5U : 1U)); + EXPECT_GE(r.median(), 250 - 50); + + EXPECT_TRUE(unit->stopPeriodicMeasurement()); + EXPECT_FALSE(unit->inPeriodic()); + } + // startPeriodicMeasurement after ART (ART is disabled) EXPECT_TRUE(unit->startPeriodicMeasurement(MPS::Two, Repeatability::High)); // 2 mps EXPECT_TRUE(unit->inPeriodic()); EXPECT_EQ(unit->updatedMillis(), 0); - std::array rbuf{}; types::elapsed_time_t timeout_at{}, now{}, at[2]{}; uint32_t idx{}; timeout_at = m5::utility::millis() + 1100; @@ -252,7 +294,7 @@ void printStatus(const Status& s) } } // namespace -TEST_P(TestSHT30, HeaterAndStatus) +TEST_F(TestSHT30, HeaterAndStatus) { SCOPED_TRACE(ustr); @@ -277,7 +319,7 @@ TEST_P(TestSHT30, HeaterAndStatus) EXPECT_FALSE(s.heater()); } -TEST_P(TestSHT30, SoftReset) +TEST_F(TestSHT30, SoftReset) { SCOPED_TRACE(ustr); @@ -303,18 +345,25 @@ TEST_P(TestSHT30, SoftReset) EXPECT_FALSE(s.checksum()); } -TEST_P(TestSHT30, GeneralReset) +TEST_F(TestSHT30, GeneralReset) { SCOPED_TRACE(ustr); + // I2C_Class hangs on generalReset (bus stuck after general call reset) + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_i2cclass = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::I2CClass; + if (is_i2cclass) { + M5_LOGW("Skip GeneralReset: I2C_Class does not recover from general call reset"); + GTEST_SKIP(); + } + EXPECT_TRUE(unit->startHeater()); EXPECT_TRUE(unit->generalReset()); Status s{}; EXPECT_TRUE(unit->readStatus(s)); - // The ALERT pin will also become active (high) after powerup and after - // resets + // The ALERT pin will also become active (high) after powerup and after resets EXPECT_TRUE(s.alertPending()); EXPECT_FALSE(s.heater()); EXPECT_FALSE(s.trackingAlertRH()); @@ -324,7 +373,7 @@ TEST_P(TestSHT30, GeneralReset) EXPECT_FALSE(s.checksum()); } -TEST_P(TestSHT30, SerialNumber) +TEST_F(TestSHT30, SerialNumber) { SCOPED_TRACE(ustr); diff --git a/test/embedded/test_sht40/sht40_test.cpp b/test/embedded/test_sht40/sht40_test.cpp index 7c668f4..d836122 100644 --- a/test/embedded/test_sht40/sht40_test.cpp +++ b/test/embedded/test_sht40/sht40_test.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,9 +26,7 @@ using m5::unit::types::elapsed_time_t; constexpr size_t STORED_SIZE{4}; -const ::testing::Environment* global_fixture = ::testing::AddGlobalTestEnvironment(new GlobalFixture<400000U>()); - -class TestSHT40 : public ComponentTestBase { +class TestSHT40 : public I2CComponentTestBase { protected: virtual UnitSHT40* get_instance() override { @@ -37,48 +36,10 @@ class TestSHT40 : public ComponentTestBase { ptr->component_config(ccfg); return ptr; } - virtual bool is_using_hal() const override - { - return GetParam(); - }; }; -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT40, -// ::testing::Values(false, true)); -// INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT40, ::testing::Values(true)); -INSTANTIATE_TEST_SUITE_P(ParamValues, TestSHT40, ::testing::Values(false)); - namespace { -template -elapsed_time_t test_periodic(U* unit, const uint32_t times) -{ - auto timeout_at = m5::utility::millis() + (times * unit->interval() * 2); - - // First read - while (!unit->updated() && m5::utility::millis() < timeout_at) { - std::this_thread::yield(); - unit->update(); - } - // timeout - if (!unit->updated()) { - return 0; - } - - // - uint32_t measured{}; - auto start_at = m5::utility::millis(); - unit->update(); - - do { - m5::utility::delay(1); - unit->update(); - measured += unit->updated() ? 1 : 0; - } while (measured < times && m5::utility::millis() < timeout_at); - - return (measured == times) ? m5::utility::millis() - start_at : 0; -} - std::tuple sm_table[] = { // {"HighLong", Precision::High, Heater::Long, 9}, @@ -96,7 +57,7 @@ std::tuple sm_table[] = { } // namespace -TEST_P(TestSHT40, SoftReset) +TEST_F(TestSHT40, SoftReset) { SCOPED_TRACE(ustr); // Soft reset is only possible in standby mode. @@ -106,13 +67,22 @@ TEST_P(TestSHT40, SoftReset) EXPECT_TRUE(unit->softReset()); } -TEST_P(TestSHT40, GeneralReset) +TEST_F(TestSHT40, GeneralReset) { SCOPED_TRACE(ustr); + + // I2C_Class hangs on generalReset (bus stuck after general call reset) + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_i2cclass = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::I2CClass; + if (is_i2cclass) { + M5_LOGW("Skip GeneralReset: I2C_Class does not recover from general call reset"); + GTEST_SKIP(); + } + EXPECT_TRUE(unit->generalReset()); } -TEST_P(TestSHT40, SerialNumber) +TEST_F(TestSHT40, SerialNumber) { SCOPED_TRACE(ustr); @@ -143,7 +113,7 @@ TEST_P(TestSHT40, SerialNumber) } } -TEST_P(TestSHT40, SingleShot) +TEST_F(TestSHT40, SingleShot) { SCOPED_TRACE(ustr); @@ -170,10 +140,13 @@ TEST_P(TestSHT40, SingleShot) } } -TEST_P(TestSHT40, Periodic) +TEST_F(TestSHT40, Periodic) { SCOPED_TRACE(ustr); + auto ad = unit->asAdapter(m5::unit::Adapter::Type::I2C); + bool is_bus = ad && ad->implType() == m5::unit::AdapterI2C::ImplType::Bus; + EXPECT_TRUE(unit->stopPeriodicMeasurement()); EXPECT_FALSE(unit->inPeriodic()); @@ -185,6 +158,7 @@ TEST_P(TestSHT40, Periodic) std::tie(s, p, h, tm) = e; SCOPED_TRACE(s); + M5_LOGI("Periodic: %s interval:%lu ms", s, (unsigned long)tm); EXPECT_TRUE(unit->startPeriodicMeasurement(p, h)); EXPECT_TRUE(unit->inPeriodic()); @@ -206,10 +180,14 @@ TEST_P(TestSHT40, Periodic) EXPECT_TRUE(unit->startPeriodicMeasurement(p, h)); EXPECT_TRUE(unit->inPeriodic()); - auto elapsed = test_periodic(unit.get(), STORED_SIZE); - EXPECT_NE(elapsed, 0); - EXPECT_GE(elapsed, STORED_SIZE * tm); - EXPECT_LE(elapsed, STORED_SIZE * tm + 1); + // interval() can be small (2-9ms); use actual cycle time to ensure non-zero timeout + uint32_t cycle = std::max(tm, unit->interval()); + uint32_t timeout = is_bus ? std::max(cycle, (uint32_t)500) * (STORED_SIZE + 1) * 4 : cycle * (STORED_SIZE + 1); + uint32_t tolerance = is_bus ? 5 : 1; + auto r = collect_periodic_measurements(unit.get(), STORED_SIZE, timeout); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, STORED_SIZE); + EXPECT_LE(r.median(), r.expected_interval + tolerance); // M5_LOGW("[%s] %lu %zu", s, elapsed, unit->available()); @@ -242,4 +220,27 @@ TEST_P(TestSHT40, Periodic) EXPECT_FALSE(std::isfinite(unit->temperature())); EXPECT_FALSE(std::isfinite(unit->humidity())); } + + // startPeriodicMeasurement() no-arg: uses cached Precision, Heater, and duty + { + EXPECT_TRUE(unit->startPeriodicMeasurement(Precision::High, Heater::None)); + EXPECT_TRUE(unit->inPeriodic()); + EXPECT_TRUE(unit->stopPeriodicMeasurement()); + EXPECT_FALSE(unit->inPeriodic()); + + // No-arg version should use cached settings (High, None) + EXPECT_TRUE(unit->startPeriodicMeasurement()); + EXPECT_TRUE(unit->inPeriodic()); + + uint32_t timeout2 = is_bus ? std::max(unit->interval(), 500) * (STORED_SIZE + 1) * 4 + : unit->interval() * (STORED_SIZE + 1); + auto r = collect_periodic_measurements(unit.get(), STORED_SIZE, timeout2); + EXPECT_FALSE(r.timed_out); + EXPECT_EQ(r.update_count, STORED_SIZE); + // High/None = 9ms interval + EXPECT_LE(r.median(), 9 + (is_bus ? 5U : 1U)); + + EXPECT_TRUE(unit->stopPeriodicMeasurement()); + EXPECT_FALSE(unit->inPeriodic()); + } } From 03d45eff1319ff0aee2a2b389c9ce8ae41b9adc6 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 17:03:25 +0900 Subject: [PATCH 09/22] Update examples to use In_I2C/Ex_I2C and add NessoN1/NanoC6 support --- examples/UnitUnified/Paper/main/Paper.cpp | 18 +-- .../PlotToSerial/main/PlotToSerial.cpp | 55 +++++---- .../PlotToSerial/main/PlotToSerial.cpp | 59 +++++---- .../PlotToSerial/main/PlotToSerial.cpp | 116 +++++++++--------- .../PlotToSerial/main/PlotToSerial.cpp | 85 ++++++++----- .../PlotToSerial/main/PlotToSerial.cpp | 53 ++++---- .../PlotToSerial/main/PlotToSerial.cpp | 53 ++++---- 7 files changed, 238 insertions(+), 201 deletions(-) diff --git a/examples/UnitUnified/Paper/main/Paper.cpp b/examples/UnitUnified/Paper/main/Paper.cpp index cc20b1c..e5e94af 100644 --- a/examples/UnitUnified/Paper/main/Paper.cpp +++ b/examples/UnitUnified/Paper/main/Paper.cpp @@ -24,8 +24,8 @@ void draw_dashboard(const float temperature, const float humidity) { char temp_text[32]; char hum_text[32]; - std::snprintf(temp_text, sizeof(temp_text), "%.2f C", temperature); - std::snprintf(hum_text, sizeof(hum_text), "%.2f %%", humidity); + std::snprintf(temp_text, sizeof(temp_text), "%7.2f C ", temperature); + std::snprintf(hum_text, sizeof(hum_text), "%7.2f %% ", humidity); const int w = lcd.width(); const int h = lcd.height(); @@ -33,8 +33,6 @@ void draw_dashboard(const float temperature, const float humidity) constexpr int value_x = 220; constexpr int temp_value_y = 130; const int humid_value_y = h / 2 + 58; - const int value_width = w - value_x - 24; - constexpr int value_height = 56; static bool initialized{}; lcd.startWrite(); @@ -60,8 +58,6 @@ void draw_dashboard(const float temperature, const float humidity) initialized = true; } - lcd.fillRect(value_x, temp_value_y - 12, value_width, value_height, TFT_WHITE); - lcd.fillRect(value_x, humid_value_y - 12, value_width, value_height, TFT_WHITE); lcd.setTextColor(TFT_BLACK, TFT_WHITE); lcd.setTextSize(3.5f); lcd.setCursor(value_x, temp_value_y); @@ -96,13 +92,8 @@ void setup() } lcd.setFont(&fonts::Orbitron_Light_32); - auto pin_num_sda = M5.getPin(m5::pin_name_t::in_i2c_sda); - auto pin_num_scl = M5.getPin(m5::pin_name_t::in_i2c_scl); - - M5_LOGI("Using TwoWire adapter"); - Wire.end(); - Wire.begin(pin_num_sda, pin_num_scl, 100 * 1000U); - if (!Units.add(sht30, Wire) || !Units.begin()) { + // The built-in SHT30 is used via M5.In_I2C + if (!Units.add(sht30, M5.In_I2C) || !Units.begin()) { M5_LOGE("Failed to begin"); M5_LOGW("%s", Units.debugInfo().c_str()); lcd.fillScreen(TFT_RED); @@ -133,7 +124,6 @@ void loop() latest_temperature = sht30.temperature(); latest_humidity = sht30.humidity(); has_measurement = true; - M5.Log.printf(">SHT30Temp:%2.2f\n>Humidity:%2.2f\n", latest_temperature, latest_humidity); } diff --git a/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp index 486046f..4490899 100644 --- a/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitCO2/PlotToSerial/main/PlotToSerial.cpp @@ -26,38 +26,43 @@ void setup() lcd.setRotation(1); } - 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); - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + auto board = M5.getBoard(); + + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); - 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); - } - } + unit_ready = Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); + unit_ready = Units.add(unit, M5.Ex_I2C) && Units.begin(); } else { - // Using TwoWire + 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); - } + unit_ready = Units.add(unit, Wire) && Units.begin(); + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + lcd.fillScreen(TFT_RED); + while (true) { + m5::utility::delay(10000); } } M5_LOGI("M5UnitUnified has been begun"); @@ -86,13 +91,13 @@ void setup() offset, altitude, pressure, asc, ppm); if (!ret) { - lcd.clear(TFT_RED); + lcd.fillScreen(TFT_RED); while (true) { m5::utility::delay(10000); } } } - lcd.clear(TFT_DARKGREEN); + lcd.fillScreen(TFT_DARKGREEN); } void loop() diff --git a/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp index feb67b8..875d255 100644 --- a/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitCO2L/PlotToSerial/main/PlotToSerial.cpp @@ -29,38 +29,43 @@ void setup() lcd.setRotation(1); } - 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); - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + auto board = M5.getBoard(); + + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); - 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); - } - } + unit_ready = Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); + unit_ready = Units.add(unit, M5.Ex_I2C) && Units.begin(); } else { - // Using TwoWire + 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); - } + unit_ready = Units.add(unit, Wire) && Units.begin(); + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + lcd.fillScreen(TFT_RED); + while (true) { + m5::utility::delay(10000); } } M5_LOGI("M5UnitUnified has been begun"); @@ -95,13 +100,13 @@ void setup() offset, altitude, pressure, asc, ppm, initialPeriod, standardPeriod); if (!ret) { - lcd.clear(TFT_RED); + lcd.fillScreen(TFT_RED); while (true) { m5::utility::delay(1000); } } } - lcd.clear(TFT_DARKGREEN); + lcd.fillScreen(TFT_DARKGREEN); } void loop() @@ -130,11 +135,11 @@ void loop() Data d{}; if (all) { if (unit.measureSingleshot(d)) { - M5.Log.printf(" SingleAll: %u/%2.2f/%2.2f\n", d.co2(), d.temperature(), d.humidity()); + M5.Log.printf(" SingleAll: CO2:%u T:%2.2f H:%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()); + M5.Log.printf(" SingleRHT: T:%2.2f H:%2.2f\n", d.temperature(), d.humidity()); } } unit.startPeriodicMeasurement(); diff --git a/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp index b57ab58..a2f39d7 100644 --- a/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVIII/PlotToSerial/main/PlotToSerial.cpp @@ -11,9 +11,6 @@ #include #include // For NessoN1 -// Using single shot measurement If defined -// #define USING_SINGLE_SHOT - // Using combined unit if defined #define USING_ENV3 @@ -48,70 +45,63 @@ void setup() lcd.setRotation(1); } -#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 + auto board = M5.getBoard(); - 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); - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); #if defined(USING_ENV3) - if (!Units.add(unitENV3, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { + unit_ready = Units.add(unitENV3, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); #else - if (!Units.add(unitSHT30, i2c_bus ? i2c_bus.value() : nullptr) || - !Units.add(unitQMP6988, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { + unit_ready = Units.add(unitSHT30, i2c_bus ? i2c_bus.value() : nullptr) && + Units.add(unitQMP6988, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); +#endif + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); +#if defined(USING_ENV3) + unit_ready = Units.add(unitENV3, M5.Ex_I2C) && Units.begin(); +#else + unit_ready = Units.add(unitSHT30, M5.Ex_I2C) && Units.add(unitQMP6988, M5.Ex_I2C) && Units.begin(); #endif - M5_LOGE("Failed to begin"); - lcd.clear(TFT_RED); - while (true) { - m5::utility::delay(10000); - } - } } else { - // Using TwoWire + 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 defined(USING_ENV3) - if (!Units.add(unitENV3, Wire) || !Units.begin()) { + unit_ready = Units.add(unitENV3, Wire) && Units.begin(); #else - if (!Units.add(unitSHT30, Wire) || !Units.add(unitQMP6988, Wire) || !Units.begin()) { + unit_ready = Units.add(unitSHT30, Wire) && Units.add(unitQMP6988, Wire) && Units.begin(); #endif - M5_LOGE("Failed to begin"); - M5_LOGW("%s", Units.debugInfo().c_str()); - lcd.clear(TFT_RED); - while (true) { - m5::utility::delay(10000); - } + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + M5_LOGW("%s", Units.debugInfo().c_str()); + lcd.fillScreen(TFT_RED); + while (true) { + m5::utility::delay(10000); } } 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); + lcd.fillScreen(TFT_DARKGREEN); } void loop() @@ -119,18 +109,6 @@ 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()); lcd.startWrite(); @@ -147,5 +125,25 @@ void loop() lcd.printf("QMP6988\nTemp:%2.2f\nPressure:%.2f", qmp6988.temperature(), qmp6988.pressure() * 0.01f); lcd.endWrite(); } -#endif + + if (M5.BtnA.wasClicked()) { + sht30.stopPeriodicMeasurement(); + qmp6988.stopPeriodicMeasurement(); + + m5::unit::sht30::Data ds{}; + if (sht30.measureSingleshot(ds)) { + M5.Log.printf("== Singleshot SHT30 Temp:%2.2f Humidity:%2.2f\n", ds.temperature(), ds.humidity()); + } else { + M5_LOGW("Single SHT30 failed"); + } + m5::unit::qmp6988::Data dq{}; + if (qmp6988.measureSingleshot(dq)) { + M5.Log.printf("== Singleshot QMP6988 Temp:%2.2f Pressure:%.2f\n", dq.temperature(), dq.pressure() * 0.01f); + } else { + M5_LOGW("Single QMP failed"); + } + + sht30.startPeriodicMeasurement(); + qmp6988.startPeriodicMeasurement(); + } } diff --git a/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp index 92d5ed3..44fedd5 100644 --- a/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVIV/PlotToSerial/main/PlotToSerial.cpp @@ -52,9 +52,6 @@ void setup() lcd.setRotation(1); } - 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); - { using namespace m5::unit::bmp280; auto cfg = bmp280.config(); @@ -65,51 +62,62 @@ void setup() bmp280.config(cfg); } - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + auto board = M5.getBoard(); + + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); #if defined(USING_ENV4) - if (!Units.add(unitENV4, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { + unit_ready = Units.add(unitENV4, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); #else - if (!Units.add(unitSHT40, i2c_bus ? i2c_bus.value() : nullptr) || - !Units.add(unitBMP280, i2c_bus ? i2c_bus.value() : nullptr) || !Units.begin()) { + unit_ready = Units.add(unitSHT40, i2c_bus ? i2c_bus.value() : nullptr) && + Units.add(unitBMP280, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); +#endif + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); +#if defined(USING_ENV4) + unit_ready = Units.add(unitENV4, M5.Ex_I2C) && Units.begin(); +#else + unit_ready = Units.add(unitSHT40, M5.Ex_I2C) && Units.add(unitBMP280, M5.Ex_I2C) && Units.begin(); #endif - M5_LOGE("Failed to begin"); - lcd.clear(TFT_RED); - while (true) { - m5::utility::delay(10000); - } - } } else { - // Using TwoWire + 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 defined(USING_ENV4) - if (!Units.add(unitENV4, Wire) || !Units.begin()) { + unit_ready = Units.add(unitENV4, Wire) && Units.begin(); #else - if (!Units.add(unitSHT40, Wire) || !Units.add(unitBMP280, Wire) || !Units.begin()) { + unit_ready = Units.add(unitSHT40, Wire) && Units.add(unitBMP280, Wire) && Units.begin(); #endif - M5_LOGE("Failed to begin"); - lcd.clear(TFT_RED); - while (true) { - m5::utility::delay(10000); - } + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + lcd.fillScreen(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); + lcd.fillScreen(TFT_DARKGREEN); } void loop() @@ -152,4 +160,25 @@ void loop() bmp280.temperature(), p * 0.01f /* To hPa */, calculate_altitude(p)); lcd.endWrite(); } + + if (M5.BtnA.wasClicked()) { + sht40.stopPeriodicMeasurement(); + bmp280.stopPeriodicMeasurement(); + + m5::unit::sht40::Data ds{}; + if (sht40.measureSingleshot(ds)) { + M5.Log.printf("== Singleshot SHT40 Temp:%.4f Humidity:%.4f\n", ds.temperature(), ds.humidity()); + } else { + M5_LOGW("Single SHT40 failed"); + } + m5::unit::bmp280::Data db{}; + if (bmp280.measureSingleshot(db)) { + M5.Log.printf("== Singleshot BMP280 Temp:%.4f Pressure:%.4f\n", db.temperature(), db.pressure() * 0.01f); + } else { + M5_LOGW("Single BMP280 failed"); + } + + sht40.startPeriodicMeasurement(); + bmp280.startPeriodicMeasurement(); + } } diff --git a/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp index ab92c59..895eba1 100644 --- a/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitENVPro/PlotToSerial/main/PlotToSerial.cpp @@ -26,44 +26,49 @@ void setup() lcd.setRotation(1); } - 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); - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + auto board = M5.getBoard(); + + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); - 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); - } - } + unit_ready = Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); + unit_ready = Units.add(unit, M5.Ex_I2C) && Units.begin(); } else { - // Using TwoWire + 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); - } + unit_ready = Units.add(unit, Wire) && Units.begin(); + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + lcd.fillScreen(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); + lcd.fillScreen(TFT_DARKGREEN); } void loop() diff --git a/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp b/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp index 25427c5..981885e 100644 --- a/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp +++ b/examples/UnitUnified/UnitTVOC/PlotToSerial/main/PlotToSerial.cpp @@ -27,45 +27,50 @@ void setup() lcd.setRotation(1); } - 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); - // For NessoN1 GROVE - if (M5.getBoard() == m5::board_t::board_ArduinoNessoN1) { - // Port A of the NessoN1 is QWIIC, then use portB (GROVE) - pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); - pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); - M5_LOGI("getPin(NessoN1): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); - // Wire is used internally, so SoftwareI2C handles the unit + auto board = M5.getBoard(); + + // NessoN1: Arduino Wire (I2C_NUM_0) cannot be used for GROVE port. + // Wire is used by M5Unified In_I2C for internal devices (IOExpander etc.). + // Solution: Use SoftwareI2C via M5HAL (bit-banging) for the GROVE port. + // NanoC6: Wire.begin() on GROVE pins conflicts with m5::I2C_Class registered by Ex_I2C.setPort() + // on the same I2C_NUM_0, causing sporadic NACK errors. + // Solution: Use M5.Ex_I2C (m5::I2C_Class) directly instead of Arduino Wire. + bool unit_ready{}; + if (board == m5::board_t::board_ArduinoNessoN1) { + // NessoN1: GROVE is on port_b (GPIO 5/4), not port_a (which maps to Wire pins 8/10) + auto pin_num_sda = M5.getPin(m5::pin_name_t::port_b_out); + auto pin_num_scl = M5.getPin(m5::pin_name_t::port_b_in); + M5_LOGI("getPin(M5HAL): SDA:%u SCL:%u", pin_num_sda, pin_num_scl); 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); M5_LOGI("Bus:%d", i2c_bus.has_value()); - 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); - } - } + unit_ready = Units.add(unit, i2c_bus ? i2c_bus.value() : nullptr) && Units.begin(); + } else if (board == m5::board_t::board_M5NanoC6) { + // NanoC6: Use M5.Ex_I2C (m5::I2C_Class, not Arduino Wire) + M5_LOGI("Using M5.Ex_I2C"); + unit_ready = Units.add(unit, M5.Ex_I2C) && Units.begin(); } else { - // Using TwoWire + 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); - } + unit_ready = Units.add(unit, Wire) && Units.begin(); + } + if (!unit_ready) { + M5_LOGE("Failed to begin"); + lcd.fillScreen(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); + lcd.fillScreen(TFT_DARKGREEN); M5.Log.printf("SGP30 measurement starts 15 seconds after begin\n"); lcd.printf("SGP30 measurement starts 15 seconds after begin"); } From 0dfaed9afd9b7e678194384764d73a21e5ad3fcb Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 17:04:05 +0900 Subject: [PATCH 10/22] Bump M5UnitUnified dependency to >=0.4.0 and add more test devices --- library.json | 2 +- platformio.ini | 5 ++--- unit_env4_env.ini | 26 ++++++++++++++++++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/library.json b/library.json index 170f611..3a3b4db 100644 --- a/library.json +++ b/library.json @@ -11,7 +11,7 @@ "url": "https://github.com/m5stack/M5Unit-ENV.git" }, "dependencies": { - "m5stack/M5UnitUnified": ">=0.1.0", + "m5stack/M5UnitUnified": ">=0.4.0", "boschsensortec/BME68x Sensor library": ">=1.3.40408", "boschsensortec/bsec2": ">=1.10.2610" }, diff --git a/platformio.ini b/platformio.ini index 906e557..1c792b6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ lib_ldf_mode = deep test_framework = googletest test_build_src = true lib_deps=m5stack/M5Unified - m5stack/M5UnitUnified + m5stack/M5UnitUnified@>=0.4.0 boschsensortec/BME68x Sensor library@>=1.3.40408 ; -------------------------------- @@ -251,7 +251,6 @@ build_flags = ${env.build_flags} -DM5_LOG_LEVEL=0 -Wl,-Map,output.map -; Require at leaset C++14 after 1.13.0 +; Require at least C++14 after 1.13.0 [test_fw] lib_deps = google/googletest@1.12.1 - diff --git a/unit_env4_env.ini b/unit_env4_env.ini index 1f079b1..9030298 100644 --- a/unit_env4_env.ini +++ b/unit_env4_env.ini @@ -58,9 +58,9 @@ lib_deps = ${AtomS3R.lib_deps} test_filter= embedded/test_sht40 [env:test_SHT40_NanoC6] -extends=NanoC6, option_release, arduino_latest +extends=NanoC6, option_release, nanoc6_latest lib_deps = ${NanoC6.lib_deps} - ${test_fw.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht40 [env:test_SHT40_StickCPlus] @@ -91,8 +91,26 @@ test_filter= embedded/test_sht40 [env:test_SHT40_CoreInk] extends=CoreInk, option_release, arduino_latest -lib_deps = ${CoreInk.lib_deps} - ${test_fw.lib_deps} +lib_deps = ${CoreInk.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht40 + +[env:test_SHT40_Cardputer] +extends=Cardputer, option_release, arduino_latest +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht40 + +[env:test_SHT40_Tab5] +extends=Tab5, option_release, pioarduino_latest +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} +test_filter= embedded/test_sht40 + +[env:test_SHT40_NessoN1] +extends=NessoN1, option_release, pioarduino_latest +lib_deps = ${NessoN1.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht40 ; BMP280 From 92c34cdf227312155b553d828232e8ceb48c6505 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 17:04:40 +0900 Subject: [PATCH 11/22] Fix Doxyfile project name quoting and typo in doxy.sh --- docs/Doxyfile | 2 +- docs/doxy.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/Doxyfile b/docs/Doxyfile index ea43d72..9b11d9f 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = M5Unit-ENV +PROJECT_NAME = "M5Unit-ENV" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version diff --git a/docs/doxy.sh b/docs/doxy.sh index 064edd0..d4492c9 100755 --- a/docs/doxy.sh +++ b/docs/doxy.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Please execute on repositry root +# Please execute on repository root ## Get version from library.properties ## Get git rev of HEAD From 901121ec8b0b8b96b6179b30571ae072992f26c1 Mon Sep 17 00:00:00 2001 From: GOB Date: Tue, 3 Mar 2026 17:05:48 +0900 Subject: [PATCH 12/22] Cosmetic change --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a55e5b..3652b5e 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ M5UnitUnified is a library for unified handling of various M5 units products. 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. +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. From a16d702ad9d4fef3bd5839d0d3fe10468a26c0bb Mon Sep 17 00:00:00 2001 From: GOB Date: Thu, 5 Mar 2026 12:49:42 +0900 Subject: [PATCH 13/22] Remove obsolete platform sections, unify Dial test envs, and fix minor docs issues --- README.md | 2 +- platformio.ini | 8 -------- src/unit/unit_QMP6988.hpp | 1 - unit_co2_env.ini | 14 ++++++-------- unit_env3_env.ini | 14 ++++++-------- unit_env4_env.ini | 14 ++++++-------- unit_envpro_env.ini | 7 +++---- 7 files changed, 22 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 3652b5e..5ca6eb1 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ CO2 is a photoacoustic Carbon Dioxide (CO2) Unit that will tell you the CO2 PPM - [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 BPS(QMP6988) - Document & Datasheet](https://docs.m5stack.com/en/unit/BPS%28QMP6988%29) - [Unit CO2 - Document & Datasheet](https://docs.m5stack.com/en/unit/co2) ## Required Libraries: diff --git a/platformio.ini b/platformio.ini index 1c792b6..4f1f69f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -189,14 +189,6 @@ framework = arduino 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 diff --git a/src/unit/unit_QMP6988.hpp b/src/unit/unit_QMP6988.hpp index 52c49ba..d55b478 100644 --- a/src/unit/unit_QMP6988.hpp +++ b/src/unit/unit_QMP6988.hpp @@ -32,7 +32,6 @@ enum class PowerMode : uint8_t { /*! @enum Oversampling @brief Oversampling value - @warning */ enum class Oversampling : uint8_t { Skipped, //!< Skipped (No measurements are performed) diff --git a/unit_co2_env.ini b/unit_co2_env.ini index 4580c0a..7fdf78d 100644 --- a/unit_co2_env.ini +++ b/unit_co2_env.ini @@ -33,10 +33,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_scd40 [env:test_SCD40_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd40 [env:test_SCD40_Atom] @@ -145,10 +144,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_scd41 [env:test_SCD41_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd41 [env:test_SCD41_Atom] diff --git a/unit_env3_env.ini b/unit_env3_env.ini index 7fd404c..16b5207 100644 --- a/unit_env3_env.ini +++ b/unit_env3_env.ini @@ -33,10 +33,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_sht30 [env:test_SHT30_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht30 [env:test_SHT30_Atom] @@ -145,10 +144,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_qmp6988 [env:test_QMP6988_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 [env:test_QMP6988_Atom] diff --git a/unit_env4_env.ini b/unit_env4_env.ini index 9030298..6ed94cb 100644 --- a/unit_env4_env.ini +++ b/unit_env4_env.ini @@ -33,10 +33,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_sht40 [env:test_SHT40_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht40 [env:test_SHT40_Atom] @@ -145,10 +144,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_bmp280 [env:test_BMP280_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bmp280 [env:test_BMP280_Atom] diff --git a/unit_envpro_env.ini b/unit_envpro_env.ini index ac88f73..7cb23f7 100644 --- a/unit_envpro_env.ini +++ b/unit_envpro_env.ini @@ -33,10 +33,9 @@ lib_deps = ${StampS3.lib_deps} test_filter= embedded/test_bme688 [env:test_BME688_Dial] -extends=StampS3, option_release, arduino_latest -lib_deps = ${StampS3.lib_deps} - ${test_fw.lib_deps} - m5stack/M5Dial +extends=Dial, option_release, arduino_latest +lib_deps = ${Dial.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bme688 [env:test_BME688_Atom] From b35dee94e7cda13545b745c713538d0becbd4596 Mon Sep 17 00:00:00 2001 From: GOB Date: Thu, 5 Mar 2026 18:17:00 +0900 Subject: [PATCH 14/22] Raise version to 1.3.2 --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 3a3b4db..d0a7925 100644 --- a/library.json +++ b/library.json @@ -15,7 +15,7 @@ "boschsensortec/BME68x Sensor library": ">=1.3.40408", "boschsensortec/bsec2": ">=1.10.2610" }, - "version": "1.3.1", + "version": "1.3.2", "frameworks": [ "arduino" ], diff --git a/library.properties b/library.properties index b0930ce..bcdc5ad 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=M5Unit-ENV -version=1.3.1 +version=1.3.2 author=M5Stack maintainer=M5Stack sentence=Library for M5Stack UNIT ENV From d798d88ff26ed91365d2baf029a97012cc02a07b Mon Sep 17 00:00:00 2001 From: GOB Date: Thu, 5 Mar 2026 23:20:09 +0900 Subject: [PATCH 15/22] Fix missing build_flags merge for Cardputer and Tab5 environments --- unit_co2_env.ini | 32 ++++++++++++++++++++++++-------- unit_env3_env.ini | 28 ++++++++++++++++++++-------- unit_env4_env.ini | 20 ++++++++++++++++---- unit_envpro_env.ini | 16 ++++++++++++---- unit_tvoc_env.ini | 16 ++++++++++++---- 5 files changed, 84 insertions(+), 28 deletions(-) diff --git a/unit_co2_env.ini b/unit_co2_env.ini index 7fdf78d..bcb195e 100644 --- a/unit_co2_env.ini +++ b/unit_co2_env.ini @@ -96,14 +96,18 @@ test_filter= embedded/test_scd40 [env:test_SCD40_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd40 [env:test_SCD40_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd40 [env:test_SCD40_NessoN1] @@ -207,14 +211,18 @@ test_filter= embedded/test_scd41 [env:test_SCD41_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd41 [env:test_SCD41_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_scd41 [env:test_SCD41_NessoN1] @@ -290,10 +298,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/Plot [env:UnitCO2_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> [env:UnitCO2_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2/PlotToSerial> [env:UnitCO2_PlotToSerial_NessoN1_Arduino_latest] @@ -366,10 +378,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/Plo [env:UnitCO2L_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> [env:UnitCO2L_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitCO2L/PlotToSerial> [env:UnitCO2L_PlotToSerial_NessoN1_Arduino_latest] diff --git a/unit_env3_env.ini b/unit_env3_env.ini index 16b5207..8460862 100644 --- a/unit_env3_env.ini +++ b/unit_env3_env.ini @@ -96,14 +96,18 @@ test_filter= embedded/test_sht30 [env:test_SHT30_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht30 [env:test_SHT30_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sht30 [env:test_SHT30_NessoN1] @@ -207,14 +211,18 @@ test_filter= embedded/test_qmp6988 [env:test_QMP6988_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 [env:test_QMP6988_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_qmp6988 [env:test_QMP6988_NessoN1] @@ -289,10 +297,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/P [env:UnitENVIII_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> [env:UnitENVIII_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIII/PlotToSerial> [env:UnitENVIII_PlotToSerial_NessoN1_Arduino_latest] diff --git a/unit_env4_env.ini b/unit_env4_env.ini index 6ed94cb..2efdcb1 100644 --- a/unit_env4_env.ini +++ b/unit_env4_env.ini @@ -96,12 +96,16 @@ test_filter= embedded/test_sht40 [env:test_SHT40_Cardputer] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} lib_deps = ${Cardputer.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht40 [env:test_SHT40_Tab5] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} lib_deps = ${Tab5.lib_deps} ${test_fw.lib_deps} test_filter= embedded/test_sht40 @@ -207,14 +211,18 @@ test_filter= embedded/test_bmp280 [env:test_BMP280_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bmp280 [env:test_BMP280_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bmp280 [env:test_BMP280_NessoN1] @@ -288,10 +296,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/Pl [env:UnitENVIV_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> [env:UnitENVIV_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVIV/PlotToSerial> [env:UnitENVIV_PlotToSerial_NessoN1_Arduino_latest] diff --git a/unit_envpro_env.ini b/unit_envpro_env.ini index 7cb23f7..cde2c13 100644 --- a/unit_envpro_env.ini +++ b/unit_envpro_env.ini @@ -96,14 +96,18 @@ test_filter= embedded/test_bme688 [env:test_BME688_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bme688 [env:test_BME688_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_bme688 [env:test_BME688_NessoN1] @@ -178,10 +182,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/P [env:UnitENVPro_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> [env:UnitENVPro_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitENVPro/PlotToSerial> [env:UnitENVPro_PlotToSerial_NessoN1_Arduino_latest] diff --git a/unit_tvoc_env.ini b/unit_tvoc_env.ini index 1caa0df..0482af4 100644 --- a/unit_tvoc_env.ini +++ b/unit_tvoc_env.ini @@ -95,14 +95,18 @@ test_filter= embedded/test_sgp30 [env:test_SGP30_Cardputer] extends=Cardputer, option_release, arduino_latest -lib_deps = ${Cardputer.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} +lib_deps = ${Cardputer.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sgp30 [env:test_SGP30_Tab5] extends=Tab5, option_release, pioarduino_latest -lib_deps = ${Tab5.lib_deps} - ${test_fw.lib_deps} +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} +lib_deps = ${Tab5.lib_deps} + ${test_fw.lib_deps} test_filter= embedded/test_sgp30 [env:test_SGP30_NessoN1] @@ -178,10 +182,14 @@ build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/Plo [env:UnitTVOC_PlotToSerial_Cardputer_Arduino_latest] extends=Cardputer, option_release, arduino_latest +build_flags = ${Cardputer.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> [env:UnitTVOC_PlotToSerial_Tab5_Arduino_latest] extends=Tab5, option_release, pioarduino_latest +build_flags = ${Tab5.build_flags} + ${option_release.build_flags} build_src_filter = +<*> -<.git/> -<.svn/> +<../examples/UnitUnified/UnitTVOC/PlotToSerial> [env:UnitTVOC_PlotToSerial_NessoN1_Arduino_latest] From 277a756fde070c4fd9359b668b9cd10fc166322f Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 02:32:38 +0900 Subject: [PATCH 16/22] Fix typos in Doxygen comments and rename UltraHightAccuracy to UltraHighAccuracy --- src/unit/unit_BME688.hpp | 2 +- src/unit/unit_BMP280.hpp | 2 +- src/unit/unit_QMP6988.cpp | 2 +- src/unit/unit_QMP6988.hpp | 4 +++- src/unit/unit_SHT40.hpp | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/unit/unit_BME688.hpp b/src/unit/unit_BME688.hpp index ad78f56..df81c2e 100644 --- a/src/unit/unit_BME688.hpp +++ b/src/unit/unit_BME688.hpp @@ -90,7 +90,7 @@ using bme68xCalibration = struct bme68x_calib_data; ///@} /*! - @enum Oversamping + @enum Oversampling @brief Sampling setting */ enum class Oversampling : uint8_t { diff --git a/src/unit/unit_BMP280.hpp b/src/unit/unit_BMP280.hpp index b62b865..ca302cb 100644 --- a/src/unit/unit_BMP280.hpp +++ b/src/unit/unit_BMP280.hpp @@ -99,7 +99,7 @@ enum class UseCase : uint8_t { }; /*! - @union Trimmming + @union Trimming @brief Trimming parameter */ union Trimming { diff --git a/src/unit/unit_QMP6988.cpp b/src/unit/unit_QMP6988.cpp index a6f41fb..b1c62f4 100644 --- a/src/unit/unit_QMP6988.cpp +++ b/src/unit/unit_QMP6988.cpp @@ -51,7 +51,7 @@ constexpr UseCaseSetting uc_table[] = { {OversamplingSetting::LowPower, Filter::Off}, {OversamplingSetting::Standard, Filter::Coeff4}, {OversamplingSetting::HighAccuracy, Filter::Coeff8}, - {OversamplingSetting::UltraHightAccuracy, Filter::Coeff32}, + {OversamplingSetting::UltraHighAccuracy, Filter::Coeff32}, }; #if 1 diff --git a/src/unit/unit_QMP6988.hpp b/src/unit/unit_QMP6988.hpp index d55b478..96daf78 100644 --- a/src/unit/unit_QMP6988.hpp +++ b/src/unit/unit_QMP6988.hpp @@ -53,7 +53,9 @@ enum class OversamplingSetting : uint8_t { LowPower, //!< osrsP:X4 osrsT:X1 Standard, //!< osrsP:X8 osrsT:X1 HighAccuracy, //!< osrsP:X16 osrsT:X2 - UltraHightAccuracy, //!< osrsP:X32 osrsT:X4 + UltraHighAccuracy, //!< osrsP:X32 osrsT:X4 + //! @deprecated Use UltraHighAccuracy instead + UltraHightAccuracy [[deprecated("Use UltraHighAccuracy")]] = UltraHighAccuracy, }; /*! diff --git a/src/unit/unit_SHT40.hpp b/src/unit/unit_SHT40.hpp index 77a4ab8..d86a4c0 100644 --- a/src/unit/unit_SHT40.hpp +++ b/src/unit/unit_SHT40.hpp @@ -146,7 +146,7 @@ class UnitSHT40 : public Component, public PeriodicMeasurementAdapter Date: Fri, 6 Mar 2026 02:33:05 +0900 Subject: [PATCH 17/22] Update test to use renamed UltraHighAccuracy --- test/embedded/test_qmp6988/qmp6988_test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/embedded/test_qmp6988/qmp6988_test.cpp b/test/embedded/test_qmp6988/qmp6988_test.cpp index 9c41226..b527729 100644 --- a/test/embedded/test_qmp6988/qmp6988_test.cpp +++ b/test/embedded/test_qmp6988/qmp6988_test.cpp @@ -46,7 +46,7 @@ constexpr Oversampling os_table[] = { constexpr OversamplingSetting oss_table[] = { OversamplingSetting::HighSpeed, OversamplingSetting::LowPower, OversamplingSetting::Standard, - OversamplingSetting::HighAccuracy, OversamplingSetting::UltraHightAccuracy, + OversamplingSetting::HighAccuracy, OversamplingSetting::UltraHighAccuracy, }; constexpr Oversampling osrss_table[][2] = { @@ -85,7 +85,7 @@ constexpr UseCaseSetting uc_val_table[] = { {OversamplingSetting::LowPower, Filter::Off}, {OversamplingSetting::Standard, Filter::Coeff4}, {OversamplingSetting::HighAccuracy, Filter::Coeff8}, - {OversamplingSetting::UltraHightAccuracy, Filter::Coeff32}, + {OversamplingSetting::UltraHighAccuracy, Filter::Coeff32}, }; } // namespace From 9ea1ad389b9c89ee55978ab8a30977c83a6a6c6f Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 02:33:43 +0900 Subject: [PATCH 18/22] Fixes typo --- .github/workflows/doxygen-gh-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/doxygen-gh-pages.yml b/.github/workflows/doxygen-gh-pages.yml index 9554f74..59c8172 100644 --- a/.github/workflows/doxygen-gh-pages.yml +++ b/.github/workflows/doxygen-gh-pages.yml @@ -1,4 +1,4 @@ -name: Deploy Doxygen docuemnt on GitHub Pages +name: Deploy Doxygen document on GitHub Pages on: [release, workflow_dispatch] # branches: # - main From 827e521a9bf07102f7309fca7e28c08e8775ba74 Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 02:34:54 +0900 Subject: [PATCH 19/22] Fixes ENVIV documentation link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ca6eb1..c8f9269 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ CO2 is a photoacoustic Carbon Dioxide (CO2) Unit that will tell you the CO2 PPM ## Related Link -- [Unit ENVIV - Document & Datasheet](https://docs.m5stack.com/en/unit/ENV%E2%85%A3%20Unit) +- [Unit ENVIV - Document & Datasheet](https://docs.m5stack.com/en/unit/Unit_ENV-IV) - [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) From 62442a071600adaf2b24b7de413c4f050b60e095 Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 02:35:27 +0900 Subject: [PATCH 20/22] Bump M5UnitUnified dependency to >=0.4.1 --- library.json | 2 +- platformio.ini | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index d0a7925..1b87428 100644 --- a/library.json +++ b/library.json @@ -11,7 +11,7 @@ "url": "https://github.com/m5stack/M5Unit-ENV.git" }, "dependencies": { - "m5stack/M5UnitUnified": ">=0.4.0", + "m5stack/M5UnitUnified": ">=0.4.1", "boschsensortec/BME68x Sensor library": ">=1.3.40408", "boschsensortec/bsec2": ">=1.10.2610" }, diff --git a/platformio.ini b/platformio.ini index 4f1f69f..3402975 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,7 +11,7 @@ lib_ldf_mode = deep test_framework = googletest test_build_src = true lib_deps=m5stack/M5Unified - m5stack/M5UnitUnified@>=0.4.0 + m5stack/M5UnitUnified@>=0.4.1 boschsensortec/BME68x Sensor library@>=1.3.40408 ; -------------------------------- From ae260df80545b8e58ded4cdbb81879df1e261033 Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 02:56:13 +0900 Subject: [PATCH 21/22] Cosmetic change --- src/unit/unit_QMP6988.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/unit/unit_QMP6988.hpp b/src/unit/unit_QMP6988.hpp index 96daf78..95de375 100644 --- a/src/unit/unit_QMP6988.hpp +++ b/src/unit/unit_QMP6988.hpp @@ -49,11 +49,11 @@ enum class Oversampling : uint8_t { @brief Oversampling Settings */ enum class OversamplingSetting : uint8_t { - HighSpeed, //!< osrsP:X2 osrsT:X1 - LowPower, //!< osrsP:X4 osrsT:X1 - Standard, //!< osrsP:X8 osrsT:X1 - HighAccuracy, //!< osrsP:X16 osrsT:X2 - UltraHighAccuracy, //!< osrsP:X32 osrsT:X4 + HighSpeed, //!< osrsP:X2 osrsT:X1 + LowPower, //!< osrsP:X4 osrsT:X1 + Standard, //!< osrsP:X8 osrsT:X1 + HighAccuracy, //!< osrsP:X16 osrsT:X2 + UltraHighAccuracy, //!< osrsP:X32 osrsT:X4 //! @deprecated Use UltraHighAccuracy instead UltraHightAccuracy [[deprecated("Use UltraHighAccuracy")]] = UltraHighAccuracy, }; From 105f91aa432f0a379331b6e5755eab83ab5c36d0 Mon Sep 17 00:00:00 2001 From: GOB Date: Fri, 6 Mar 2026 03:16:24 +0900 Subject: [PATCH 22/22] Cosmetic change --- test/embedded/test_qmp6988/qmp6988_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/embedded/test_qmp6988/qmp6988_test.cpp b/test/embedded/test_qmp6988/qmp6988_test.cpp index b527729..33a6a7d 100644 --- a/test/embedded/test_qmp6988/qmp6988_test.cpp +++ b/test/embedded/test_qmp6988/qmp6988_test.cpp @@ -45,7 +45,7 @@ constexpr Oversampling os_table[] = { }; constexpr OversamplingSetting oss_table[] = { - OversamplingSetting::HighSpeed, OversamplingSetting::LowPower, OversamplingSetting::Standard, + OversamplingSetting::HighSpeed, OversamplingSetting::LowPower, OversamplingSetting::Standard, OversamplingSetting::HighAccuracy, OversamplingSetting::UltraHighAccuracy, };