#include #include #include "esp_rom_sys.h" #include "esp_task_wdt.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "nvs_flash.h" #include "esp_system.h" #include "esp_log.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_netif.h" #include "esp_sntp.h" #include "eeprom_virtual.h" #include "eeprom_tls.h" #include "eeprom_animacao.h" #include "wifi_config_portal.h" #include "mqtt_handler.h" #include "led_driver.h" #include "led_effects.h" #include "creditos.h" #include "led_task.h" #include "driver/i2c.h" #include "i2c_helper.h" #include "display.h" #include bool modo_bloqueado = false; // definição oficial #define SDA_PIN 21 #define SCL_PIN 22 #define I2C_PORT I2C_NUM_0 static const char *TAG = "APP"; static uint32_t segundos = 0; static bool wifi_ready = false; typedef struct { int total_creditos; int total_saidas; } contadores_t; // ============================ // Task contador simples // ============================ void segundos_task(void *pv) { while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); segundos++; } } uint32_t get_segundos(void) { return segundos; } // ============================ // Callback Wi-Fi pronto // ============================ static void on_wifi_connected(void) { wifi_ready = true; ESP_LOGI(TAG, "✅ Wi-Fi conectado — iniciando MQTT..."); mqtt_handler_start(); ESP_LOGI(TAG, "🕒 SNTP..."); esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, "pool.ntp.org"); esp_sntp_init(); ESP_LOGI(TAG, "💡 Inicializando driver LED..."); led_driver_init(); ESP_LOGI(TAG, "🎬 Iniciando tasks LED e Créditos..."); xTaskCreate(led_task, "led_task", 8192, NULL, 5, NULL); xTaskCreate(creditos_task, "creditos_task", 8192, NULL, 5, NULL); } // ============================ // Stack Overflow Handler // ============================ void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { esp_rom_printf("\n🧨 Stack overflow em %s!\n", pcTaskName); esp_task_wdt_reset(); vTaskDelay(pdMS_TO_TICKS(1000)); esp_restart(); } // Configuração básica do I2C i2c_config_t cfg = { .mode = I2C_MODE_MASTER, .sda_io_num = SDA_PIN, .scl_io_num = SCL_PIN, .sda_pullup_en = GPIO_PULLUP_ENABLE, .scl_pullup_en = GPIO_PULLUP_ENABLE, .master.clk_speed = 100000 }; void ht16_init() { uint8_t cmd1 = 0x21; // liga oscilador i2c_master_write_to_device(I2C_PORT, 0x70, &cmd1, 1, 10 / portTICK_PERIOD_MS); uint8_t cmd2 = 0x81; // display ON, sem piscar i2c_master_write_to_device(I2C_PORT, 0x70, &cmd2, 1, 10 / portTICK_PERIOD_MS); uint8_t cmd3 = 0xEF; // brilho máximo i2c_master_write_to_device(I2C_PORT, 0x70, &cmd3, 1, 10 / portTICK_PERIOD_MS); } void ht16_test() { uint8_t buf[17] = {0}; buf[0] = 0x00; // endereço inicial buf[7] = 0b0111111; // acende apenas o dígito 0 // (que mostra um "0" bonitinho) // Os outros dígitos ficam a 0 = apagados i2c_master_write_to_device(I2C_PORT, 0x70, buf, sizeof(buf), 20 / portTICK_PERIOD_MS); } void i2c_scan() { printf("\n--- A fazer scan ao I2C ---\n"); // --- SCAN I2C --- for (uint8_t addr = 1; addr < 127; addr++) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (addr << 1) | I2C_MASTER_WRITE, true); i2c_master_stop(cmd); esp_err_t r = i2c_master_cmd_begin(I2C_PORT, cmd, 20 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (r == ESP_OK) { printf("ENCONTRADO I2C: 0x%02X\n", addr); } } } // ============================ // MAIN // ============================ void app_main(void) { // -------- EEPROM virtual -------- eeprom_virtual_init(); contadores_t contadores = {100, 25}; eeprom_virtual_write_bin("contadores", &contadores, sizeof(contadores)); ESP_LOGI("EEPROM", "💾 Gravado: total_creditos=%d, total_saidas=%d", contadores.total_creditos, contadores.total_saidas); contadores_t lidos = {0}; size_t len = sizeof(lidos); if (eeprom_virtual_read_bin("contadores", &lidos, &len) == ESP_OK) { ESP_LOGI("EEPROM", "📖 Lido: total_creditos=%d, total_saidas=%d", lidos.total_creditos, lidos.total_saidas); } else { ESP_LOGW("EEPROM", "⚠️ Falha ao ler dados!"); } // -------- NVS normal -------- ESP_ERROR_CHECK(nvs_flash_init()); animacao_load(); ESP_LOGI("ANIM", "🎨 Animação carregada = %u", animacao); i2c_init(); // <- o helper entra aqui display_init(); // <- inicializa o HT16K33 i2c_scan(); display_text_top("INIT"); // -------- Wi-Fi -------- wifi_config_t cfg; bool have_creds = false; if (esp_wifi_get_config(WIFI_IF_STA, &cfg) == ESP_OK) { if (strlen((char *)cfg.sta.ssid) > 0) { ESP_LOGI(TAG, "📂 Credenciais no NVS: SSID=%s", cfg.sta.ssid); have_creds = true; } } wifi_config_portal_init(on_wifi_connected, have_creds); // -------- Criar tasks iniciais -------- xTaskCreate(segundos_task, "segundos_task", 4096, NULL, 5, NULL); // -------- Loop principal -------- while (1) { if (wifi_ready) { mqtt_handler_loop(); } vTaskDelay(pdMS_TO_TICKS(100)); } }