sTodo-m5paper-client/libraries/M5Unit-ENV/test/embedded/test_sgp30/sgp30_test.cpp
2025-06-30 20:47:33 +02:00

208 lines
5.4 KiB
C++

/*
* SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*
UnitTest for UnitSGP30
*/
#include <gtest/gtest.h>
#include <Wire.h>
#include <M5Unified.h>
#include <M5UnitUnified.hpp>
#include <googletest/test_template.hpp>
#include <googletest/test_helper.hpp>
#include <unit/unit_SGP30.hpp>
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<UnitSGP30, bool> {
protected:
virtual UnitSGP30* get_instance() override
{
auto* ptr = new m5::unit::UnitSGP30();
if (ptr) {
auto ccfg = ptr->component_config();
ccfg.stored_size = 4;
ptr->component_config(ccfg);
auto cfg = ptr->config();
cfg.start_periodic = false;
ptr->config(cfg);
}
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)
{
EXPECT_NE(u->co2eq(), 0xFFFFU);
EXPECT_NE(u->tvoc(), 0XFFFFU);
// readRaw test
uint16_t h{}, e{};
EXPECT_TRUE(u->readRaw(h, e));
EXPECT_NE(h, 0U);
EXPECT_NE(e, 0U);
}
void wait15sec()
{
auto to = m5::utility::millis() + 15 * 1000;
do {
m5::utility::delay(1);
} while (m5::utility::millis() < to);
}
} // namespace
TEST_P(TestSGP30, FeatureSet)
{
SCOPED_TRACE(ustr);
EXPECT_NE(unit->productVersion(), 0U);
M5_LOGI("productVersion:%x", unit->productVersion());
Feature f{};
EXPECT_TRUE(unit->readFeatureSet(f));
EXPECT_EQ(f.productType(), 0U);
EXPECT_NE(f.productVersion(), 0U);
EXPECT_EQ(unit->productVersion(), f.productVersion());
}
TEST_P(TestSGP30, selfTest)
{
SCOPED_TRACE(ustr);
uint16_t result{};
EXPECT_TRUE(unit->measureTest(result));
EXPECT_EQ(result, 0xD400);
}
TEST_P(TestSGP30, serialNumber)
{
SCOPED_TRACE(ustr);
// Read direct [MSB] SNB_3, SNB_2, CRC, SNB_1, SNB_0, CRC [LSB]
std::array<uint8_t, 9> rbuf{};
EXPECT_TRUE(unit->readRegister(command::GET_SERIAL_ID, rbuf.data(), rbuf.size(), 1));
// M5_LOGI("%02x%02x%02x%02x%02x%02x", rbuf[0], rbuf[1], rbuf[3],
// rbuf[4],
// rbuf[6], rbuf[7]);
m5::types::big_uint16_t w0(rbuf[0], rbuf[1]);
m5::types::big_uint16_t w1(rbuf[3], rbuf[4]);
m5::types::big_uint16_t w2(rbuf[6], rbuf[7]);
uint64_t d_sno = (((uint64_t)w0.get()) << 32) | (((uint64_t)w1.get()) << 16) | ((uint64_t)w2.get());
// M5_LOGI("d_sno[%llX]", d_sno);
//
uint64_t sno{};
char ssno[13]{};
EXPECT_TRUE(unit->readSerialNumber(sno));
EXPECT_TRUE(unit->readSerialNumber(ssno));
// M5_LOGI("s:[%s] uint64:[%x]", ssno, sno);
EXPECT_EQ(sno, d_sno);
std::stringstream stream;
stream << std::uppercase << std::setw(12) << std::hex << std::setfill('0') << sno;
std::string s(stream.str());
EXPECT_STREQ(s.c_str(), ssno);
}
TEST_P(TestSGP30, generalReset)
{
SCOPED_TRACE(ustr);
EXPECT_TRUE(unit->startPeriodicMeasurement(0x1234, 0x5678, 0x9ABC));
M5_LOGW("SGP30 measurement starts 15 seconds after begin");
EXPECT_TRUE(unit->inPeriodic());
wait15sec();
uint16_t co2eq{}, tvoc{}, inceptive_tvoc{};
EXPECT_TRUE(unit->readIaqBaseline(co2eq, tvoc));
// EXPECT_TRUE(unit->readTvocInceptiveBaseline(inceptive_tvoc));
// M5_LOGW("%x/%x/%x", co2eq, tvoc, inceptive_tvoc);
EXPECT_EQ(co2eq, 0x1234);
EXPECT_EQ(tvoc, 0x5678);
// EXPECT_EQ(inceptive_tvoc, 0x1122);
EXPECT_TRUE(unit->generalReset());
EXPECT_TRUE(unit->readIaqBaseline(co2eq, tvoc));
// EXPECT_TRUE(unit->readTvocInceptiveBaseline(inceptive_tvoc));
// M5_LOGW("%x/%x/%x", co2eq, tvoc, inceptive_tvoc);
EXPECT_EQ(co2eq, 0x0000);
EXPECT_EQ(tvoc, 0x0000);
// EXPECT_EQ(inceptive_tvoc, 0x0000);
}
TEST_P(TestSGP30, Periodic)
{
SCOPED_TRACE(ustr);
EXPECT_FALSE(unit->inPeriodic());
{
uint32_t cnt{10};
uint16_t h2{}, et{};
while (cnt--) {
EXPECT_TRUE(unit->readRaw(h2, et));
}
}
EXPECT_TRUE(unit->startPeriodicMeasurement(0, 0, 0));
M5_LOGW("SGP30 measurement starts 15 seconds after begin");
EXPECT_TRUE(unit->inPeriodic());
wait15sec();
test_periodic_measurement(unit.get(), 4, check_measurement_values);
EXPECT_TRUE(unit->stopPeriodicMeasurement());
EXPECT_FALSE(unit->inPeriodic());
EXPECT_EQ(unit->available(), 4);
EXPECT_TRUE(unit->full());
EXPECT_FALSE(unit->empty());
uint32_t cnt{2};
while (unit->available() && cnt--) {
EXPECT_FALSE(unit->empty());
// M5_LOGW("C:%u T:%u", unit->co2eq(), unit->tvoc());
EXPECT_EQ(unit->co2eq(), unit->oldest().co2eq());
EXPECT_EQ(unit->tvoc(), unit->oldest().tvoc());
unit->discard();
}
EXPECT_EQ(unit->available(), 2);
EXPECT_FALSE(unit->full());
EXPECT_FALSE(unit->empty());
unit->flush();
EXPECT_EQ(unit->co2eq(), 0XFFFF);
EXPECT_EQ(unit->tvoc(), 0XFFFF);
EXPECT_EQ(unit->available(), 0);
EXPECT_TRUE(unit->empty());
EXPECT_FALSE(unit->full());
}