mirror of
https://github.com/espressif/esp-matter.git
synced 2026-04-27 19:13:13 +00:00
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:
@@ -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();
|
||||
|
||||
@@ -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]"
|
||||
|
||||
Reference in New Issue
Block a user