Skip to content

Commit

Permalink
add power management and button fuction
Browse files Browse the repository at this point in the history
  • Loading branch information
lisir233 committed Sep 3, 2023
1 parent db6dbf8 commit 9f98ce6
Show file tree
Hide file tree
Showing 6 changed files with 2,135 additions and 57 deletions.
7 changes: 1 addition & 6 deletions components/app_wifi/app_wifi_with_homekit.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,9 @@ void app_wifi_with_homekit_init(void)
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &event_handler, NULL));

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config;
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
wifi_config.sta.listen_interval = 4;
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
}

static void app_wifi_prov_stop(void *priv)
Expand Down
236 changes: 191 additions & 45 deletions main/app_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
#include "freertos/task.h"

#include "pwm_servo.h"
#include "esp_adc/adc_oneshot.h"
#include "esp_pm.h"
#include "esp_sleep.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include <esp_rmaker_utils.h>
static const char *TAG = "app_driver";
/* This is the button that is used for toggling the power */
#define BUTTON_GPIO CONFIG_EXAMPLE_BOARD_BUTTON_GPIO
Expand All @@ -38,10 +44,25 @@ static bool g_power_state = DEFAULT_POWER;
#define SERVO_POWER_GPIO 6
#define DEFAULT_PWM_SERVO_STATE false
#define DEFAULT_SERVO_POWER_STATE false
#define SERVO_EXECUTION_TIME 150 //ms
#define SERVO_EXECUTION_TIME 100 //ms
static bool g_pwm_servo_state = DEFAULT_PWM_SERVO_STATE;
static TaskHandle_t servo_task_handle = NULL;

#define BATTERY_ADC_CHANNEL ADC_CHANNEL_3
#define BATTERY_ADC_ATTEN ADC_ATTEN_DB_11
#define BATTERY_ATTEN 0.5f //V_bat = V_io / BATTERY_ATTEN

#define BATTERY_WARNING_VLOT 3.6f //V_bat = V_io / BATTERY_ATTEN
#define BATTERY_SHUTDOWN_VLOT 3.4f //V_bat = V_io / BATTERY_ATTEN

static esp_timer_handle_t button1_timer = NULL;
static gpio_int_type_t button1_intr_type = GPIO_INTR_HIGH_LEVEL;
#define BUTTON_DELAY_MIN_CONFIG 100000
#define BUTTON_DELAY_MAX_CONFIG 3000000
#define QCLOUD_NETWORK_CONFIG 5000000

#define REBOOT_DELAY 2
#define RESET_DELAY 2
typedef enum
{
SERVO_EXECUTION_OFF = 0,
Expand Down Expand Up @@ -74,44 +95,58 @@ void app_servo_click(void)
{
xTaskNotify(servo_task_handle, (uint32_t)SERVO_EXECUTION_CLICK,eSetValueWithoutOverwrite);
}
static void servo_task(void* pvParameters){
static void servo_task(void* pvParameters)
{
static servo_execution_t servo_execution = SERVO_EXECUTION_OFF;
while(1){
if(xTaskNotifyWait(0,0,(uint32_t *)&servo_execution,portMAX_DELAY) == pdTRUE){
if(servo_execution == SERVO_EXECUTION_OFF){
ESP_LOGI(TAG, "SERVO_EXECUTION_OFF");
gpio_set_level(SERVO_POWER_GPIO, 1);
g_pwm_servo_state = false;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_set_level(SERVO_POWER_GPIO, 0);
}else if(servo_execution == SERVO_EXECUTION_ON){
ESP_LOGI(TAG, "SERVO_EXECUTION_ON");
gpio_set_level(SERVO_POWER_GPIO, 1);
g_pwm_servo_state = true;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_set_level(SERVO_POWER_GPIO, 0);

}else if(servo_execution == SERVO_EXECUTION_TOGGLE){
ESP_LOGI(TAG, "SERVO_EXECUTION_TOGGLE");
gpio_set_level(SERVO_POWER_GPIO, 1);
g_pwm_servo_state = !g_pwm_servo_state;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_set_level(SERVO_POWER_GPIO, 0);
}else if(servo_execution == SERVO_EXECUTION_CLICK){
ESP_LOGI(TAG, "SERVO_EXECUTION_CLICK");
gpio_set_level(SERVO_POWER_GPIO, 1);
g_pwm_servo_state = true;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
g_pwm_servo_state = false;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_set_level(SERVO_POWER_GPIO, 0);
}
esp_pm_lock_handle_t servo_task_pm_lock;
esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "servo", &servo_task_pm_lock);

while(xTaskNotifyWait(0,0,(uint32_t *)&servo_execution,portMAX_DELAY) == pdTRUE){
if(servo_execution == SERVO_EXECUTION_OFF){
ESP_LOGI(TAG, "SERVO_EXECUTION_OFF");
esp_pm_lock_acquire(servo_task_pm_lock);
gpio_set_level(SERVO_POWER_GPIO, 1);
gpio_hold_en(SERVO_POWER_GPIO);
g_pwm_servo_state = false;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_hold_dis(SERVO_POWER_GPIO);
gpio_set_level(SERVO_POWER_GPIO, 0);
esp_pm_lock_release(servo_task_pm_lock);
}else if(servo_execution == SERVO_EXECUTION_ON){
ESP_LOGI(TAG, "SERVO_EXECUTION_ON");
esp_pm_lock_acquire(servo_task_pm_lock);
gpio_set_level(SERVO_POWER_GPIO, 1);
gpio_hold_en(SERVO_POWER_GPIO);
g_pwm_servo_state = true;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_hold_dis(SERVO_POWER_GPIO);
gpio_set_level(SERVO_POWER_GPIO, 0);
esp_pm_lock_release(servo_task_pm_lock);
}else if(servo_execution == SERVO_EXECUTION_TOGGLE){
ESP_LOGI(TAG, "SERVO_EXECUTION_TOGGLE");
gpio_set_level(SERVO_POWER_GPIO, 1);
gpio_hold_en(SERVO_POWER_GPIO);
g_pwm_servo_state = !g_pwm_servo_state;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_hold_dis(SERVO_POWER_GPIO);
gpio_set_level(SERVO_POWER_GPIO, 0);
}else if(servo_execution == SERVO_EXECUTION_CLICK){
ESP_LOGI(TAG, "SERVO_EXECUTION_CLICK");
gpio_set_level(SERVO_POWER_GPIO, 1);
gpio_hold_en(SERVO_POWER_GPIO);
g_pwm_servo_state = true;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
g_pwm_servo_state = false;
pwm_servo_set(g_pwm_servo_state);
vTaskDelay(SERVO_EXECUTION_TIME/portTICK_PERIOD_MS);
gpio_hold_dis(SERVO_POWER_GPIO);
gpio_set_level(SERVO_POWER_GPIO, 0);
}

}

}
Expand Down Expand Up @@ -152,16 +187,125 @@ static void set_power_state(bool target)
gpio_set_level(OUTPUT_GPIO, target);
app_indicator_set(target);
}
static void battery_monitor_task(void* pvParameters)
{

void app_driver_init()
adc_oneshot_unit_handle_t adc1_handle;
adc_oneshot_unit_init_cfg_t init_config1 = {
.unit_id = ADC_UNIT_1,
};
ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));
//-------------ADC1 Config---------------//
adc_oneshot_chan_cfg_t config = {
.bitwidth = ADC_BITWIDTH_DEFAULT,
.atten = BATTERY_ADC_ATTEN,
};
ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, BATTERY_ADC_CHANNEL, &config));
int adc_raw;
float battery_voltage;
while(1){
vTaskDelay(10*60*1000/portTICK_PERIOD_MS);
ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle, BATTERY_ADC_CHANNEL, &adc_raw));
battery_voltage = adc_raw * 3.0f / 4095 / BATTERY_ATTEN;
//printf("Battery Voltage %f\r\n",battery_voltage);
if(battery_voltage < BATTERY_SHUTDOWN_VLOT ){
gpio_hold_dis(BOARD_POWER_IO);
gpio_set_level(BOARD_POWER_IO, 0);
}
else if(battery_voltage < BATTERY_WARNING_VLOT){
gpio_set_level(BOARD_LED_IO, 1);
gpio_hold_en(BOARD_LED_IO);
vTaskDelay(3000/portTICK_PERIOD_MS);
gpio_set_level(BOARD_LED_IO, 1);
gpio_hold_dis(BOARD_LED_IO);
}
else{
gpio_set_level(BOARD_POWER_IO, 1);
gpio_hold_en(BOARD_POWER_IO);
}
}
}
static void app_driver_button_long_press_callback(void* arg)
{
button_handle_t btn_handle = iot_button_create(BUTTON_GPIO, BUTTON_ACTIVE_LEVEL);
if (btn_handle) {
/* Register a callback for a button tap (short press) event */
iot_button_set_evt_cb(btn_handle, BUTTON_CB_TAP, push_btn_cb, NULL);
/* Register Wi-Fi reset and factory reset functionality on same button */
app_reset_button_register(btn_handle, WIFI_RESET_BUTTON_TIMEOUT, FACTORY_RESET_BUTTON_TIMEOUT);
esp_rmaker_factory_reset(RESET_DELAY, REBOOT_DELAY);
}
static void app_driver_button_click_callback(void* arg)
{
push_btn_cb(NULL);
}
void IRAM_ATTR app_driver_button_isr(void *arg)
{
static int64_t button_delay_time = -BUTTON_DELAY_MAX_CONFIG;
if(button1_intr_type == GPIO_INTR_LOW_LEVEL){
button1_intr_type = GPIO_INTR_HIGH_LEVEL;
gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_HIGH_LEVEL);
esp_timer_start_once(button1_timer, QCLOUD_NETWORK_CONFIG);
button_delay_time = esp_timer_get_time();
}else if (button1_intr_type == GPIO_INTR_HIGH_LEVEL) {
esp_timer_stop(button1_timer);
if(esp_timer_get_time() > button_delay_time + BUTTON_DELAY_MIN_CONFIG &&
esp_timer_get_time() < button_delay_time + BUTTON_DELAY_MAX_CONFIG ){
app_driver_button_click_callback(NULL);
button_delay_time = esp_timer_get_time();
}else{
button_delay_time = esp_timer_get_time();
}
button1_intr_type = GPIO_INTR_LOW_LEVEL;
gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_LOW_LEVEL);
}else {
button1_intr_type = GPIO_INTR_HIGH_LEVEL;
gpio_set_intr_type(BUTTON_GPIO, GPIO_INTR_HIGH_LEVEL);
}
}

esp_err_t app_driver_button_config(gpio_num_t gpio_num)
{
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << gpio_num);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = true;
return gpio_config(&io_conf);
}


esp_err_t app_driver_button_init(void)
{
esp_err_t ret = ESP_FAIL;

const esp_timer_create_args_t button_long_timer_args = {
.callback = &app_driver_button_long_press_callback,
.name = "button_long"
};
esp_timer_create(&button_long_timer_args, &button1_timer);

ret = app_driver_button_config(BUTTON_GPIO);

if(gpio_get_level(BUTTON_GPIO) == 0){
button1_intr_type = GPIO_INTR_NEGEDGE;
}

ret = gpio_hold_en(BUTTON_GPIO);

ret = gpio_install_isr_service(0);

ret = gpio_isr_handler_add(BUTTON_GPIO, app_driver_button_isr, (void *)BUTTON_GPIO);
ret = gpio_wakeup_enable(BUTTON_GPIO, GPIO_INTR_LOW_LEVEL);
ret = esp_sleep_enable_gpio_wakeup();
return ret;
}

void app_driver_init()
{
// button_handle_t btn_handle = iot_button_create(BUTTON_GPIO, BUTTON_ACTIVE_LEVEL);
// if (btn_handle) {
// /* Register a callback for a button tap (short press) event */
// iot_button_set_evt_cb(btn_handle, BUTTON_CB_TAP, push_btn_cb, NULL);
// /* Register Wi-Fi reset and factory reset functionality on same button */
// app_reset_button_register(btn_handle, WIFI_RESET_BUTTON_TIMEOUT, FACTORY_RESET_BUTTON_TIMEOUT);
// }
app_driver_button_init();

/* Configure power */
gpio_config_t io_conf = {
Expand All @@ -186,6 +330,8 @@ void app_driver_init()
gpio_set_level(BOARD_LED_IO, 1);
app_indicator_init();
app_servo_init();
xTaskCreate(battery_monitor_task, "battery_monitor_task", 2048, NULL, 12, NULL);

}

int IRAM_ATTR app_driver_set_state(bool state)
Expand All @@ -194,7 +340,7 @@ int IRAM_ATTR app_driver_set_state(bool state)
g_power_state = state;
set_power_state(g_power_state);
}
app_servo_click();
app_servo_set_state(state);
return ESP_OK;
}

Expand Down
16 changes: 13 additions & 3 deletions main/app_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "app_wifi_with_homekit.h"
#include "app_priv.h"
#include "esp_pm.h"
#include <esp_wifi.h>
static const char *TAG = "app_main";
esp_rmaker_device_t *switch_device;

Expand Down Expand Up @@ -155,15 +156,16 @@ void app_main()
err = nvs_flash_init();
}
ESP_ERROR_CHECK( err );

#if CONFIG_PM_ENABLE
// Configure dynamic frequency scaling:
// maximum and minimum frequencies are set in sdkconfig,
// automatic light sleep is enabled if tickless idle support is enabled.
esp_pm_config_esp32c3_t pm_config = {
.max_freq_mhz = 160,
.min_freq_mhz = 40,
.min_freq_mhz = 80,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
.light_sleep_enable = true
.light_sleep_enable = true,
#endif
};
ESP_ERROR_CHECK( esp_pm_configure(&pm_config) );
Expand All @@ -173,6 +175,14 @@ void app_main()
*/
app_wifi_with_homekit_init();

wifi_config_t wifi_config;
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
if(strcmp((char *)wifi_config.sta.ssid,"") != 0){
wifi_config.sta.listen_interval = 4;
err = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
printf("WIFI_PS_MAX_MODEM set!\n");
}
/* Register an event handler to catch RainMaker events */
ESP_ERROR_CHECK(esp_event_handler_register(RMAKER_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
Expand Down Expand Up @@ -244,5 +254,5 @@ void app_main()
ESP_LOGE(TAG, "Could not start Wifi. Aborting!!!");
vTaskDelay(5000/portTICK_PERIOD_MS);
abort();
}
}
}
6 changes: 3 additions & 3 deletions main/pwm_servo.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
#define PWM_SERVO_IO (4) // Define the output GPIO
#define PWM_SERVO_LEDC_CHANNEL LEDC_CHANNEL_0
#define PWM_SERVO_LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define PWM_SERVO_LEDC_DUTY_OFF (410) // Set duty to 5%. ((2 ** 13) - 1) * 5% = 410
#define PWM_SERVO_LEDC_DUTY_ON (2078) // Set duty to 25%. ((2 ** 13) - 1) * 50% = 2048
#define PWM_SERVO_LEDC_DUTY_OFF (520) // Set duty to 5%. ((2 ** 13) - 1) * 5% = 410 //1.5ms 614
#define PWM_SERVO_LEDC_DUTY_ON (820) // Set duty to 25%. ((2 ** 13) - 1) * 20% = 2048 //
#define PWM_SERVO_LEDC_FREQUENCY (100) // Frequency in Hertz. Set frequency at 100 Hz

void pwm_servo_init(void)
Expand All @@ -19,7 +19,7 @@ void pwm_servo_init(void)
.timer_num = PWM_SERVO_LEDC_TIMER,
.duty_resolution = PWM_SERVO_LEDC_DUTY_RES,
.freq_hz = PWM_SERVO_LEDC_FREQUENCY, // Set output frequency at 5 kHz
.clk_cfg = LEDC_AUTO_CLK
.clk_cfg = LEDC_USE_RTC8M_CLK
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

Expand Down
22 changes: 22 additions & 0 deletions sdkconfig.defaults.esp32c3
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#Enable Power Management
CONFIG_PM_ENABLE=y
CONFIG_PM_DFS_INIT_AUTO=y
CONFIG_PM_SLP_DISABLE_GPIO=y

CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=3


CONFIG_ESP_PHY_MAC_BB_PD=y


CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y
CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS=y


CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y

CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=17
CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=60
CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y
Loading

0 comments on commit 9f98ce6

Please sign in to comment.