#include "user_sleep.h" #include #include #include #include #include #include #include "sdkconfig.h" #include "soc/soc_caps.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_sleep.h" #include "esp_log.h" #include "driver/rtc_io.h" #include "soc/rtc.h" #include "nvs_flash.h" #include "nvs.h" #include "EPD.h" #include "FONT_LIB.h" #include "esp_timer.h" #include "freertos/timers.h" #include "SPIFFS.h" #include "ulp_main.h" #include "LORA.h" // 定时器选择 #define TIMER_CHOICE 1 // 0:ESP //1 FREERTOS #if TIMER_CHOICE TimerHandle_t sleep_timer; // 进入休眠定时器 TimerHandle_t already_send_timer; // 可以发送数据的定时器 #else esp_timer_handle_t sleep_timer; // 开启睡眠定时器 esp_timer_handle_t already_send_timer; // 可以发送数据的定时器 #endif static RTC_DATA_ATTR struct timeval sleep_enter_time; RTC_DATA_ATTR uint8_t _wakeup_reson = 0; // 内存上次唤醒的原因 int64_t sleep_before_us = 0; // 开始进入睡眠时间 int64_t sleep_afterr_us = 0; // 唤醒时间 #define DEEP_SLEEP 0 #if !DEEP_SLEEP #include #include #include #include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/uart.h" #include "esp_sleep.h" #include "esp_log.h" #include "esp_timer.h" #include "esp_log.h" static const char *LOG_TAG = "user_sleep"; extern QueueHandle_t sleep_queue; extern QueueHandle_t wakeup_queue; extern void light_sleep_task(void *args); extern void wakeup_sleep_task(void *args); bool is_sleep = false; extern void set_screen_dis_info_and_send_queue(bool is_into_sleep, bool is_left, bool is_change_power, bool is_dont_dis, bool sleep_ms); /********************************************************************************* * function : sleep_timer_callback * Description : 进入睡眠回调函数 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void sleep_timer_callback(void *arg) { #if 0 send_sleep_Queue(); #else // printf("fall into sleep\r\n"); #include "ulp_riscv.h" #include "esp_sleep.h" #include "driver/uart.h" // printf("error =%d\r\n",err); sleep_before_us = esp_timer_get_time(); uart_wait_tx_idle_polling(0); // ulp_riscv_timer_resume(); is_sleep = true; // #if LORA_SLEEP_ENABLE // //rtc_gpio_hold_dis(LORA_POWER_PIN); // lora_set_power_level(0); // //rtc_gpio_hold_en(LORA_POWER_PIN); // #endif // esp_light_sleep_start(); #endif } /********************************************************************************* * function : sleep_timer_start * Description : 倒计时开始进入睡眠 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void sleep_timer_start(int ms) { #if TIMER_CHOICE xTimerStop(sleep_timer, 0); // 停止定时器 // 在这里可以改变定时器的超时时间 // 第一个参数是定时器句柄,第二个参数是新的超时时间(以时钟节拍为单位) xTimerChangePeriod(sleep_timer, pdMS_TO_TICKS(ms), 0); xTimerStart(sleep_timer, 0); // 开始定时器 // xTimerStart(sleep_Timerout, 0); ESP_LOGI(LOG_TAG, "#############%s##############reset sleep_timer [%d]", is_sleep ? "true" : "false", ms); #else #if 0 ESP_ERROR_CHECK(esp_timer_start_once(sleep_timer, ms*1000));//500ms #else esp_timer_start_once(sleep_timer, ms * 1000); // 500ms #endif #endif } /********************************************************************************* * function : sleep_timer_stop * Description : 停止进入睡眠 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void sleep_timer_stop(void) { #if TIMER_CHOICE xTimerStop(sleep_timer, 0); // 停止定时器 #else #if 0 ESP_ERROR_CHECK(esp_timer_stop(sleep_timer)); #else esp_timer_stop(sleep_timer); #endif #endif } // /********************************************************************************* * function : Already_send_timer_callback * Description : 定到达指定时间准备发送数据或者接收数据 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void Already_send_timer_callback(void *arg) { #if TIMER_CHOICE // printf("Already_send_timer_callback\r\n"); extern void send_can_I_receive(); if (Machine_info.eflagID != 0xff) { send_can_I_receive(); // 发送可以接受的命令 if (Send_list != NULL) { vTaskDelay(50 / portTICK_PERIOD_MS); lora_send_data((char *)Send_list->data, Send_list->len); printf("->send one data to gateway\r\n"); } else { printf("list not have data\r\n"); } } // uart_wait_tx_idle_polling(UART_NUM_1); // example_register_timer_wakeup(); // esp_sleep_enable_timer_wakeup(TIMER_WAKEUP_TIME_US*Machine_info.eflagID); //配置当前休眠的唤醒时间 // printf("sleep time = %d\r\n",(TIMER_WAKEUP_TIME_US*Machine_info.eflagID)/1000); #if 1 set_screen_dis_info_and_send_queue(true, false, false, true, 100); #endif #else #if 0 send_sleep_Queue(); #else printf("Already_send_timer_callback\r\n"); extern void send_can_I_receive(); send_can_I_receive(); // 发送可以接受的命令 uart_wait_tx_idle_polling(UART_NUM_1); sleep_timer_start(600); // 进入睡眠 // #include "ulp_riscv.h" // #include "esp_sleep.h" // #include "driver/uart.h" // //printf("error =%d\r\n",err); // uart_wait_tx_idle_polling(0); // //ulp_riscv_timer_resume(); // esp_light_sleep_start(); #endif #endif } /********************************************************************************* * function : Already_send_timer_start * Description : 定到达指定时间准备发送数据或者接收数据 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void Already_send_timer_start(int ms) { #if TIMER_CHOICE xTimerStop(already_send_timer, 0); // 停止定时器 // 在这里可以改变定时器的超时时间 // 第一个参数是定时器句柄,第二个参数是新的超时时间(以时钟节拍为单位) xTimerChangePeriod(already_send_timer, pdMS_TO_TICKS(ms), 0); xTimerStart(already_send_timer, 0); // 开始定时器 #else ESP_ERROR_CHECK(esp_timer_start_once(already_send_timer, ms * 1000)); // 500ms #endif } /********************************************************************************* * function : Already_send_timer_stop * Description : 停止定时器 * Input : * Output : * Author : 祁鑫 Data : 2023 10.18 **********************************************************************************/ void Already_send_timer_stop(void) { #if TIMER_CHOICE xTimerStop(already_send_timer, 0); // 停止定时器 #else ESP_ERROR_CHECK(esp_timer_stop(already_send_timer)); #endif } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /*定时器唤醒*/ #include "esp_check.h" #include "esp_sleep.h" static const char *TAG = "timer_wakeup"; esp_err_t example_register_timer_wakeup(void) { ESP_RETURN_ON_ERROR(esp_sleep_enable_timer_wakeup(TIMER_WAKEUP_TIME_US), TAG, "Configure timer as wakeup source failed"); ESP_LOGI(TAG, "timer wakeup source is ready"); return ESP_OK; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #endif void user_sleep_into() { #if DEEP_SLEEP struct timeval now; gettimeofday(&now, NULL); int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; switch (esp_sleep_get_wakeup_cause()) { #if CONFIG_EXAMPLE_EXT0_WAKEUP case ESP_SLEEP_WAKEUP_EXT0: { printf("Wake up from ext0\n"); break; } #endif // CONFIG_EXAMPLE_EXT0_WAKEUP #ifdef CONFIG_EXAMPLE_EXT1_WAKEUP case ESP_SLEEP_WAKEUP_EXT1: { uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status(); if (wakeup_pin_mask != 0) { int pin = __builtin_ffsll(wakeup_pin_mask) - 1; printf("Wake up from GPIO %d\n", pin); } else { printf("Wake up from GPIO\n"); } break; } #endif // CONFIG_EXAMPLE_EXT1_WAKEUP #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP case ESP_SLEEP_WAKEUP_GPIO: { uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status(); if (wakeup_pin_mask != 0) { int pin = __builtin_ffsll(wakeup_pin_mask) - 1; printf("Wake up from GPIO %d\n", pin); } else { printf("Wake up from GPIO\n"); } break; } #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP case ESP_SLEEP_WAKEUP_TIMER: { printf("Wake up from timer. Time spent in deep sleep: %dms\n", sleep_time_ms); break; } #ifdef CONFIG_EXAMPLE_TOUCH_WAKEUP case ESP_SLEEP_WAKEUP_TOUCHPAD: { printf("Wake up from touch on pad %d\n", esp_sleep_get_touchpad_wakeup_status()); break; } #endif // CONFIG_EXAMPLE_TOUCH_WAKEUP case ESP_SLEEP_WAKEUP_UNDEFINED: default: printf("Not a deep sleep reset\n"); } vTaskDelay(1000 / portTICK_PERIOD_MS); const int wakeup_time_sec = 3; printf("Enabling timer wakeup, %ds\n", wakeup_time_sec); ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000)); printf("Entering deep sleep\n"); // get deep sleep enter time gettimeofday(&sleep_enter_time, NULL); font_into_sleep(); #if 0 int i = 60; printf("not start deep display\r\n"); while(i--) { vTaskDelay(1000 / portTICK_PERIOD_MS); } printf("start deep display\r\n"); epd_sleep(SCREEN_LEFT); epd_sleep(SCREEN_RIGHT); i = 60; while(i--) { vTaskDelay(1000 / portTICK_PERIOD_MS); } #else epd_sleep(SCREEN_LEFT); epd_sleep(SCREEN_RIGHT); #endif // enter deep sleep esp_deep_sleep_start(); #else #if 0 //进入睡眠timer const esp_timer_create_args_t lora_timer_args = { .callback = &sleep_timer_callback, /* argument specified here will be passed to timer callback function */ .name = "sleep_one-shot" }; ESP_ERROR_CHECK(esp_timer_create(&lora_timer_args, &sleep_timer)); //唤醒后可以准备发送数据的timer const esp_timer_create_args_t send_timer_args = { .callback = &Already_send_timer_callback, /* argument specified here will be passed to timer callback function */ .name = "sleep_one-shot" }; ESP_ERROR_CHECK(esp_timer_create(&send_timer_args, &already_send_timer)); #else // 创建 sleep_timer = xTimerCreate( "sleep_timer", // 定时器名称(可以为NULL) pdMS_TO_TICKS(800), // 定时器超时时间(以毫秒为单位) pdFALSE, // 定时器为周期性(pdTRUE)还是单次(pdFALSE) 0, // 定时器ID(可以为0) sleep_timer_callback // 定时器回调函数 ); // 创建 already_send_timer = xTimerCreate( "already_send_timer", // 定时器名称(可以为NULL) pdMS_TO_TICKS(800), // 定时器超时时间(以毫秒为单位) pdFALSE, // 定时器为周期性(pdTRUE)还是单次(pdFALSE) 0, // 定时器ID(可以为0) Already_send_timer_callback // 定时器回调函数 ); #endif #endif } int is_wake_up_reson() // 返回唤醒的原因 { _wakeup_reson = esp_sleep_get_wakeup_cause(); // /* not a wakeup from ULP, load the firmware */ // if ((cause != ESP_SLEEP_WAKEUP_ULP) && (cause != ESP_SLEEP_WAKEUP_TIMER)) { // printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause); // init_ulp_program(); // } return _wakeup_reson; } #include "user_button.h" int left_adc_wake_btn_send() { uint16_t adc_value[][2] = { {BAOYANG_MIN_ADC, BAOYANG_MAX_ADC}, {FENGCUN_MIN_ADC, FENGCUN_MAX_ADC}, {GUZHUANG_MIN_ADC, GUZHANG_MAX_ADC}, {DAILIAO_MIN_ADC, DAILIAO_MAX_ADC}, {TINGJI_MIN_ADC, TINGJI_MAX_ADC}, {YUNXING_MIN_ADC, YUNXING_MAX_ADC}, }; // 获取adc值 返回左界面索引值 #include "user_button.h" int result = 0xff; int button_info = 0xfB; // extern uint16_t adc_value[][2]; #include "ulp/example_config.h" // extern int32_t wakeup_result; // int result_adc = wakeup_result; #if 1 int result_adc = ulp_wakeup_result; #endif int mid_result = result_adc; //(int)(((float)(result_adc/4095.0))*1100); printf("mid adc = %d\r\n", mid_result); for (int i = 0; i < 6; i++) { if ((adc_value[i][0] <= mid_result) && (adc_value[i][1] >= mid_result)) { result = i; break; } } switch ((int)result) { case BAOYANG_KEY: button_info = 6; // ESP_LOGD(LOG_TAG,"bao yang"); break; case FENGCUN_KEY: button_info = 5; // ESP_LOGD(LOG_TAG,"feng cun"); break; case GUZHUANG_KEY: button_info = 4; // ESP_LOGD(LOG_TAG,"gu zhang"); break; case DAILIAO_KEY: button_info = 3; // ESP_LOGD(LOG_TAG,"dai liao"); break; case TINGJI_KEY: button_info = 2; // ESP_LOGD(LOG_TAG,"ting ji"); break; case YUNXING_KEY: button_info = 1; // ESP_LOGD(LOG_TAG,"yun xing"); break; default: break; } ulp_wakeup_result = 3300; if (button_info > 6) { return 0xff; } return button_info; }