Skip to content

Commit

Permalink
[Telink] Add Mars board overlay and real measurment of sht3xd sensor
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiiSalamakha committed Oct 24, 2023
1 parent f74e95b commit bc858f6
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 15 deletions.
5 changes: 5 additions & 0 deletions config/telink/chip-module/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,8 @@ config CHIP_ENABLE_POWER_ON_FACTORY_RESET
Enable power on factory reset sequence. If device power triggered off during
first 5 seconds after power on and this sequence repeated 5 times - factory
reset will be involved.

config CHIP_USE_MARS_SENSOR
bool "Use Mars board sensor"
depends on SOC_SERIES_RISCV_TELINK_B9X && (BOARD_TLSR9518ADK80D || BOARD_TLSR9518ADK80D_RETENTION)
default n
24 changes: 21 additions & 3 deletions examples/air-quality-sensor-app/telink/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ get_filename_component(CHIP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/connect
get_filename_component(TELINK_COMMON ${CHIP_ROOT}/examples/platform/telink REALPATH)
get_filename_component(GEN_DIR ${CHIP_ROOT}/zzz_generated/ REALPATH)

set(ignoreMe "${TLNK_MARS_BOARD}")

if(${TLNK_MARS_BOARD} MATCHES y)
if(EXISTS "${CHIP_ROOT}/src/platform/telink/${BOARD}_mars.overlay")
set(MARS_DTC_OVERLAY_FILE "${CHIP_ROOT}/src/platform/telink/${BOARD}_mars.overlay")
else()
unset(MARS_DTC_OVERLAY_FILE)
endif()
if(EXISTS "${CHIP_ROOT}/src/platform/telink/${BOARD}_mars.conf")
set(MARS_CONF_OVERLAY_FILE "${CHIP_ROOT}/src/platform/telink/${BOARD}_mars.conf")
else()
unset(MARS_CONF_OVERLAY_FILE)
endif()
else()
unset(MARS_CONF_OVERLAY_FILE)
endif()

if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD}.overlay")
set(LOCAL_DTC_OVERLAY_FILE "${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD}.overlay")
else()
Expand All @@ -41,14 +58,14 @@ endif()

if(DTC_OVERLAY_FILE)
set(DTC_OVERLAY_FILE
"${DTC_OVERLAY_FILE} ${GLOBAL_DTC_OVERLAY_FILE} ${FLASH_DTC_OVERLAY_FILE} ${LOCAL_DTC_OVERLAY_FILE}"
"${DTC_OVERLAY_FILE} ${GLOBAL_DTC_OVERLAY_FILE} ${MARS_DTC_OVERLAY_FILE} ${FLASH_DTC_OVERLAY_FILE} ${LOCAL_DTC_OVERLAY_FILE}"
CACHE STRING "" FORCE
)
else()
set(DTC_OVERLAY_FILE ${GLOBAL_DTC_OVERLAY_FILE} ${FLASH_DTC_OVERLAY_FILE} ${LOCAL_DTC_OVERLAY_FILE})
set(DTC_OVERLAY_FILE ${GLOBAL_DTC_OVERLAY_FILE} ${MARS_DTC_OVERLAY_FILE} ${FLASH_DTC_OVERLAY_FILE} ${LOCAL_DTC_OVERLAY_FILE})
endif()

set(CONF_FILE prj.conf)
set(CONF_FILE ${MARS_CONF_OVERLAY_FILE} prj.conf)

# Load NCS/Zephyr build system
list(APPEND ZEPHYR_EXTRA_MODULES ${CHIP_ROOT}/config/telink/chip-module)
Expand All @@ -75,6 +92,7 @@ add_definitions(

target_sources(app PRIVATE
src/AppTask.cpp
src/SensorManager.cpp
src/ZclCallbacks.cpp
${TELINK_COMMON}/common/src/mainCommon.cpp
${TELINK_COMMON}/common/src/AppTaskCommon.cpp
Expand Down
4 changes: 3 additions & 1 deletion examples/air-quality-sensor-app/telink/include/AppTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class AppTask : public AppTaskCommon

CHIP_ERROR Init(void);

static void AirQualityActionEventHandler(AppEvent * aEvent);
static void AirQualitySensorMeasurTimerTimeoutCallback(k_timer * timer);
static void AirQualitySensorBanForNextMeasurTimerTimeoutCallback(k_timer * timer);
static void AirQualitySensorMeasurActionEventHandler(AppEvent * aEvent);

static AppTask sAppTask;
};
Expand Down
44 changes: 44 additions & 0 deletions examples/air-quality-sensor-app/telink/include/SensorManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <stdbool.h>
#include <stdint.h>

#include "AppEventCommon.h"

#include <app-common/zap-generated/attributes/Accessors.h>
#include <lib/core/CHIPError.h>

class SensorManager
{
public:
CHIP_ERROR Init();
CHIP_ERROR GetTempAndHumMeasurValue(int16_t *pTempMeasured, uint16_t *pHumMeasured);

private:
friend SensorManager & SensorMgr();

static SensorManager sSensorManager;
};

inline SensorManager & SensorMgr()
{
return SensorManager::sSensorManager;
}
2 changes: 1 addition & 1 deletion examples/air-quality-sensor-app/telink/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ CONFIG_CHIP_FACTORY_DATA_BUILD=n
CONFIG_CHIP_FACTORY_DATA_MERGE_WITH_FIRMWARE=n

# Enable Power Management
CONFIG_PM=y
CONFIG_PM=n
95 changes: 85 additions & 10 deletions examples/air-quality-sensor-app/telink/src/AppTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,125 @@
*/

#include "AppTask.h"
#include "SensorManager.h"
#include <air-quality-sensor-manager.h>

LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);

using namespace chip;
using namespace ::chip::app::Clusters;
using namespace ::chip::app::Clusters::AirQuality;

AppTask AppTask::sAppTask;
namespace {
volatile bool mSensorBanForNextMeasur = false;
k_timer sSensorMeasurTimer;
k_timer sSensorBanForNextMeasurTimer;
constexpr uint16_t kSensorMeasurTimerPeriodMs = 10000; // 10s timer period
constexpr uint16_t kSensorBanForNextMeasurTimeoutMs = 1000; // 1s timeout
} // namespace

constexpr EndpointId kAirQualityEndpoint = 1;
AppTask AppTask::sAppTask;

CHIP_ERROR AppTask::Init(void)
{
CHIP_ERROR ret;

#if APP_USE_EXAMPLE_START_BUTTON
SetExampleButtonCallbacks(AirQualityActionEventHandler);
SetExampleButtonCallbacks(AirQualitySensorMeasurActionEventHandler);
#endif
InitCommonParts();

AirQualitySensorManager::InitInstance(kAirQualityEndpoint);
ret = SensorMgr().Init();
if (ret != CHIP_NO_ERROR)
{
LOG_ERR("Init of the Sensor Manager failed");
return ret;
}

// Initialize sensor measurement timer
k_timer_init(&sSensorMeasurTimer, &AppTask::AirQualitySensorMeasurTimerTimeoutCallback, nullptr);
k_timer_user_data_set(&sSensorMeasurTimer, this);
k_timer_start(&sSensorMeasurTimer, K_MSEC(kSensorMeasurTimerPeriodMs), K_NO_WAIT);

// Initialise the timer to ban sensor measurement
k_timer_init(&sSensorBanForNextMeasurTimer, &AppTask::AirQualitySensorBanForNextMeasurTimerTimeoutCallback, nullptr);
k_timer_user_data_set(&sSensorBanForNextMeasurTimer, this);

AirQualitySensorManager::InitInstance(kExampleEndpointId);

return CHIP_NO_ERROR;
}

void AppTask::UpdateClusterState(void)
{
CHIP_ERROR ret;
AirQualitySensorManager * mInstance = AirQualitySensorManager::GetInstance();
static int16_t temperature = 0;
static uint16_t humidity = 0;

if (!mSensorBanForNextMeasur)
{
ret = SensorMgr().GetTempAndHumMeasurValue(&temperature, &humidity);
if (ret != CHIP_NO_ERROR)
{
LOG_ERR("Update of the Air Quality clusters failed");
return;
}

mSensorBanForNextMeasur = true;

// Start next timer to measurement the air quality sensor
k_timer_start(&sSensorBanForNextMeasurTimer, K_MSEC(kSensorBanForNextMeasurTimeoutMs), K_NO_WAIT);
}

// Update AirQuality value
mInstance->OnAirQualityChangeHandler(AirQualityEnum::kModerate);
mInstance->OnAirQualityChangeHandler(AirQualityEnum::kUnknown);

// Update Carbon Dioxide
mInstance->OnCarbonDioxideMeasurementChangeHandler(400);
mInstance->OnCarbonDioxideMeasurementChangeHandler(0);

// Update Temperature value
mInstance->OnTemperatureMeasurementChangeHandler(18);
mInstance->OnTemperatureMeasurementChangeHandler(temperature);

// Update Humidity value
mInstance->OnHumidityMeasurementChangeHandler(60);
mInstance->OnHumidityMeasurementChangeHandler(humidity);

LOG_INF("Update Air Quality: temperature is %d*0.01°C, humidity is %d", temperature, humidity);
}

void AppTask::AirQualityActionEventHandler(AppEvent * aEvent)
void AppTask::AirQualitySensorMeasurTimerTimeoutCallback(k_timer * timer)
{
if (aEvent->Type == AppEvent::kEventType_Button)
if (!timer)
{
return;
}

AppEvent event;
event.Type = AppEvent::kEventType_Timer;
event.Handler = AirQualitySensorMeasurActionEventHandler;
sAppTask.PostEvent(&event);
}

void AppTask::AirQualitySensorBanForNextMeasurTimerTimeoutCallback(k_timer * timer)
{
if (!timer)
{
return;
}

mSensorBanForNextMeasur = false;
}

void AppTask::AirQualitySensorMeasurActionEventHandler(AppEvent * aEvent)
{
if ((aEvent->Type == AppEvent::kEventType_Button) || (aEvent->Type == AppEvent::kEventType_Timer))
{
sAppTask.UpdateClusterState();
}

if (aEvent->Type == AppEvent::kEventType_Timer)
{
// Start next timer to measurement the air quality sensor
k_timer_start(&sSensorMeasurTimer, K_MSEC(kSensorMeasurTimerPeriodMs), K_NO_WAIT);
}
}
120 changes: 120 additions & 0 deletions examples/air-quality-sensor-app/telink/src/SensorManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "SensorManager.h"
#include "AppConfig.h"
#include "AppTask.h"
#include <zephyr/drivers/sensor.h>

LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);

using namespace chip;
using namespace ::chip::DeviceLayer;

constexpr float kMinTempDelta = 0.5; // 0.5 degree Celsius

#ifdef CONFIG_CHIP_USE_MARS_SENSOR
const struct device *const sht3xd_dev = DEVICE_DT_GET_ONE(sensirion_sht3xd);
#elif
constexpr float kSimulatedHum = 55.5; // percents
constexpr uint16_t kSimulatedReadingFrequency = 5; // change Simulated number
static float mSimulatedTemp[] = { 23.01, 24.02, 28.03, 25.50, 22.05, 21.25, 21.07, 26.08, 18.09, 27.11 };
#endif // CONFIG_CHIP_USE_MARS_SENSOR

SensorManager SensorManager::sSensorManager;

CHIP_ERROR SensorManager::Init()
{
#ifdef CONFIG_CHIP_USE_MARS_SENSOR
if (!device_is_ready(sht3xd_dev))
{
LOG_ERR("Device %s is not ready", sht3xd_dev->name);
return CHIP_ERROR_INCORRECT_STATE;
}
#endif // CONFIG_CHIP_USE_MARS_SENSOR

return CHIP_NO_ERROR;
}

CHIP_ERROR SensorManager::GetTempAndHumMeasurValue(int16_t *pTempMeasured, uint16_t *pHumMeasured)
{
static float lastTemp = 0.0;
float temp = 0.0;
float hum = 0.0;

#ifdef CONFIG_CHIP_USE_MARS_SENSOR
struct sensor_value sensorTemp = {0};
struct sensor_value sensorHum = {0};

int status = sensor_sample_fetch(sht3xd_dev);
if (!status)
{
status = sensor_channel_get(sht3xd_dev, SENSOR_CHAN_AMBIENT_TEMP, &sensorTemp);
}

if (!status)
{
status = sensor_channel_get(sht3xd_dev, SENSOR_CHAN_HUMIDITY, &sensorHum);
}

if (status)
{
LOG_ERR("Device %s is not ready for temperature and humidity measurement (status: %d)", sht3xd_dev->name, status);
return System::MapErrorZephyr(status);
}

temp = (float)sensor_value_to_double(&sensorTemp);
hum = (float)sensor_value_to_double(&sensorHum);
#else
/* Temperature simulation is used */
static uint8_t nbOfRepetition = 0;
static uint8_t simulatedIndex = 0;
if (simulatedIndex >= ArraySize(mSimulatedTemp))
{
simulatedIndex = 0;
}
temp = mSimulatedTemp[simulatedIndex];

nbOfRepetition++;

if (nbOfRepetition >= kSimulatedReadingFrequency)
{
simulatedIndex++;
nbOfRepetition = 0;
}

/* Humidity simulation is used */
hum = kSimulatedHum;

#endif // CONFIG_CHIP_USE_MARS_SENSOR

if ((temp >= (lastTemp + kMinTempDelta)) || temp <= (lastTemp - kMinTempDelta))
{
lastTemp = temp;
}
else
{
temp = lastTemp;
}

// Per spec Application Clusters 2.3.4.1. : MeasuredValue = 100 x temperature [°C]
*pTempMeasured = (int16_t) 100 * temp;
*pHumMeasured = (uint16_t) hum;

return CHIP_NO_ERROR;
}
4 changes: 4 additions & 0 deletions src/platform/telink/tlsr9518adk80d_mars.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CONFIG_CHIP_USE_MARS_SENSOR=y
CONFIG_CHIP_BUTTON_MANAGER_IRQ_MODE=y
CONFIG_I2C=y
CONFIG_SENSOR=y
Loading

0 comments on commit bc858f6

Please sign in to comment.