Added automatic light sleep.

This commit is contained in:
imi415 2021-06-08 00:54:03 +08:00
parent 322fc1d9c6
commit a7bacfd671
Signed by: imi415
GPG Key ID: 17F01E106F9F5E0A
12 changed files with 232 additions and 19 deletions

View File

@ -8,6 +8,7 @@ idf_component_register(SRCS
"app_lib_epd_impl.c"
"app_lib_wifi_impl.c"
"app_lib_fs_impl.c"
"app_lib_pm_impl.c"
"lib/gdew042t2_epd.c"
"lib/ltc2941_battery.c"
"lib/sht35_dht.c"

View File

@ -17,4 +17,89 @@ menu "Application Specific Configuration"
default 5
help
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
config APP_WIFI_LISTEN_INTERVAL
int "WiFi listen interval"
default 3
help
Interval for station to listen to beacon from AP. The unit of listen interval is one beacon interval.
For example, if beacon interval is 100 ms and listen interval is 3, the interval for station to listen
to beacon is 300 ms.
choice APP_POWER_SAVE_MODE
prompt "power save mode"
default APP_POWER_SAVE_MIN_MODEM
help
Power save mode for the esp32 to use. Modem sleep mode includes minimum and maximum power save modes.
In minimum power save mode, station wakes up every DTIM to receive beacon. Broadcast data will not be
lost because it is transmitted after DTIM. However, it can not save much more power if DTIM is short
for DTIM is determined by AP.
In maximum power save mode, station wakes up every listen interval to receive beacon. Broadcast data
may be lost because station may be in sleep state at DTIM time. If listen interval is longer, more power
is saved but broadcast data is more easy to lose.
config APP_POWER_SAVE_NONE
bool "none"
config APP_POWER_SAVE_MIN_MODEM
bool "minimum modem"
config APP_POWER_SAVE_MAX_MODEM
bool "maximum modem"
endchoice
choice APP_MAX_CPU_FREQ
prompt "Maximum CPU frequency"
default APP_MAX_CPU_FREQ_80
depends on PM_ENABLE
help
Maximum CPU frequency to use for dynamic frequency scaling.
config APP_MAX_CPU_FREQ_80
bool "80 MHz"
config APP_MAX_CPU_FREQ_160
bool "160 MHz"
config APP_MAX_CPU_FREQ_240
bool "240 MHz"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
endchoice
config APP_MAX_CPU_FREQ_MHZ
int
default 80 if APP_MAX_CPU_FREQ_80
default 160 if APP_MAX_CPU_FREQ_160
default 240 if APP_MAX_CPU_FREQ_240
choice APP_MIN_CPU_FREQ
prompt "Minimum CPU frequency"
default APP_MIN_CPU_FREQ_10M
depends on PM_ENABLE
help
Minimum CPU frequency to use for dynamic frequency scaling.
Should be set to XTAL frequency or XTAL frequency divided by integer.
config APP_MIN_CPU_FREQ_40M
bool "40 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_20M
bool "20 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_10M
bool "10 MHz (use with 40MHz XTAL)"
depends on IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || ESP32_XTAL_FREQ_40 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_26M
bool "26 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
config APP_MIN_CPU_FREQ_13M
bool "13 MHz (use with 26MHz XTAL)"
depends on ESP32_XTAL_FREQ_26 || ESP32_XTAL_FREQ_AUTO
endchoice
config APP_MIN_CPU_FREQ_MHZ
int
default 40 if APP_MIN_CPU_FREQ_40M
default 20 if APP_MIN_CPU_FREQ_20M
default 10 if APP_MIN_CPU_FREQ_10M
default 26 if APP_MIN_CPU_FREQ_26M
default 13 if APP_MIN_CPU_FREQ_13M
endmenu

View File

@ -1,3 +1,5 @@
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -5,7 +7,7 @@
#include "app_lib_epd_impl.h"
#define MAXIMUM_XFER_SIZE 400 * 300 / 8 // FULL fb.
#define MAXIMUM_XFER_SIZE 4000
#define MAX_BUSY_POLL_COUNT 10
static void _spi_pre_transfere_callback(spi_transaction_t *txn) {
@ -46,6 +48,7 @@ void app_lib_epd_impl_init(app_lib_epd_impl_t *impl) {
.spics_io_num = BOARD_EPD_SPI_CS_PIN,
.queue_size = 7,
.pre_cb = _spi_pre_transfere_callback,
.flags = SPI_DEVICE_HALFDUPLEX,
};
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &bus_cfg, SPI_DMA_CH_AUTO));
@ -102,15 +105,36 @@ gd_epd_042_ret_t app_lib_epd_impl_write_cmd(app_lib_epd_impl_t *impl, uint8_t *c
gd_epd_042_ret_t app_lib_epd_impl_write_data(app_lib_epd_impl_t *impl, uint8_t *data, uint32_t len) {
esp_err_t ret;
uint8_t *dma_buffer = heap_caps_malloc(MAXIMUM_XFER_SIZE, MALLOC_CAP_DMA);
if(dma_buffer == NULL) return EPD_ERR;
uint8_t has_partial = (len % MAXIMUM_XFER_SIZE ? 1 : 0);
uint32_t txn_count = len / MAXIMUM_XFER_SIZE + has_partial;
spi_transaction_t txn = {
.length = 8 * len,
.tx_buffer = data,
.user = (void *)1
};
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
for(uint32_t i = 0; i < txn_count; i++) {
uint16_t txn_bytes = MAXIMUM_XFER_SIZE;
if(i == (txn_count - 1) && has_partial) {
txn_bytes = len % MAXIMUM_XFER_SIZE;
}
memcpy(dma_buffer, &data[i * MAXIMUM_XFER_SIZE], txn_bytes);
txn.length = 8 * txn_bytes;
txn.tx_buffer = dma_buffer;
ret = spi_device_polling_transmit(impl->spi_handle, &txn);
if(ret != ESP_OK) return EPD_ERR;
}
free(dma_buffer);
if(ret != ESP_OK) return EPD_ERR;
return EPD_OK;
}

14
main/app_lib_pm_impl.c Normal file
View File

@ -0,0 +1,14 @@
#include "esp_pm.h"
#define DVFS_MAXIMUM_FREQ CONFIG_APP_MAX_CPU_FREQ_MHZ
#define DVFS_MINIMUM_FREQ CONFIG_APP_MIN_CPU_FREQ_MHZ
void app_lib_pm_init(void) {
esp_pm_config_esp32s2_t pm_config = {
.max_freq_mhz = DVFS_MAXIMUM_FREQ,
.min_freq_mhz = DVFS_MINIMUM_FREQ,
.light_sleep_enable = true
};
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
}

6
main/app_lib_pm_impl.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __APP_LIB_PM_IMPL_H
#define __APP_LIB_PM_IMPL_H
void app_lib_pm_init(void);
#endif

View File

@ -17,6 +17,21 @@ static const char *TAG = "APP_WIFI";
#define APP_WIFI_SSID CONFIG_APP_WIFI_SSID
#define APP_WIFI_PASS CONFIG_APP_WIFI_PASSWORD
#define APP_WIFI_RETR CONFIG_APP_WIFI_MAXIMUM_RETRY
#define APP_WIFI_INTV CONFIG_APP_WIFI_LISTEN_INTERVAL
#if CONFIG_APP_POWER_SAVE_MIN_MODEM
#define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM
#elif CONFIG_APP_POWER_SAVE_MAX_MODEM
#define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM
#elif CONFIG_APP_POWER_SAVE_NONE
#define DEFAULT_PS_MODE WIFI_PS_NONE
#else
#define DEFAULT_PS_MODE WIFI_PS_NONE
#endif
static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
@ -38,7 +53,7 @@ static void event_handler(void *arg, esp_event_base_t event_base, int32_t event_
}
}
void app_lib_start_wifi(void) {
void app_lib_init_wifi(void) {
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
@ -65,6 +80,7 @@ void app_lib_start_wifi(void) {
.ssid = APP_WIFI_SSID,
.password = APP_WIFI_PASS,
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
.listen_interval = APP_WIFI_INTV,
.pmf_cfg = {
.capable = true,
@ -75,5 +91,12 @@ void app_lib_start_wifi(void) {
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
}
void app_lib_start_wifi(void) {
ESP_ERROR_CHECK(esp_wifi_start());
}
void app_lib_stop_wifi(void) {
ESP_ERROR_CHECK(esp_wifi_stop());
}

View File

@ -10,6 +10,8 @@ extern EventGroupHandle_t g_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_ERROR_BIT BIT1
void app_lib_init_wifi(void);
void app_lib_start_wifi(void);
void app_lib_stop_wifi(void);
#endif

20
main/app_task.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __APP_TASK_H
#define __APP_TASK_H
#include "esp_sleep.h"
typedef struct {
esp_sleep_source_t wakeup_source;
void *user_params;
} app_task_params_t;
void vTaskLEDs(void *pvParameters);
extern TaskHandle_t xTaskLEDsHandle;
void vTasBatteryExample(void *pvParameters);
extern TaskHandle_t xTaskBatteryExampleHandle;
extern TaskHandle_t xTaskEPDExampleHandle;
void vTaskEPDExample(void *pvParameters);
#endif

View File

@ -44,6 +44,6 @@ void vTasBatteryExample(void *pvParameters) {
ESP_LOGI(TAG, "Capacity: %04.2fmAh, Charge: %03.2f%%", mah, percentage);
vTaskDelay(pdMS_TO_TICKS(5000));
vTaskDelay(pdMS_TO_TICKS(30000));
}
}

View File

@ -4,9 +4,13 @@
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "app_lib_epd_impl.h"
static uint8_t frame_data[2][15000];
static uint8_t *frame_data[2];
static const char *TAG = "TASK_EPD";
extern const unsigned char pixiv_82311703_p0_4indexed[];
extern const unsigned char pixiv_57852730_p0_4indexed[];
@ -19,6 +23,16 @@ extern const unsigned char pixiv_57852730_p0_4indexed[];
TaskHandle_t xTaskEPDExampleHandle = NULL;
void vTaskEPDExample(void *pvParameters) {
ESP_LOGI(TAG, "EPD task started.");
frame_data[0] = malloc(15000);
frame_data[1] = malloc(15000);
if(frame_data[0] == NULL || frame_data[1] == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory on heap.");
vTaskSuspend(NULL);
}
app_lib_epd_impl_t epd_impl = {0};
gd_epd_042_t epd = {
@ -40,11 +54,15 @@ void vTaskEPDExample(void *pvParameters) {
frame_data[1][i] = ARRAY_EVEN_BYTES(pixiv_57852730_p0_4indexed, i);
}
ESP_LOGI(TAG, "EPD frame constructed.");
gd_epd_042_load(&epd, frame_data[0], frame_data[1]);
gd_epd_042_update(&epd);
gd_epd_042_deepsleep(&epd);
ESP_LOGI(TAG, "EPD task finished.");
for(;;) {
vTaskDelay(pdMS_TO_TICKS(10000));
vTaskSuspend(NULL);
}
}

View File

@ -105,7 +105,13 @@ void vTaskLEDs(void *pvParameters) {
ledc_channels[i].channel, LEDC_FADE_NO_WAIT);
}
current_phase++;
if(current_phase == 8) current_phase = 0;
if(current_phase == 8) {
for(uint8_t i = 0; i < 4; i++) {
ledc_set_duty(ledc_channels[i].speed_mode, ledc_channels[i].channel, 0);
}
vTaskSuspend(NULL);
}
vTaskDelay(pdMS_TO_TICKS(BREATHE_LED_CYCLE));
}
}

View File

@ -8,17 +8,11 @@
#include "app_lib_wifi_impl.h"
#include "app_lib_fs_impl.h"
#include "app_lib_pm_impl.h"
#include "user_board.h"
void vTaskLEDs(void *pvParameters);
extern TaskHandle_t xTaskLEDsHandle;
void vTasBatteryExample(void *pvParameters);
extern TaskHandle_t xTaskBatteryExampleHandle;
extern TaskHandle_t xTaskEPDExampleHandle;
void vTaskEPDExample(void *pvParameters);
#include "app_task.h"
void app_lib_i2c_system_init(void);
@ -27,15 +21,35 @@ static const char *TAG = "APP_MAIN";
void app_main(void) {
// Init system peripherals.
app_lib_i2c_system_init();
//app_lib_pm_init();
app_lib_init_wifi();
app_lib_start_wifi();
app_lib_fs_init();
ESP_LOGI(TAG, "System initialized, starting tasks.");
// Init tasks
xTaskCreate(vTaskLEDs, "TASK_LEDs", 1024, NULL, 4, &xTaskLEDsHandle);
xTaskCreate(vTasBatteryExample, "TASK_BAT", 2048, NULL, 4, &xTaskBatteryExampleHandle);
xTaskCreate(vTaskEPDExample, "TASK_EPD", 2048, NULL, 4, &xTaskEPDExampleHandle);
if(xTaskCreate(vTaskLEDs, "TASK_LEDs", 1024, NULL, 4, &xTaskLEDsHandle) != pdPASS) {
ESP_LOGE(TAG, "Task LED creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
if(xTaskCreate(vTasBatteryExample, "TASK_BAT", 2048, NULL, 4, &xTaskBatteryExampleHandle) != pdPASS) {
ESP_LOGE(TAG, "Task BAT creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
if(xTaskCreate(vTaskEPDExample, "TASK_EPD", 2048, NULL, 4, &xTaskEPDExampleHandle) != pdPASS) {
ESP_LOGE(TAG, "Task EPD creation failed.");
for(;;) {
vTaskSuspend(NULL);
}
}
ESP_LOGI(TAG, "Task created, suspending current task.");