#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include <inttypes.h>
#include <driver/gpio.h>
#include <esp_sleep.h>
#include <esp_attr.h>
#include "ADC.h"
#include "PWM.h"
#define WAKE_BTN_GPIO 14 // номер пина пробуждения
#define LIGHT_SLEEP_US (2ULL * 1000000ULL) // 2 sec
#define ACTIVE_MS 5000 // 5 с когда мы можем регулировать яркость светодиода
#define LIGHT_CYCLES_BEFORE_DEEP 3 // Сколько циклов работы перед уходом в сон
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
static const char *TAG = "ADC_PWM_SLEEP";
// Переменная которая будет храниться при DEEP SLEEP
RTC_DATA_ATTR static uint32_t boot_count = 0;
// Обычная переменная для LIGHTSLEEP
static uint32_t runtime_count = 0;
// Convert WAKEUP CASE to readable format
static const char* wakeup_cause_to_str(esp_sleep_wakeup_cause_t cause) {
switch (cause) {
case ESP_SLEEP_WAKEUP_TIMER: return "TIMER";
case ESP_SLEEP_WAKEUP_GPIO: return "GPIO";
case ESP_SLEEP_WAKEUP_EXT0: return "EXT0";
case ESP_SLEEP_WAKEUP_TOUCHPAD: return "TOUCHPAD";
case ESP_SLEEP_WAKEUP_ULP: return "EXT0";
default: return "OTHER";
}
}
//==≠=============================================================
// Button init for deep wakeup
static void wake_button_init(void) {
gpio_config_t io = {
.pin_bit_mask = (1ULL << WAKE_BTN_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
ESP_ERROR_CHECK(gpio_config(&io));
}
//================================================================
// Debounce
static void debounce_after_deep_wakeup(void) {
vTaskDelay(pdMS_TO_TICKS(30));
while(gpio_get_level(WAKE_BTN_GPIO) == 0) {
vTaskDelay(pdMS_TO_TICKS(30));
}
}
//================================================================
void app_main() {
esp_log_level_set("*", ESP_LOG_VERBOSE);
// Узнаем причину пробуждения
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
boot_count++;
ESP_LOGI(TAG, "Wake up cause %s", wakeup_cause_to_str(cause));
ESP_LOGI(TAG, "Boot count (RTC) = %lu, runtime counter (normal) = %lu",
(unsigned long)boot_count, (unsigned long)runtime_count);
// Инициируем пин пробужденич
wake_button_init();
// Если причина пробуждения от кнопки, то обрабатываем дребезг
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
debounce_after_deep_wakeup();
}
// Инициируем ADC
ldr_adc_init();
// Инициируем PWM
PWM_init();
// определяем допустимое разрешение при частоте 5000 Гц
//uint32_t duty_res = ledc_find_suitable_duty_resolution(80000000, 5000);
int lite_cycles = 0; // Переменная кол-ва циклов лёгкого сна
while (true) {
// After N cyclesof actions going to deep sleep
if (lite_cycles >= LIGHT_CYCLES_BEFORE_DEEP) {
ESP_LOGI(TAG,"Enter deep sleep now.");
ESP_LOGI(TAG,"Wakeup: press button GPIO%d", WAKE_BTN_GPIO);
ESP_ERROR_CHECK(esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER));
//ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(1ULL<< WAKE_BTN_GPIO, ESP_GPIO_WAKEUP_GPIO_LOW));
esp_sleep_enable_ext0_wakeup(14, 1);
// Задержка чтобы логи успели уйти в терминал
vTaskDelay(pdMS_TO_TICKS(50));
// Засыпаем глубоким сном
esp_deep_sleep_start();
}
//================================================
// Active operations: 5 sec
TickType_t t0 = xTaskGetTickCount(); // Записываем в t0 текущее время
while ((xTaskGetTickCount()- t0) < pdMS_TO_TICKS(ACTIVE_MS)) {
int raw = read_adc();
PWM_set(raw);
runtime_count++;
vTaskDelay(pdMS_TO_TICKS(100));
}
ESP_LOGI(TAG, "Cycle done. runtime counter = %lu", (unsigned long)runtime_count);
//================================================
// Настраиваем таймер для выхода из LIGHT SLEEP через LIGHT_SLEEP_US
ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(LIGHT_SLEEP_US));
ESP_LOGI(TAG, "Enter light sleep for %llu ms (cycle %d/%d)", (unsigned long long) (LIGHT_SLEEP_US / 1000ULL),
lite_cycles + 1, LIGHT_CYCLES_BEFORE_DEEP);
//ESP_LOGI(TAG, "duty resolution = %"PRIu32"", duty_res);
esp_light_sleep_start();
esp_sleep_wakeup_cause_t c = esp_sleep_get_wakeup_cause();
ESP_LOGI(TAG, "Wakeup from light sleep, cause %s", wakeup_cause_to_str(c));
lite_cycles++;
}
}