Merge branch 'example/fan' into 'main'

example: improve fan data-model, add motor driver

See merge request app-frameworks/esp-matter!615
This commit is contained in:
Hrishikesh Dhayagude
2024-06-07 01:03:29 +08:00
13 changed files with 1285 additions and 27 deletions
+4 -4
View File
@@ -11,10 +11,10 @@ if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c3")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c3_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32c2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32h2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32h2_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32c2")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c2_devkit_m)
elseif("${IDF_TARGET}" STREQUAL "esp32c6")
set(ENV{ESP_MATTER_DEVICE_PATH} $ENV{ESP_MATTER_PATH}/device_hal/device/esp32c6_devkit_c)
elseif("${IDF_TARGET}" STREQUAL "esp32s3")
@@ -24,7 +24,7 @@ if(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
endif()
endif(NOT DEFINED ENV{ESP_MATTER_DEVICE_PATH})
set(PROJECT_VER "v1.0")
set(PROJECT_VER "1.0")
set(PROJECT_VER_NUMBER 1)
set(ESP_MATTER_PATH $ENV{ESP_MATTER_PATH})
@@ -52,4 +52,4 @@ idf_build_set_property(CXX_COMPILE_OPTIONS "-std=gnu++17;-Os;-DCHIP_HAVE_CONFIG_
idf_build_set_property(C_COMPILE_OPTIONS "-Os" APPEND)
# For RISCV chips, project_include.cmake sets -Wno-format, but does not clear various
# flags that depend on -Wformat
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security;-Wformat=0" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-security;-Wformat=0" APPEND)
@@ -1,10 +1,31 @@
set(PRIV_REQUIRES_LIST device esp_matter esp_matter_console esp_matter_thread_br app_reset console fatfs hal)
set(SRC_DIRS_LIST ".")
set(INCLUDE_DIRS_LIST ".")
set(ldfragments linker.lf)
idf_component_register(SRC_DIRS "."
# set(PRIV_REQUIRES_LIST device esp_matter esp_matter_console esp_matter_thread_br app_reset console fatfs hal)
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3)
list(APPEND SRC_DIRS_LIST "driver/fan")
list(APPEND INCLUDE_DIRS_LIST "driver/fan/include")
endif()
idf_component_register(SRC_DIRS ${SRC_DIRS_LIST}
PRIV_INCLUDE_DIRS "." "${ESP_MATTER_PATH}/examples/common/utils"
PRIV_REQUIRES ${PRIV_REQUIRES_LIST}
LDFRAGMENTS "${ldfragments}"
)
# PRIV_REQUIRES ${PRIV_REQUIRES_LIST}
INCLUDE_DIRS ${INCLUDE_DIRS_LIST}
LDFRAGMENTS "${ldfragments}")
set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17)
target_compile_options(${COMPONENT_LIB} PRIVATE "-DCHIP_HAVE_CONFIG_H")
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3)
idf_build_get_property(build_components BUILD_COMPONENTS)
#To distinguish between a local component and a component manager
if("espressif__esp_sensorless_bldc_control" IN_LIST build_components)
idf_component_get_property(bldc_lib espressif__esp_sensorless_bldc_control COMPONENT_LIB)
else()
idf_component_get_property(bldc_lib esp_sensorless_bldc_control COMPONENT_LIB)
endif()
cmake_policy(SET CMP0079 NEW)
target_link_libraries(${bldc_lib} PUBLIC ${COMPONENT_LIB})
endif()
@@ -0,0 +1,87 @@
menu "App Driver Configuration"
menu "Fan driver configuration"
menu "upper switch config"
config UPPER_SWITCH_PHASE_U_GPIO
int "upper switch PHASE_U GPIO"
default 25 if IDF_TARGET_ESP32
default 17 if IDF_TARGET_ESP32S3
default 17
config UPPER_SWITCH_PHASE_V_GPIO
int "upper switch PHASE_V GPIO"
default 26 if IDF_TARGET_ESP32
default 16 if IDF_TARGET_ESP32S3
default 16
config UPPER_SWITCH_PHASE_W_GPIO
int "upper switch PHASE_W GPIO"
default 27 if IDF_TARGET_ESP32
default 15 if IDF_TARGET_ESP32S3
default 15
endmenu
menu "lower switch config"
config LOWER_SWITCH_PHASE_U_GPIO
int "lower switch PHASE_U GPIO"
default 16 if IDF_TARGET_ESP32
default 12 if IDF_TARGET_ESP32S3
default 12
config LOWER_SWITCH_PHASE_V_GPIO
int "lower switch PHASE_V GPIO"
default 17 if IDF_TARGET_ESP32
default 11 if IDF_TARGET_ESP32S3
default 11
config LOWER_SWITCH_PHASE_W_GPIO
int "lower switch PHASE_W GPIO"
default 5 if IDF_TARGET_ESP32
default 10 if IDF_TARGET_ESP32S3
default 10
endmenu
menu "zero cross comparer config"
config ZERO_CROSS_COMPARER_PHASE_U_GPIO
int "zero cross comparer PHASE_U GPIO"
default 3 if IDF_TARGET_ESP32
default 3 if IDF_TARGET_ESP32S3
default 3
config ZERO_CROSS_COMPARER_PHASE_V_GPIO
int "zero cross comparer PHASE_V GPIO"
default 18 if IDF_TARGET_ESP32
default 46 if IDF_TARGET_ESP32S3
default 46
config ZERO_CROSS_COMPARER_PHASE_W_GPIO
int "zero cross comparer PHASE_W GPIO"
default 2 if IDF_TARGET_ESP32
default 9 if IDF_TARGET_ESP32S3
default 9
endmenu
menu "Step motor config"
config STEP_MOTOR_A0_GPIO
int "Step motor A+ GPIO"
default 12 if IDF_TARGET_ESP32
default 14 if IDF_TARGET_ESP32S3
default 14
config STEP_MOTOR_A1_GPIO
int "Step motor A- GPIO"
default 13 if IDF_TARGET_ESP32
default 21 if IDF_TARGET_ESP32S3
default 21
config STEP_MOTOR_B0_GPIO
int "Step motor B+ GPIO"
default 14 if IDF_TARGET_ESP32
default 47 if IDF_TARGET_ESP32S3
default 47
config STEP_MOTOR_B1_GPIO
int "Step motor B- GPIO"
default 15 if IDF_TARGET_ESP32
default 48 if IDF_TARGET_ESP32S3
default 48
endmenu
config POWER_BUTTON_GPIO
int "Power Button GPIO"
default 0
endmenu
endmenu
@@ -0,0 +1,308 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "esp_matter.h"
#include "esp_err.h"
#include <device.h>
#include <protocols/Protocols.h>
#include <app_priv.h>
#include <app/clusters/fan-control-server/fan-control-delegate.h>
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
#include "fan_hal_stepper_motor.h"
#include "fan_hal_bldc.h"
#endif
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::FanControl;
using namespace esp_matter;
using namespace esp_matter::attribute;
using namespace esp_matter::cluster;
using namespace esp_matter::endpoint;
static const char *TAG = "app_driver";
extern uint16_t app_endpoint_id;
static void get_attribute(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val)
{
node_t *node = node::get();
endpoint_t *endpoint = endpoint::get(node, endpoint_id);
cluster_t *cluster = cluster::get(endpoint, cluster_id);
attribute_t *attribute = attribute::get(cluster, attribute_id);
attribute::get_val(attribute, val);
}
static esp_err_t set_attribute(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t val)
{
node_t *node = node::get();
endpoint_t *endpoint = endpoint::get(node, endpoint_id);
cluster_t *cluster = cluster::get(endpoint, cluster_id);
attribute_t *attribute = attribute::get(cluster, attribute_id);
return attribute::set_val(attribute, &val);
}
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
chip::Protocols::InteractionModel::Status FanDelegateImpl::HandleStep(chip::app::Clusters::FanControl::StepDirectionEnum aDirection, bool aWrap, bool aLowestOff)
{
uint8_t lowest = 0;
static int8_t max_speed = HIGH_MODE_PERCENT_MAX;
int8_t tmp = 0;
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
get_attribute(app_endpoint_id, FanControl::Id, FanControl::Attributes::PercentSetting::Id, &val);
tmp = val.val.u8;
ESP_LOGI(TAG, "Step received value: %d %d %d", (uint8_t)aDirection, aWrap, aLowestOff);
/* Update percent-setting when speed is changed by the step command */
if (aLowestOff)
lowest = 0;
else
lowest = 1;
if ((uint8_t)aDirection == 0) {
tmp += 1;
if (aWrap == 0) {
tmp = tmp > max_speed ? max_speed:tmp;
} else {
tmp = tmp > max_speed ? lowest:tmp;
}
} else if ((uint8_t)aDirection == 1) {
tmp -= 1;
if (aWrap == 0) {
tmp = tmp < lowest ? lowest:tmp;
} else {
tmp = tmp < lowest ? max_speed:tmp;
}
}
val.val.u8 = tmp;
attribute::update(app_endpoint_id, FanControl::Id, FanControl::Attributes::PercentSetting::Id, &val);
return chip::Protocols::InteractionModel::Status::Success;
}
static esp_err_t app_driver_fan_set_mode(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGI(TAG, "Mode received value = %d ", val->val.i);
hal_bldc_set_wind(0);
if (val->val.i == 0) {
hal_stepper_motor_set_rock(0);
}
hal_bldc_set_fanmode(val->val.i);
return ESP_OK;
}
static esp_err_t app_driver_fan_set_percent(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
hal_bldc_set_wind(0);
ESP_LOGI(TAG, "Percent received value = %d ", val->val.i);
hal_bldc_set_percent_speed(val->val.i);
return ESP_OK;
}
static esp_err_t app_driver_fan_set_rock(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGI(TAG, "Shake received value = %d ", val->val.i);
return hal_stepper_motor_set_rock(val->val.i);
}
static esp_err_t app_driver_fan_set_wind(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGI(TAG, "Wind received value = %d", val->val.i);
hal_bldc_set_wind(val->val.i);
/* When exit nature wind mode, set fan speed value to the pre-set percent-setting */
if (val->val.i != 2) {
esp_matter_attr_val_t val = esp_matter_invalid(NULL);
get_attribute(app_endpoint_id, FanControl::Id, FanControl::Attributes::PercentSetting::Id, &val);
attribute::update(app_endpoint_id, FanControl::Id, FanControl::Attributes::PercentSetting::Id, &val);
}
return ESP_OK;
}
static esp_err_t app_driver_fan_set_airflow_direction(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGI(TAG, "Airflow_Direction received value = %d", val->val.b);
return hal_bldc_set_airflow_direction(val->val.b);
}
#else
static esp_err_t app_driver_fan_set_mode(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGE(TAG, "don't support");
return ESP_ERR_NOT_SUPPORTED;
}
static esp_err_t app_driver_fan_set_percent(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGE(TAG, "don't support");
return ESP_ERR_NOT_SUPPORTED;
}
static esp_err_t app_driver_fan_set_rock(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGE(TAG, "don't support");
return ESP_ERR_NOT_SUPPORTED;
}
static esp_err_t app_driver_fan_set_wind(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGE(TAG, "don't support");
return ESP_ERR_NOT_SUPPORTED;
}
static esp_err_t app_driver_fan_set_airflow_direction(fan_driver_handle_t handle, esp_matter_attr_val_t *val)
{
ESP_LOGE(TAG, "don't support");
return ESP_ERR_NOT_SUPPORTED;
}
#endif
static bool check_if_mode_percent_match(uint8_t fan_mode, uint8_t percent)
{
switch (fan_mode) {
case chip::to_underlying(FanModeEnum::kHigh): {
if (percent < HIGH_MODE_PERCENT_MIN) {
return false;
}
break;
}
case chip::to_underlying(FanModeEnum::kMedium): {
if ((percent < MED_MODE_PERCENT_MIN) || (percent > MED_MODE_PERCENT_MAX)) {
return false;
}
break;
}
case chip::to_underlying(FanModeEnum::kLow): {
if ((percent < LOW_MODE_PERCENT_MIN) || (percent > LOW_MODE_PERCENT_MAX)) {
return false;
}
break;
}
default:
return false;
}
return true;
}
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val)
{
esp_err_t err = ESP_OK;
if (endpoint_id == app_endpoint_id) {
fan_driver_handle_t handle = (fan_driver_handle_t)driver_handle;
if (cluster_id == FanControl::Id) {
if (attribute_id == FanControl::Attributes::FanMode::Id) {
esp_matter_attr_val_t val_a = esp_matter_invalid(NULL);
get_attribute(endpoint_id, FanControl::Id, Attributes::PercentSetting::Id, &val_a);
/* When FanMode attribute change , should check the persent setting value, if this value not match
FanMode, need write the persent setting value to corresponding value. Now we set it to the max
value of the FanMode */
if (!check_if_mode_percent_match(val->val.u8, val_a.val.u8)) {
switch (val->val.u8) {
case chip::to_underlying(FanModeEnum::kHigh): {
val_a.val.u8 = HIGH_MODE_PERCENT_MAX;
set_attribute(endpoint_id, FanControl::Id, Attributes::PercentSetting::Id, val_a);
set_attribute(endpoint_id, FanControl::Id, Attributes::SpeedSetting::Id, val_a);
break;
}
case chip::to_underlying(FanModeEnum::kMedium): {
val_a.val.u8 = MED_MODE_PERCENT_MAX;
set_attribute(endpoint_id, FanControl::Id, Attributes::PercentSetting::Id, val_a);
set_attribute(endpoint_id, FanControl::Id, Attributes::SpeedSetting::Id, val_a);
break;
}
case chip::to_underlying(FanModeEnum::kLow): {
val_a.val.u8 = LOW_MODE_PERCENT_MAX;
set_attribute(endpoint_id, FanControl::Id, Attributes::PercentSetting::Id, val_a);
set_attribute(endpoint_id, FanControl::Id, Attributes::SpeedSetting::Id, val_a);
break;
}
case chip::to_underlying(FanModeEnum::kAuto): {
/* add auto mode driver for auto logic */
break;
}
case chip::to_underlying(FanModeEnum::kOff): {
/* add off mode driver if needed */
break;
}
default:
break;
}
}
set_attribute(endpoint_id, FanControl::Id, FanControl::Attributes::PercentCurrent::Id, val_a);
set_attribute(endpoint_id, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id, val_a);
err = app_driver_fan_set_mode(handle, val);
} else if (attribute_id == FanControl::Attributes::PercentSetting::Id) {
esp_matter_attr_val_t val_b = esp_matter_invalid(NULL);
get_attribute(endpoint_id, FanControl::Id, Attributes::FanMode::Id, &val_b);
if (!check_if_mode_percent_match(val_b.val.u8, val->val.u8)) {
if (val->val.u8 >= HIGH_MODE_PERCENT_MIN) {
/* set high mode */
val_b.val.u8 = chip::to_underlying(FanModeEnum::kHigh);
set_attribute(endpoint_id, FanControl::Id, Attributes::FanMode::Id, val_b);
} else if (val->val.u8 >= MED_MODE_PERCENT_MIN) {
/* set med mode */
val_b.val.u8 = chip::to_underlying(FanModeEnum::kMedium);
set_attribute(endpoint_id, FanControl::Id, Attributes::FanMode::Id, val_b);
} else if (val->val.u8 >= LOW_MODE_PERCENT_MIN) {
/* set low mode */
val_b.val.u8 = chip::to_underlying(FanModeEnum::kLow);
set_attribute(endpoint_id, FanControl::Id, Attributes::FanMode::Id, val_b);
}
}
set_attribute(endpoint_id, FanControl::Id, FanControl::Attributes::PercentCurrent::Id, *val);
set_attribute(endpoint_id, FanControl::Id, FanControl::Attributes::SpeedCurrent::Id, *val);
err = app_driver_fan_set_percent(handle, val);
} else if (attribute_id == FanControl::Attributes::RockSetting::Id) {
err = app_driver_fan_set_rock(handle, val);
} else if (attribute_id == FanControl::Attributes::WindSetting::Id) {
err = app_driver_fan_set_wind(handle, val);
} else if (attribute_id == FanControl::Attributes::AirflowDirection::Id) {
err = app_driver_fan_set_airflow_direction(handle, val);
}
}
}
return err;
}
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
esp_err_t fan_driver_init()
{
esp_err_t err = ESP_OK;
/* initializing brushless motor */
bldc_variable_init();
err = hal_bldc_init(CW);
/* initializing step motor */
err = hal_stepper_motor_init((gpio_num_t)CONFIG_STEP_MOTOR_A0_GPIO, (gpio_num_t)CONFIG_STEP_MOTOR_A1_GPIO, (gpio_num_t)CONFIG_STEP_MOTOR_B0_GPIO, (gpio_num_t)CONFIG_STEP_MOTOR_B1_GPIO);
return err;
}
#endif
esp_err_t app_driver_init()
{
esp_err_t err = ESP_OK;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
/* initializing fan driver */
fan_driver_init();
#endif
return err;
}
@@ -5,9 +5,13 @@
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_console.h"
#include <esp_err.h>
#include <esp_log.h>
#include <nvs_flash.h>
#include <esp_matter.h>
@@ -16,7 +20,7 @@
#include <common_macros.h>
#include <app_priv.h>
#include <app_reset.h>
#include "esp_console.h"
#include <helpers.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
@@ -33,15 +37,16 @@
#endif // CONFIG_OPENTHREAD_BORDER_ROUTER
static const char *TAG = "app_main";
uint16_t app_endpoint_id = 0;
// Semaphore is used to block esp_matter::start(), it will be unblock when we have
// valid device type input from user.
SemaphoreHandle_t semaphoreHandle = NULL;
using namespace esp_matter;
using namespace esp_matter::attribute;
using namespace esp_matter::cluster;
using namespace esp_matter::endpoint;
using namespace chip::app::Clusters;
@@ -148,8 +153,14 @@ static esp_err_t app_identification_cb(identification::callback_type_t type, uin
static esp_err_t app_attribute_update_cb(attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data)
{
esp_err_t err = ESP_OK;
// If user want to use driver, can be called from here.
return ESP_OK;
if (type == PRE_UPDATE) {
/* Driver update */
app_driver_handle_t driver_handle = (app_driver_handle_t)priv_data;
err = app_driver_attribute_update(driver_handle, endpoint_id, cluster_id, attribute_id, val);
}
return err;
}
extern "C" void app_main()
@@ -166,7 +177,7 @@ extern "C" void app_main()
ABORT_APP_ON_FAILURE(node != nullptr, ESP_LOGE(TAG, "Failed to create Matter node"));
uint8_t device_type_index;
if(esp_matter::nvs_helpers::get_device_type_from_nvs(&device_type_index) != ESP_OK) {
if (esp_matter::nvs_helpers::get_device_type_from_nvs(&device_type_index) != ESP_OK) {
semaphoreHandle = xSemaphoreCreateBinary();
ABORT_APP_ON_FAILURE(semaphoreHandle != nullptr, ESP_LOGE(TAG, "Failed to create semaphore"));
@@ -182,6 +193,10 @@ extern "C" void app_main()
esp_matter::data_model::create(device_type_index);
}
/* Initialize app driver, according to the device_type.
For now it's just for fan_control driver, Waiting for refinement*/
app_driver_init();
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
/* Set OpenThread platform config */
esp_openthread_platform_config_t config = {
@@ -195,6 +210,9 @@ extern "C" void app_main()
/* Matter start */
err = esp_matter::start(app_event_cb);
ABORT_APP_ON_FAILURE(err == ESP_OK, ESP_LOGE(TAG, "Failed to start Matter, err:%d", err));
if (err != ESP_OK) {
ESP_LOGE(TAG, "Matter start failed: %d", err);
}
#if CONFIG_ENABLE_CHIP_SHELL
esp_matter::console::diagnostics_register_commands();
+56 -6
View File
@@ -9,18 +9,58 @@
#pragma once
#include "sdkconfig.h"
#include <esp_err.h>
#include <esp_matter.h>
#include <app/clusters/fan-control-server/fan-control-delegate.h>
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include "esp_openthread_types.h"
#endif
#define LOW_MODE_PERCENT_MIN 1
#define LOW_MODE_PERCENT_MAX 33
#define MED_MODE_PERCENT_MIN 34
#define MED_MODE_PERCENT_MAX 66
#define HIGH_MODE_PERCENT_MIN 67
#define HIGH_MODE_PERCENT_MAX 100
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_NATIVE, \
typedef void *app_driver_handle_t;
typedef void *fan_driver_handle_t;
/** Driver Update
*
* This API should be called to update the driver for the attribute being updated.
* This is usually called from the common `app_attribute_update_cb()`.
*
* @param[in] driver_handle Handle to the driver.
* @param[in] endpoint_id Endpoint ID of the attribute.
* @param[in] cluster_id Cluster ID of the attribute.
* @param[in] attribute_id Attribute ID of the attribute.
* @param[in] val Pointer to `esp_matter_attr_val_t`. Use appropriate elements as per the value type.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t app_driver_attribute_update(app_driver_handle_t driver_handle, uint16_t endpoint_id, uint32_t cluster_id,
uint32_t attribute_id, esp_matter_attr_val_t *val);
/** Driver Initialize
*
* This API should be called to init driver(motor)
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t app_driver_init();
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \
{ \
.radio_mode = RADIO_MODE_NATIVE, \
}
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
{ \
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \
{ \
.host_connection_mode = HOST_CONNECTION_MODE_NONE, \
}
#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \
@@ -96,3 +136,13 @@
.storage_partition_name = "nvs", .netif_queue_size = 10, .task_queue_size = 10, \
}
#endif // CONFIG_OPENTHREAD_BORDER_ROUTER
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
class FanDelegateImpl:public chip::app::Clusters::FanControl::Delegate
{
public:
FanDelegateImpl(uint16_t aEndpoint):Delegate(aEndpoint){}
chip::Protocols::InteractionModel::Status HandleStep(chip::app::Clusters::FanControl::StepDirectionEnum aDirection, bool aWrap, bool aLowestOff);
};
#endif
@@ -0,0 +1,269 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdlib.h>
#include <string.h>
#include "math.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "fan_hal_bldc.h"
#include "iot_button.h"
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
#define PI 3.14159265f
motor_parameter_t motor_parameter;
void bldc_variable_init()
{
memset(&motor_parameter, 0x00, sizeof(motor_parameter));
motor_parameter.target_speed = 0; /*!< motor target speed */
motor_parameter.min_speed = 50; /*!< motor min speed */
motor_parameter.max_speed = DEFAULT_SPEED_MAX * DEFAULT_SPEED2MOTOR;
}
#define LIMIT(VALUE, MIN, MAX) \
((VALUE) < (MIN) ? (MIN) : ((VALUE) > (MAX) ? (MAX) : (VALUE)))
static bldc_control_handle_t bldc_control_handle = NULL;
static void hal_bldc_button_ctrl(void *arg, void *data)
{
motor_parameter.is_start = !motor_parameter.is_start;
}
static int hal_bldc_natural_speed(int min_speed, int max_speed, float noise_level, int t)
{
double k = (1 + sin(t * 2 * PI / 16)) / 2;
if (k >= noise_level) {
k = noise_level;
} else if (k <= 1 - noise_level) {
k = 1 - noise_level;
}
k = (k - (1 - noise_level)) / (noise_level - (1 - noise_level));
int speed = k * (max_speed - min_speed) + min_speed;
return speed;
}
static void hal_bldc_timer_cb(void *args)
{
static int t = 0;
static int min_speed = 300;
static int max_speed = DEFAULT_SPEED_MAX * DEFAULT_SPEED2MOTOR;
if (++t > 15) {
t = 0;
}
if (motor_parameter.is_start && motor_parameter.is_natural) {
motor_parameter.target_speed = hal_bldc_natural_speed(min_speed, max_speed - 200, 0.8, t);
bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
}
}
esp_err_t hal_bldc_button_ctrl_init(gpio_num_t pin)
{
button_config_t cfg = {
.type = BUTTON_TYPE_GPIO,
.gpio_button_config = {
.gpio_num = pin,
.active_level = 0,
},
};
button_handle_t btn = iot_button_create(&cfg);
if (iot_button_register_cb(btn, BUTTON_PRESS_DOWN, hal_bldc_button_ctrl, &btn) != ESP_OK) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t hal_bldc_init(dir_enum_t direction)
{
switch_config_t_t upper_switch_config = {
.control_type = CONTROL_TYPE_MCPWM,
.bldc_mcpwm = {
.group_id = 0,
.gpio_num = {CONFIG_UPPER_SWITCH_PHASE_U_GPIO, CONFIG_UPPER_SWITCH_PHASE_V_GPIO, CONFIG_UPPER_SWITCH_PHASE_W_GPIO},
},
};
switch_config_t_t lower_switch_config = {
.control_type = CONTROL_TYPE_GPIO,
.bldc_gpio[0] = {
.gpio_num = CONFIG_LOWER_SWITCH_PHASE_U_GPIO,
.gpio_mode = GPIO_MODE_OUTPUT,
},
.bldc_gpio[1] = {
.gpio_num = CONFIG_LOWER_SWITCH_PHASE_V_GPIO,
.gpio_mode = GPIO_MODE_OUTPUT,
},
.bldc_gpio[2] = {
.gpio_num = CONFIG_LOWER_SWITCH_PHASE_W_GPIO,
.gpio_mode = GPIO_MODE_OUTPUT,
},
};
bldc_zero_cross_comparer_config_t zero_cross_comparer_config = {
.comparer_gpio[0] = {
.gpio_num = CONFIG_ZERO_CROSS_COMPARER_PHASE_U_GPIO,
.gpio_mode = GPIO_MODE_INPUT,
.active_level = 0,
},
.comparer_gpio[1] = {
.gpio_num = CONFIG_ZERO_CROSS_COMPARER_PHASE_V_GPIO,
.gpio_mode = GPIO_MODE_INPUT,
.active_level = 0,
},
.comparer_gpio[2] = {
.gpio_num = CONFIG_ZERO_CROSS_COMPARER_PHASE_W_GPIO,
.gpio_mode = GPIO_MODE_INPUT,
.active_level = 0,
},
};
bldc_control_config_t config = {
.speed_mode = SPEED_CLOSED_LOOP,
.control_mode = BLDC_SIX_STEP,
.alignment_mode = ALIGNMENT_COMPARER,
.six_step_config = {
.lower_switch_active_level = 0,
.upper_switch_config = upper_switch_config,
.lower_switch_config = lower_switch_config,
.mos_en_config.has_enable = false,
},
.zero_cross_comparer_config = zero_cross_comparer_config,
};
if (bldc_control_init(&bldc_control_handle, &config) != ESP_OK) {
return ESP_FAIL;
}
if (bldc_control_set_dir(bldc_control_handle, direction) != ESP_OK) {
return ESP_FAIL;
}
if (hal_bldc_button_ctrl_init(CONFIG_POWER_BUTTON_GPIO) != ESP_OK) {
return ESP_FAIL;
}
const esp_timer_create_args_t periodic_timer_args = {
.callback = &hal_bldc_timer_cb,
.name = "periodic"
};
esp_timer_handle_t periodic_bldc_timer;
if (esp_timer_create(&periodic_timer_args, &periodic_bldc_timer) != ESP_OK) {
return ESP_FAIL;
}
if (esp_timer_start_periodic(periodic_bldc_timer, 1000 * 1000) != ESP_OK) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t hal_bldc_start_stop(uint8_t status)
{
if (status == 0) {
return bldc_control_stop(bldc_control_handle);
} else {
motor_parameter.is_start = 1;
return bldc_control_start(bldc_control_handle, motor_parameter.target_speed);
}
}
esp_err_t hal_bldc_set_fanmode(uint8_t status)
{
if (status == 0) {
motor_parameter.is_start = 0;
motor_parameter.target_speed = 0;
hal_bldc_start_stop(status);
} else if (status == 1) {
motor_parameter.target_speed = LOW_MODE_PERCENT * DEFAULT_SPEED2MOTOR;
motor_parameter.target_speed = LIMIT(motor_parameter.target_speed, motor_parameter.min_speed, motor_parameter.max_speed);
if (motor_parameter.is_start == 1) {
bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
} else {
hal_bldc_start_stop(status);
}
} else if (status == 2) {
motor_parameter.target_speed = MED_MODE_PERCENT * DEFAULT_SPEED2MOTOR;
motor_parameter.target_speed = LIMIT(motor_parameter.target_speed, motor_parameter.min_speed, motor_parameter.max_speed);
if (motor_parameter.is_start == 1) {
bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
} else {
hal_bldc_start_stop(status);
}
} else if (status == 3) {
motor_parameter.target_speed = HIGH_MODE_PERCENT * DEFAULT_SPEED2MOTOR;
motor_parameter.target_speed = LIMIT(motor_parameter.target_speed, motor_parameter.min_speed, motor_parameter.max_speed);
if (motor_parameter.is_start == 1) {
bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
} else {
hal_bldc_start_stop(status);
}
}
return ESP_OK;
}
esp_err_t hal_bldc_set_percent_speed(uint16_t percent)
{
percent = percent > 100 ? 0:percent;
motor_parameter.target_speed = (uint16_t)(percent * DEFAULT_SPEED_MAX * 0.01 * DEFAULT_SPEED2MOTOR);
motor_parameter.target_speed = LIMIT(motor_parameter.target_speed, motor_parameter.min_speed, motor_parameter.max_speed);
if (percent != 0) {
if (motor_parameter.is_start == 0) {
motor_parameter.is_start = 1;
bldc_control_start(bldc_control_handle, motor_parameter.target_speed);
} else {
bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
}
}
return ESP_OK;
}
esp_err_t hal_bldc_set_speed(uint16_t speed)
{
motor_parameter.target_speed = speed * DEFAULT_SPEED2MOTOR;
motor_parameter.target_speed = LIMIT(motor_parameter.target_speed, motor_parameter.min_speed, motor_parameter.max_speed);
return bldc_control_set_speed_rpm(bldc_control_handle, motor_parameter.target_speed);
}
esp_err_t hal_bldc_set_wind(uint8_t status)
{
if (status == 2) {
motor_parameter.is_natural = 1;
return ESP_OK;
} else {
motor_parameter.is_natural = 0;
return ESP_OK;
}
}
esp_err_t hal_bldc_set_airflow_direction(bool status)
{
if (status == 0) {
bldc_control_set_dir(bldc_control_handle, CW);
} else {
bldc_control_set_dir(bldc_control_handle, CCW);
}
return ESP_OK;
}
esp_err_t hal_bldc_status()
{
return motor_parameter.is_start;
}
esp_err_t hal_bldc_speed()
{
return motor_parameter.target_speed;
}
#endif
@@ -0,0 +1,144 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include "fan_hal_stepper_motor.h"
#include "fan_hal_bldc.h"
stepper_motor_t stepper_motor;
void hal_stepper_motor_ctrl(stepper_dir_t dir);
static void hal_stepper_motor_timer_cb(void *args)
{
static uint16_t step_count = 0;
if (stepper_motor.is_start) {
if (step_count++ == 30 * 100) {
stepper_motor.dir = !stepper_motor.dir;
step_count = 0;
}
hal_stepper_motor_ctrl(stepper_motor.dir);
}
}
esp_err_t hal_stepper_motor_init(gpio_num_t pin_1, gpio_num_t pin_2, gpio_num_t pin_3, gpio_num_t pin_4)
{
gpio_num_t pin[4] = {pin_1, pin_2, pin_3, pin_4};
gpio_config_t io_config = {
.pin_bit_mask = (1ULL << pin_1) | (1ULL << pin_2) | (1ULL << pin_3) | (1ULL << pin_4),
.mode = GPIO_MODE_OUTPUT,
.pull_down_en = 0,
.pull_up_en = 1,
.intr_type = GPIO_INTR_DISABLE,
};
memcpy(stepper_motor.pin, pin, sizeof(pin));
if (gpio_config(&io_config) != ESP_OK) {
return ESP_FAIL;
}
const esp_timer_create_args_t periodic_timer_args = {
.callback = &hal_stepper_motor_timer_cb,
.name = "periodic"
};
if (esp_timer_create(&periodic_timer_args, &stepper_motor.stepper_timer) != ESP_OK) {
return ESP_FAIL;
}
if (esp_timer_start_periodic(stepper_motor.stepper_timer, 10 * 1000) != ESP_OK) {
return ESP_FAIL;
}
stepper_motor.dir = STEP_CCW;
return ESP_OK;
}
esp_err_t hal_stepper_motor_set_rock(int status)
{
uint8_t bldc_status = hal_bldc_status();
if(status == 0) {
// close
stepper_motor.is_start = 0;
} else if ((status == 1 || status == 3 || status == 5 || status == 7) && bldc_status != 0) {
// RockLeftRight
stepper_motor.is_start = 1;
} else if ((status == 2 || status == 6) && bldc_status !=0) {
// UpDown
} else if (status == 4 && bldc_status !=0) {
// Round
}
return ESP_OK;
}
void hal_stepper_motor_ctrl(stepper_dir_t dir)
{
static uint8_t step = 0;
if (dir == STEP_CCW) {
if (++step == 8) {
step = 0;
}
} else if (dir == STEP_CW) {
if (step == 0) {
step = 8;
}
--step;
}
switch (step) {
case 0:
gpio_set_level(stepper_motor.pin[0], 1);
gpio_set_level(stepper_motor.pin[1], 0);
gpio_set_level(stepper_motor.pin[2], 0);
gpio_set_level(stepper_motor.pin[3], 1);
break;
case 1:
gpio_set_level(stepper_motor.pin[0], 0);
gpio_set_level(stepper_motor.pin[1], 0);
gpio_set_level(stepper_motor.pin[2], 0);
gpio_set_level(stepper_motor.pin[3], 1);
break;
case 2:
gpio_set_level(stepper_motor.pin[0], 0);
gpio_set_level(stepper_motor.pin[1], 0);
gpio_set_level(stepper_motor.pin[2], 1);
gpio_set_level(stepper_motor.pin[3], 1);
break;
case 3:
gpio_set_level(stepper_motor.pin[0], 0);
gpio_set_level(stepper_motor.pin[1], 0);
gpio_set_level(stepper_motor.pin[2], 1);
gpio_set_level(stepper_motor.pin[3], 0);
break;
case 4:
gpio_set_level(stepper_motor.pin[0], 0);
gpio_set_level(stepper_motor.pin[1], 1);
gpio_set_level(stepper_motor.pin[2], 1);
gpio_set_level(stepper_motor.pin[3], 0);
break;
case 5:
gpio_set_level(stepper_motor.pin[0], 0);
gpio_set_level(stepper_motor.pin[1], 1);
gpio_set_level(stepper_motor.pin[2], 0);
gpio_set_level(stepper_motor.pin[3], 0);
break;
case 6:
gpio_set_level(stepper_motor.pin[0], 1);
gpio_set_level(stepper_motor.pin[1], 1);
gpio_set_level(stepper_motor.pin[2], 0);
gpio_set_level(stepper_motor.pin[3], 0);
break;
case 7:
gpio_set_level(stepper_motor.pin[0], 1);
gpio_set_level(stepper_motor.pin[1], 0);
gpio_set_level(stepper_motor.pin[2], 0);
gpio_set_level(stepper_motor.pin[3], 0);
break;
default:
break;
}
}
@@ -0,0 +1,146 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define BLDC_LEDC 0
#define BLDC_MCPWM 1
/**
* @brief Configure the generation of PWM.
*
*/
#define PWM_MODE (BLDC_MCPWM) /*!< Configure the generation of PWM. */
/**
* @brief MCPWM Settings
*
*/
#define MCPWM_CLK_SRC (40 * 1000 * 1000) /*!< Number of count ticks within a period time_us = 1,000,000 / MCPWM_CLK_SRC */
#define MCPWM_PERIOD (2000) /*!< pwm_cycle_us = 1,000,000 / MCPWM_CLK_SRC * MCPWM_PERIOD */
/**
* @brief LEDC Settings
*
*/
#define FREQ_HZ (20*1000) /*<! Frequency in Hertz */
#define DUTY_RES (11) /*!< Set duty resolution to 11 bits */
/**
* @brief No changes should be made here.
*
*/
#if PWM_MODE
#define ALARM_COUNT_US (1000 * 1000 * MCPWM_PERIOD / MCPWM_CLK_SRC)
#define DUTY_MAX (MCPWM_PERIOD/2)
#else
#define ALARM_COUNT_US ( 1000*1000 / FREQ_HZ)
#define DUTY_MAX ((1 << DUTY_RES) - 1)
#endif
#define PWM_DUTYCYCLE_05 (DUTY_MAX/20)
#define PWM_DUTYCYCLE_10 (DUTY_MAX/10)
#define PWM_DUTYCYCLE_15 (DUTY_MAX*3/20)
#define PWM_DUTYCYCLE_20 (DUTY_MAX/5)
#define PWM_DUTYCYCLE_25 (DUTY_MAX*5/20)
#define PWM_DUTYCYCLE_30 (DUTY_MAX*3/10)
#define PWM_DUTYCYCLE_40 (DUTY_MAX*2/5)
#define PWM_DUTYCYCLE_50 (DUTY_MAX/2)
#define PWM_DUTYCYCLE_60 (DUTY_MAX*3/5)
#define PWM_DUTYCYCLE_80 (DUTY_MAX*4/5)
#define PWM_DUTYCYCLE_90 (DUTY_MAX*9/10)
#define PWM_DUTYCYCLE_100 (DUTY_MAX)
/**
* @brief Pulse injection-related parameters.
* @note Used to detect the initial phase of the motor; MCPWM peripheral support is necessary.
*/
#if PWM_MODE
#define INJECT_ENABLE (0) /*!< Whether to enable pulse injection. */
#endif
#define INJECT_DUTY (PWM_DUTYCYCLE_90) /*!< Injected torque. */
#define CHARGE_TIME (5) /*!< Capacitor charging and injection time. */
/**
* @brief Parameters related to motor alignment.
* Used to lock the motor in a specific phase
* before strong dragging.
*/
#define ALIGNMENTNMS (300) /*!< Duration of alignment, too short may not reach the position, too long may cause the motor to overheat. */
#define ALIGNMENTDUTY (PWM_DUTYCYCLE_20) /*!< alignment torque. */
/**
* @brief Setting parameters for strong dragging. The principle of
* strong dragging is to increase the control frequency and intensity
* @note If the control cycle speeds up, corresponding reductions
* should be made to the RAMP_TIM_STA, RAMP_TIM_END, RAMP_TIM_STEP
*/
#define RAMP_TIM_STA (900) /*!< The start step time for climbing. A smaller value results in faster startup but may lead to overcurrent issues. */
#define RAMP_TIM_END (180) /*!< The end step time for climbing, adjusted based on the load. If loaded, this value should be relatively larger. */
#define RAMP_TIM_STEP (15) /*!< Decremental increment for climbing step time—adjusted in accordance with RAMP_TIM_STA. */
#define RAMP_DUTY_STA (PWM_DUTYCYCLE_20) /*!< The starting torque for climbing. */
#define RAMP_DUTY_END (PWM_DUTYCYCLE_40) /*!< The ending torque for climbing. */
#define RAMP_DUTY_INC (13) /*!< The incremental torque step for climbing—too small a value may result in failure to start, while too large a value may lead to overcurrent issues. */
/**
* @brief ADC parameters for zero-crossing detection; please do not delete if not in use.
*
*/
#define ENTER_CLOSE_TIME (10000) /*!< Enter the closed-loop state delay times. */
#define ZERO_REPEAT_TIME (2) /*!< Change phase after detecting zero-crossing signals continuously for several times. */
#define AVOID_CONTINUE_CURRENT_TIME (4) /*!< Avoiding Continuous Current */
/**
* @brief Comparator parameters for zero-crossing detection; please do not delete if not in use.
*
*/
#define ZERO_STABLE_FLAG_CNT (4) /*!< After stable detection for multiple revolutions, it is considered to enter a sensorless state. */
#define ZERO_CROSS_DETECTION_ACCURACY 0xFFFF /*!< Count a valid comparator value every consecutive detection for how many times. */
/**
* @brief Common parameter for compensated commutation time calculation
*
*/
#define ZERO_CROSS_ADVANCE (10) /*!< Advance switching at zero-crossing, switching angle = 180°/ZERO_CROSS_ADVANCE. angle compensation should be provided. >= 6 */
/**
* @brief Motor parameter settings.
*
*/
#define POLE_PAIR (5) /*!< Number of pole pairs in the motor. */
#define BASE_VOLTAGE (12) /*!< Rated voltage. */
#define BASE_SPEED (1000) /*!< Rated speed unit: rpm. */
/**
* @brief Closed-loop PID parameters for speed.
*
*/
#define SPEED_KP (0.003) /*!< P */
#define SPEED_KI (0.0001) /*!< I */
#define SPEED_KD (0) /*!< D */
#define SPEED_MIN_INTEGRAL (- DUTY_MAX/SPEED_KI) /*!< Minimum integral saturation limit. */
#define SPEED_MAX_INTEGRAL (DUTY_MAX/SPEED_KI) /*!< Maximum integral saturation limit. */
#define SPEED_MIN_OUTPUT (PWM_DUTYCYCLE_20) /*!< Minimum PWM duty cycle output. */
#define SPEED_MAX_OUTPUT (DUTY_MAX) /*!< Maximum PWM duty cycle output. */
#define SPEED_CAL_TYPE (0) /*!< 0 Incremental 1 Positional */
/**
* @brief Speed parameter settings.
*
*/
#define SPEED_MAX_RPM 1000 /*!< Maximum speed. */
#define SPEED_MIN_RPM 0 /*!< Minimum speed. */
#define MAX_SPEED_MEASUREMENT_FACTOR 1.2 /*!< Supports a measured speed range from 0 to 1.2 times SpeedMAX. Large values could prevent proper filtering of incorrect data. */
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,120 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#include "bldc_control.h"
#ifdef __cplusplus
extern "C" {
#endif
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_SPEED_MAX 100
#define DEFAULT_SPEED2MOTOR 10
#define LOW_MODE_PERCENT 33
#define MED_MODE_PERCENT 66
#define HIGH_MODE_PERCENT 100
typedef struct {
uint8_t is_start; /*!< motor status 0:off 1:start */
uint8_t is_natural; /*!< motor natural wind 0: off 1: start */
uint16_t target_speed; /*!< motor target speed */
uint16_t min_speed; /*!< motor min speed */
uint16_t max_speed; /*!< motor max speed */
} motor_parameter_t;
/**
* @brief variable init
*
*/
void bldc_variable_init();
/**
* @brief bldc init
*
* @param direction
* @return esp_err_t
*/
esp_err_t hal_bldc_init(dir_enum_t direction);
/**
* @brief set bldc start or stop
*
* @param status
* @return esp_err_t
*/
esp_err_t hal_bldc_start_stop(uint8_t status);
/**
* @brief set bldc fan mode
*
* @param status
* @return esp_err_t
*/
esp_err_t hal_bldc_set_fanmode(uint8_t status);
/**
* @brief set bldc speed through percent
*
* @param speed
* @return esp_err_t
*/
esp_err_t hal_bldc_set_percent_speed(uint16_t speed);
/**
* @brief set bldc wind mode
*
* @param status
* @return esp_err_t
*/
esp_err_t hal_bldc_set_wind(uint8_t status);
/**
* @brief set bldc step
*
* @param status, aWrap, aLowestOff
* @return esp_err_t
*/
esp_err_t hal_bldc_set_step(uint8_t status,bool aWrap,bool aLowestOff);
/**
* @brief set bldc direction
*
* @param status
* @return esp_err_t
*/
esp_err_t hal_bldc_set_airflow_direction(bool status);
/**
* @brief set bldc speed
*
* @param speed
* @return esp_err_t
*/
esp_err_t hal_bldc_set_speed(uint16_t speed);
/**
* @brief read and return bldc motor status
*
* @return esp_err_t
*/
esp_err_t hal_bldc_status();
/**
* @brief read and return bldc motor speed
*
* @return esp_err_t
*/
esp_err_t hal_bldc_speed();
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,52 @@
/*
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#pragma once
#include "driver/gpio.h"
#include "esp_timer.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
STEP_CW = 0,
STEP_CCW,
} stepper_dir_t;
typedef struct {
uint8_t is_start;
gpio_num_t pin[4];
stepper_dir_t dir;
esp_timer_handle_t stepper_timer;
} stepper_motor_t;
extern stepper_motor_t stepper_motor;
/**
* @brief stepper init
*
* @param pin_1
* @param pin_2
* @param pin_3
* @param pin_4
* @return esp_err_t
*/
esp_err_t hal_stepper_motor_init(gpio_num_t pin_1, gpio_num_t pin_2, gpio_num_t pin_3, gpio_num_t pin_4);
/**
* @brief set stepper motor status
*
* @return esp_err_t
*/
esp_err_t hal_stepper_motor_set_rock(int status);
#ifdef __cplusplus
}
#endif
@@ -6,38 +6,51 @@
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_check.h>
#include <esp_log.h>
#include <esp_matter.h>
#include <string.h>
#include "esp_check.h"
#include "esp_log.h"
#include "esp_matter.h"
#include "esp_console.h"
#include "esp_vfs_dev.h"
#include "linenoise/linenoise.h"
#include "argtable3/argtable3.h"
#include "esp_vfs_fat.h"
#include "driver/usb_serial_jtag.h"
#include "esp_vfs_usb_serial_jtag.h"
#include "hal/uart_types.h"
#include "driver/uart.h"
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
#include "esp_vfs_usb_serial_jtag.h"
#include "driver/usb_serial_jtag.h"
#endif // CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
#include <app_priv.h>
#include <helpers.h>
#include <device_types.h>
#include <string.h>
#include <app/clusters/fan-control-server/fan-control-delegate.h>
#include <app/clusters/fan-control-server/fan-control-server.h>
using namespace esp_matter;
extern uint16_t app_endpoint_id;
static const char *TAG = "esp_matter_console_helpers";
extern SemaphoreHandle_t semaphoreHandle;
#define PROMPT_STR CONFIG_IDF_TARGET
#define SPEED_MAX_SET 100
#define ROCK_SET 0
#define ROCK_SUPPORT_SET 7
#define AIRFLOW_DIRECTION_SET 0
#define WIND_SET 0
#define WIND_SUPPORT_SET 7
#if CONFIG_STORE_HISTORY
#define MOUNT_PATH "/data"
#define HISTORY_PATH MOUNT_PATH "/history.txt"
static void initialize_filesystem(void)
{
static wl_handle_t wl_handle;
@@ -205,7 +218,34 @@ int create(uint8_t device_type_index)
}
case ESP_MATTER_FAN: {
esp_matter::endpoint::fan::config_t fan_config;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
static FanDelegateImpl fan_delegate(app_endpoint_id);
fan_config.fan_control.delegate = &fan_delegate;
#endif
endpoint = esp_matter::endpoint::fan::create(node, &fan_config, ENDPOINT_FLAG_NONE, NULL);
cluster_t *cluster = cluster::get(endpoint, chip::app::Clusters::FanControl::Id);
cluster::fan_control::feature::multi_speed::config_t multispeed_config;
cluster::fan_control::feature::rocking::config_t rock_config;
cluster::fan_control::feature::airflow_direction::config_t airflow_direction_config;
cluster::fan_control::feature::wind::config_t wind_config;
multispeed_config.speed_max = SPEED_MAX_SET;
cluster::fan_control::feature::multi_speed::add(cluster, &multispeed_config);
rock_config.rock_setting = ROCK_SET;
rock_config.rock_support = ROCK_SUPPORT_SET;
cluster::fan_control::feature::rocking::add(cluster, &rock_config);
airflow_direction_config.airflow_direction = AIRFLOW_DIRECTION_SET;
cluster::fan_control::feature::airflow_direction::add(cluster, &airflow_direction_config);
wind_config.wind_setting = WIND_SET;
wind_config.wind_support = WIND_SUPPORT_SET;
cluster::fan_control::feature::wind::add(cluster, &wind_config);
cluster::fan_control::feature::step::add(cluster);
app_endpoint_id = endpoint::get_id(endpoint);
break;
}
case ESP_MATTER_THERMOSTAT: {
@@ -4,4 +4,7 @@ dependencies:
rules: # will add "optional_component" only when all if clauses are True
- if: "idf_version >=5.0"
- if: "target in [esp32c2]"
espressif/esp_sensorless_bldc_control:
version: "==0.2.0"
rules: # will add "optional_component" only when all if clauses are True
- if: "target in [esp32, esp32s3]"