inicio do uso da eeprom
This commit is contained in:
parent
a1230f66ad
commit
e5572b2fad
13
.vscode/settings.json
vendored
13
.vscode/settings.json
vendored
@ -3,8 +3,14 @@
|
||||
"*.c": "c",
|
||||
"*.h": "c"
|
||||
},
|
||||
|
||||
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
|
||||
"C_Cpp.default.compileCommands": "Z:/varios/LED_shit/build/compile_commands.json",
|
||||
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||
|
||||
"C_Cpp.default.includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"C:/ESP/frameworks/v5.1.6/esp-idf/components/**"
|
||||
],
|
||||
|
||||
"idf.espIdfPath": "C:/Users/carec/esp/v5.1.6/esp-idf",
|
||||
"idf.pythonBinPath": "C:/Users/carec/.espressif/python_env/idf5.1_py3.11_env/Scripts/python.exe",
|
||||
@ -14,8 +20,9 @@
|
||||
"idf.adapterTargetName": "esp32",
|
||||
"idf.portWin": "COM3",
|
||||
"idf.flashType": "UART",
|
||||
"idf.buildDir": "C:/esp_build_temp",
|
||||
"idf.flashDir": "C:/esp_build_temp",
|
||||
|
||||
"idf.buildDir": "${workspaceFolder}/build",
|
||||
"idf.flashDir": "${workspaceFolder}/build",
|
||||
|
||||
"cmake.buildDirectory": "${workspaceFolder}/build",
|
||||
"cmake.configureSettings": {
|
||||
|
||||
@ -4,20 +4,17 @@ idf_component_register(
|
||||
"wifi_config_portal.c"
|
||||
"mqtt_handler.c"
|
||||
"mqtt_comandos.c"
|
||||
"fs_handler.c"
|
||||
"eeprom_tls.c"
|
||||
"eeprom_virtual.c"
|
||||
"dns_server.c"
|
||||
|
||||
# LED driver
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/led_driver.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/led_strip/led_strip.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/led_strip/led_strip_encoder.c"
|
||||
"dns_server.c"
|
||||
"led_driver.c"
|
||||
"led_effects.c"
|
||||
"eeprom_animacao.c"
|
||||
"led_task.c"
|
||||
"creditos.c"
|
||||
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
"include"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/led_strip"
|
||||
|
||||
REQUIRES
|
||||
esp_wifi
|
||||
@ -26,7 +23,6 @@ idf_component_register(
|
||||
nvs_flash
|
||||
mqtt
|
||||
json
|
||||
spiffs
|
||||
driver
|
||||
esp_http_server
|
||||
)
|
||||
|
||||
34
main/creditos.c
Normal file
34
main/creditos.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include "creditos.h"
|
||||
#include "led_driver.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
volatile bool tem_creditos = false;
|
||||
static const char *TAG = "CREDITOS";
|
||||
|
||||
void creditos_dar(void) {
|
||||
tem_creditos = true;
|
||||
ESP_LOGI(TAG, "💰 Crédito recebido");
|
||||
}
|
||||
|
||||
void creditos_task(void *pv) {
|
||||
while (1) {
|
||||
|
||||
if (tem_creditos) {
|
||||
uint16_t pos = esp_random() % LED_COUNT;
|
||||
|
||||
ESP_LOGI(TAG, "🎯 SPIN -> posição %u", pos);
|
||||
|
||||
led_spin_to(pos, 2, 12, 80);
|
||||
|
||||
tem_creditos = false; // crédito consumido
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
48
main/eeprom_animacao.c
Normal file
48
main/eeprom_animacao.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "eeprom_animacao.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "EEPROM_ANIM";
|
||||
|
||||
#define NAMESPACE "storage"
|
||||
#define KEY_ANIM "animacao"
|
||||
|
||||
// valor em RAM, sempre igual ao guardado
|
||||
uint8_t animacao = 0;
|
||||
|
||||
void animacao_load(void)
|
||||
{
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(NAMESPACE, NVS_READONLY, &handle);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
err = nvs_get_u8(handle, KEY_ANIM, &animacao);
|
||||
nvs_close(handle);
|
||||
|
||||
if (err != ESP_OK) {
|
||||
animacao = 0; // default
|
||||
}
|
||||
} else {
|
||||
animacao = 0; // default
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Carregado animacao = %u", animacao);
|
||||
}
|
||||
|
||||
void animacao_save(uint8_t v)
|
||||
{
|
||||
nvs_handle_t handle;
|
||||
esp_err_t err = nvs_open(NAMESPACE, NVS_READWRITE, &handle);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
nvs_set_u8(handle, KEY_ANIM, v);
|
||||
nvs_commit(handle);
|
||||
nvs_close(handle);
|
||||
|
||||
animacao = v; // atualiza RAM também
|
||||
ESP_LOGI(TAG, "Gravado animacao = %u", v);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Falha ao abrir NVS p/ animacao");
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_spiffs.h"
|
||||
|
||||
static const char *TAG = "FS";
|
||||
|
||||
// --- MONTAR SPIFFS ---
|
||||
void fs_init(void) {
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = "storage",
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = true
|
||||
};
|
||||
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "❌ Falha ao montar SPIFFS (%s)", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
size_t total = 0, used = 0;
|
||||
ret = esp_spiffs_info(conf.partition_label, &total, &used);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "❌ Erro ao obter info SPIFFS (%s)", esp_err_to_name(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "📂 SPIFFS montado: total=%d KB, usado=%d KB",
|
||||
(int)(total / 1024), (int)(used / 1024));
|
||||
|
||||
// Criar ficheiro de exemplo se não existir
|
||||
FILE *f = fopen("/spiffs/config.json", "r");
|
||||
if (!f) {
|
||||
ESP_LOGW(TAG, "⚠️ config.json não existe, a criar...");
|
||||
f = fopen("/spiffs/config.json", "w");
|
||||
if (f) {
|
||||
fprintf(f, "{ \"ssid\": \"ALQAEDA\", \"pass\": \"1q2w3e4r5t\" }");
|
||||
fclose(f);
|
||||
ESP_LOGI(TAG, "✅ config.json criado.");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "❌ Erro a criar config.json");
|
||||
}
|
||||
} else {
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
// --- DESMONTAR SPIFFS ---
|
||||
void fs_deinit(void) {
|
||||
ESP_LOGI(TAG, "🧹 Desmontando SPIFFS...");
|
||||
esp_vfs_spiffs_unregister(NULL);
|
||||
}
|
||||
8
main/include/creditos.h
Normal file
8
main/include/creditos.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
extern volatile bool tem_creditos;
|
||||
|
||||
void creditos_task(void *pv);
|
||||
void creditos_dar(void); // função para marcar crédito
|
||||
12
main/include/eeprom_animacao.h
Normal file
12
main/include/eeprom_animacao.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// byte carregado da EEPROM
|
||||
extern uint8_t animacao;
|
||||
|
||||
// lê o byte guardado
|
||||
void animacao_load(void);
|
||||
|
||||
// grava o byte
|
||||
void animacao_save(uint8_t v);
|
||||
@ -1,24 +1,26 @@
|
||||
#pragma once
|
||||
#ifndef LED_DRIVER_H
|
||||
#define LED_DRIVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// === Configurações principais ===
|
||||
#define LED_PIN 18
|
||||
#define LED_COUNT 60
|
||||
#define LED_RES_HZ 10000000 // 10 MHz de resolução (0.1 µs por tick)
|
||||
|
||||
// === Interface pública ===
|
||||
esp_err_t led_init(void);
|
||||
esp_err_t led_clear(void);
|
||||
esp_err_t led_set(uint16_t index, uint8_t r, uint8_t g, uint8_t b);
|
||||
esp_err_t led_show(void);
|
||||
void led_rainbow(uint16_t offset);
|
||||
void led_spin_to(uint16_t target, uint16_t rounds, uint16_t delay_start, uint16_t delay_end);
|
||||
void led_idle_animation(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#define LED_COUNT 60
|
||||
|
||||
// inicialização do driver
|
||||
void led_driver_init(void);
|
||||
|
||||
// número de LEDs
|
||||
int led_get_count(void);
|
||||
|
||||
// envia os dados para o anel
|
||||
void led_show(void);
|
||||
|
||||
// limpa todos os LEDs
|
||||
void led_clear(void);
|
||||
|
||||
// define um LED individual
|
||||
void led_set_pixel(int index, uint8_t r, uint8_t g, uint8_t b);
|
||||
|
||||
// spin da sorte
|
||||
void led_spin_to(uint16_t target, int min_spins, int max_spins, int base_delay_ms);
|
||||
|
||||
#endif
|
||||
|
||||
10
main/include/led_effects.h
Normal file
10
main/include/led_effects.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void led_all_on(uint8_t r, uint8_t g, uint8_t b);
|
||||
void led_all_off(void);
|
||||
|
||||
void led_idle_animation(void);
|
||||
void led_jackpot_animation(void);
|
||||
void led_clock_animation(void); // <-- NOVA ANIMAÇÃO
|
||||
3
main/include/led_task.h
Normal file
3
main/include/led_task.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void led_task(void *pv);
|
||||
@ -1,5 +1,4 @@
|
||||
#pragma once
|
||||
#include "cJSON.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
void mqtt_comandos_handle(cJSON *root);
|
||||
|
||||
@ -5,10 +5,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern esp_mqtt_client_handle_t mqtt_client; // ✅ agora visível em outros .c
|
||||
static inline void mqtt_handler_loop(void) {
|
||||
// placeholder — sem função neste build
|
||||
}
|
||||
extern esp_mqtt_client_handle_t mqtt_client;
|
||||
|
||||
// Exportar os tópicos MQTT (antes eram static!)
|
||||
extern char topic_status[64];
|
||||
extern char topic_cmd[64];
|
||||
extern char topic_resp[64];
|
||||
extern char topic_lwt[64];
|
||||
|
||||
// Opcional: loop placeholder
|
||||
static inline void mqtt_handler_loop(void) {}
|
||||
|
||||
void mqtt_handler_start(void);
|
||||
|
||||
|
||||
@ -1,147 +1,131 @@
|
||||
#include "led_driver.h"
|
||||
#include "driver/rmt_tx.h"
|
||||
#include "led_strip_encoder.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_random.h"
|
||||
#include <string.h>
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
static const char *TAG = "LED";
|
||||
static bool led_ready = false; // 🚦 flag de inicialização
|
||||
static rmt_channel_handle_t led_chan = NULL;
|
||||
static rmt_encoder_handle_t led_enc = NULL;
|
||||
static uint8_t led_pixels[LED_COUNT * 3];
|
||||
#define LED_PIN 18 // <-- CERTIFICA-TE disto
|
||||
#define RMT_RESOLUTION_HZ 10000000 // 10 MHz (1 tick = 0.1us)
|
||||
|
||||
// --- Conversão HSV → RGB ---
|
||||
static void hsv2rgb(uint32_t h, uint32_t s, uint32_t v,
|
||||
uint8_t *r, uint8_t *g, uint8_t *b)
|
||||
typedef struct {
|
||||
uint8_t r,g,b;
|
||||
} led_color_t;
|
||||
|
||||
static led_color_t leds[LED_COUNT];
|
||||
|
||||
static rmt_channel_handle_t rmt_chan = NULL;
|
||||
static rmt_encoder_handle_t encoder = NULL;
|
||||
|
||||
static rmt_transmit_config_t tx_config = {
|
||||
.loop_count = 0
|
||||
};
|
||||
|
||||
void led_driver_init(void)
|
||||
{
|
||||
h %= 360;
|
||||
uint32_t rgb_max = v * 255 / 100;
|
||||
uint32_t rgb_min = rgb_max * (100 - s) / 100;
|
||||
uint32_t i = h / 60, diff = h % 60;
|
||||
uint32_t adj = (rgb_max - rgb_min) * diff / 60;
|
||||
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
|
||||
|
||||
switch (i) {
|
||||
case 0: *r = rgb_max; *g = rgb_min + adj; *b = rgb_min; break;
|
||||
case 1: *r = rgb_max - adj; *g = rgb_max; *b = rgb_min; break;
|
||||
case 2: *r = rgb_min; *g = rgb_max; *b = rgb_min + adj; break;
|
||||
case 3: *r = rgb_min; *g = rgb_max - adj; *b = rgb_max; break;
|
||||
case 4: *r = rgb_min + adj; *g = rgb_min; *b = rgb_max; break;
|
||||
default:*r = rgb_max; *g = rgb_min; *b = rgb_max - adj; break;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Inicialização ---
|
||||
esp_err_t led_init(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Inicializando LEDs no GPIO%d (%d LEDs)", LED_PIN, LED_COUNT);
|
||||
|
||||
rmt_tx_channel_config_t tx_cfg = {
|
||||
rmt_tx_channel_config_t chan_cfg = {
|
||||
.gpio_num = LED_PIN,
|
||||
.clk_src = RMT_CLK_SRC_DEFAULT,
|
||||
.resolution_hz = RMT_RESOLUTION_HZ,
|
||||
.mem_block_symbols = 64,
|
||||
.resolution_hz = LED_RES_HZ,
|
||||
.trans_queue_depth = 4,
|
||||
.trans_queue_depth = 1,
|
||||
};
|
||||
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_cfg, &led_chan));
|
||||
|
||||
led_strip_encoder_config_t enc_cfg = {.resolution = LED_RES_HZ};
|
||||
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&enc_cfg, &led_enc));
|
||||
ESP_ERROR_CHECK(rmt_enable(led_chan));
|
||||
ESP_ERROR_CHECK(rmt_new_tx_channel(&chan_cfg, &rmt_chan));
|
||||
ESP_ERROR_CHECK(rmt_enable(rmt_chan));
|
||||
|
||||
memset(led_pixels, 0, sizeof(led_pixels));
|
||||
// WS2812B timings (EXATOS)
|
||||
rmt_bytes_encoder_config_t enc_cfg = {
|
||||
.bit0 = {
|
||||
.duration0 = 4, .level0 = 1, // 0.4us HIGH
|
||||
.duration1 = 9, .level1 = 0 // 0.9us LOW
|
||||
},
|
||||
.bit1 = {
|
||||
.duration0 = 9, .level0 = 1, // 0.9us HIGH
|
||||
.duration1 = 4, .level1 = 0 // 0.4us LOW
|
||||
},
|
||||
.flags.msb_first = 1
|
||||
};
|
||||
|
||||
led_ready = true; // ✅ marca como pronto
|
||||
led_show(); // apaga tudo ao iniciar
|
||||
return ESP_OK;
|
||||
ESP_ERROR_CHECK(rmt_new_bytes_encoder(&enc_cfg, &encoder));
|
||||
|
||||
memset(leds, 0, sizeof(leds));
|
||||
led_show();
|
||||
}
|
||||
|
||||
// --- Apagar todos os LEDs ---
|
||||
esp_err_t led_clear(void)
|
||||
void led_set_pixel(int index, uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
if (!led_ready) return ESP_ERR_INVALID_STATE;
|
||||
memset(led_pixels, 0, sizeof(led_pixels));
|
||||
return led_show();
|
||||
if (index < 0 || index >= LED_COUNT) return;
|
||||
leds[index].r = r;
|
||||
leds[index].g = g;
|
||||
leds[index].b = b;
|
||||
}
|
||||
|
||||
// --- Definir cor individual ---
|
||||
esp_err_t led_set(uint16_t index, uint8_t r, uint8_t g, uint8_t b)
|
||||
void led_clear(void)
|
||||
{
|
||||
if (index >= LED_COUNT) return ESP_ERR_INVALID_ARG;
|
||||
led_pixels[index * 3 + 0] = g; // WS2812 usa ordem GRB
|
||||
led_pixels[index * 3 + 1] = r;
|
||||
led_pixels[index * 3 + 2] = b;
|
||||
return ESP_OK;
|
||||
memset(leds, 0, sizeof(leds));
|
||||
}
|
||||
|
||||
// --- Enviar buffer para o anel ---
|
||||
esp_err_t led_show(void)
|
||||
static void hw_update(void)
|
||||
{
|
||||
if (!led_ready || !led_chan || !led_enc) {
|
||||
ESP_LOGW(TAG, "⚠️ led_show() chamado antes da inicialização — ignorado");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
uint8_t buf[LED_COUNT * 3];
|
||||
|
||||
// MOST common format is GRB
|
||||
for (int i = 0; i < LED_COUNT; i++) {
|
||||
buf[i*3 + 0] = leds[i].g;
|
||||
buf[i*3 + 1] = leds[i].r;
|
||||
buf[i*3 + 2] = leds[i].b;
|
||||
}
|
||||
|
||||
rmt_transmit_config_t tx_cfg = {.loop_count = 0};
|
||||
esp_err_t err = rmt_transmit(led_chan, led_enc,
|
||||
led_pixels, sizeof(led_pixels), &tx_cfg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "❌ rmt_transmit falhou (%s)", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
ESP_ERROR_CHECK(rmt_transmit(rmt_chan, encoder, buf, sizeof(buf), &tx_config));
|
||||
rmt_tx_wait_all_done(rmt_chan, -1);
|
||||
|
||||
// Reset time > 50us
|
||||
esp_rom_delay_us(60);
|
||||
|
||||
err = rmt_tx_wait_all_done(led_chan, portMAX_DELAY);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "❌ rmt_tx_wait_all_done falhou (%s)", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
// --- Animação de rotação até posição alvo ---
|
||||
void led_spin_to(uint16_t target, uint16_t rounds, uint16_t delay_start, uint16_t delay_end)
|
||||
|
||||
void led_show(void)
|
||||
{
|
||||
if (!led_ready) return;
|
||||
hw_update();
|
||||
}
|
||||
|
||||
uint32_t total_steps = rounds * LED_COUNT + target;
|
||||
for (uint32_t i = 0; i < total_steps; i++) {
|
||||
uint16_t pos = i % LED_COUNT;
|
||||
int led_get_count(void)
|
||||
{
|
||||
return LED_COUNT;
|
||||
}
|
||||
void led_spin_to(uint16_t target, int min_spins, int max_spins, int base_delay_ms)
|
||||
{
|
||||
int n = LED_COUNT;
|
||||
if (min_spins < 1) min_spins = 1;
|
||||
if (max_spins < min_spins) max_spins = min_spins;
|
||||
|
||||
int extra = 0;
|
||||
if (max_spins > min_spins)
|
||||
extra = rand() % (max_spins - min_spins + 1);
|
||||
|
||||
int total_steps = (min_spins + extra) * n + (target % n);
|
||||
int delay = base_delay_ms;
|
||||
|
||||
for (int step = 0; step <= total_steps; step++) {
|
||||
int pos = step % n;
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (i == pos)
|
||||
led_set_pixel(i, 0, 40, 0); // verde fraco no cursor
|
||||
else
|
||||
led_set_pixel(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Limpa e acende o LED atual
|
||||
led_clear();
|
||||
led_set(pos, 255, 150, 0);
|
||||
led_show();
|
||||
|
||||
// Calcula delay progressivo (aceleração -> desaceleração)
|
||||
uint32_t delay = delay_start + ((delay_end - delay_start) * i) / total_steps;
|
||||
if (step < total_steps / 3 && delay > 3)
|
||||
delay--;
|
||||
else if (step > (2 * total_steps) / 3)
|
||||
delay++;
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(delay));
|
||||
}
|
||||
|
||||
// Flash final
|
||||
for (int j = 0; j < 3; j++) {
|
||||
led_clear();
|
||||
led_show();
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
for (int k = 0; k < LED_COUNT; k++)
|
||||
led_set(k, 255, 200, 50);
|
||||
led_show();
|
||||
vTaskDelay(pdMS_TO_TICKS(80));
|
||||
}
|
||||
}
|
||||
|
||||
// --- Animação idle (arco-íris lento) ---
|
||||
void led_idle_animation(void)
|
||||
{
|
||||
if (!led_ready) return;
|
||||
|
||||
static uint16_t hue = 0;
|
||||
for (int i = 0; i < LED_COUNT; i++) {
|
||||
uint8_t r, g, b;
|
||||
hsv2rgb((hue + i * 6) % 360, 100, 10, &r, &g, &b);
|
||||
led_set(i, r, g, b);
|
||||
}
|
||||
led_show();
|
||||
hue = (hue + 2) % 360;
|
||||
}
|
||||
|
||||
115
main/led_effects.c
Normal file
115
main/led_effects.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "led_effects.h"
|
||||
#include "led_driver.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
void led_all_on(uint8_t r, uint8_t g, uint8_t b)
|
||||
{
|
||||
int n = led_get_count();
|
||||
for (int i = 0; i < n; i++) {
|
||||
led_set_pixel(i, r, g, b);
|
||||
}
|
||||
led_show();
|
||||
}
|
||||
|
||||
void led_all_off(void)
|
||||
{
|
||||
led_clear();
|
||||
led_show();
|
||||
}
|
||||
|
||||
void led_idle_animation(void)
|
||||
{
|
||||
static int pos = 0;
|
||||
int n = led_get_count();
|
||||
if (n <= 0) return;
|
||||
|
||||
for (int i = 0; i < n; i++)
|
||||
led_set_pixel(i, 0, 0, 0);
|
||||
|
||||
// pontinho azul
|
||||
led_set_pixel(pos, 0, 0, 16);
|
||||
led_show();
|
||||
|
||||
pos = (pos + 1) % n;
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
void led_jackpot_animation(void)
|
||||
{
|
||||
static int state = 0;
|
||||
static int step = 0;
|
||||
int n = led_get_count();
|
||||
|
||||
if (state == 0) {
|
||||
// Piscas laranja
|
||||
for (int i = 0; i < n; i++)
|
||||
led_set_pixel(i, (step & 1) ? 32 : 0, (step & 1) ? 16 : 0, 0);
|
||||
|
||||
led_show();
|
||||
|
||||
step++;
|
||||
if (step >= 12) { // 6 ON + 6 OFF
|
||||
step = 0;
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (state == 1) {
|
||||
// Arco-íris progressivo
|
||||
for (int i = 0; i < n; i++) {
|
||||
int x = (i + step) % n;
|
||||
uint8_t r = (x * 5) & 0xFF;
|
||||
uint8_t g = ((x * 3) & 0xFF) >> 1;
|
||||
uint8_t b = ((x * 7) & 0xFF) >> 2;
|
||||
led_set_pixel(i, r, g, b);
|
||||
}
|
||||
|
||||
led_show();
|
||||
|
||||
step++;
|
||||
if (step >= n * 2) {
|
||||
step = 0;
|
||||
state = 0; // repete a animação
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void led_clock_animation(void)
|
||||
{
|
||||
int n = led_get_count();
|
||||
if (n <= 0) return;
|
||||
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
int h = timeinfo.tm_hour % 12;
|
||||
int m = timeinfo.tm_min;
|
||||
int s = timeinfo.tm_sec;
|
||||
|
||||
int pos_h = (h * n) / 12;
|
||||
int pos_m = (m * n) / 60;
|
||||
int pos_s = (s * n) / 60;
|
||||
|
||||
led_clear();
|
||||
|
||||
// HORAS – verde forte
|
||||
led_set_pixel(pos_h, 10, 40, 10);
|
||||
|
||||
// MINUTOS – azul
|
||||
led_set_pixel(pos_m, 10, 10, 60);
|
||||
|
||||
// SEGUNDOS – branco muito suave
|
||||
led_set_pixel(pos_s, 5, 5, 5);
|
||||
|
||||
led_show();
|
||||
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
}
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
#include "led_strip.h"
|
||||
#include "esp_log.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
static const char *TAG = "led_strip";
|
||||
|
||||
struct led_strip_t {
|
||||
uint32_t length;
|
||||
uint8_t *buffer;
|
||||
rmt_channel_handle_t channel;
|
||||
uint32_t resolution;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t b;
|
||||
} __attribute__((packed)) grb_pixel_t;
|
||||
|
||||
esp_err_t led_strip_new_rmt_device(const led_strip_config_t *config, led_strip_handle_t *ret_strip) {
|
||||
if (!config || !ret_strip) return ESP_ERR_INVALID_ARG;
|
||||
|
||||
led_strip_handle_t strip = calloc(1, sizeof(struct led_strip_t));
|
||||
if (!strip) return ESP_ERR_NO_MEM;
|
||||
|
||||
strip->length = config->strip_length;
|
||||
strip->resolution = config->resolution_hz;
|
||||
strip->channel = config->rmt_channel;
|
||||
strip->buffer = calloc(strip->length, sizeof(grb_pixel_t));
|
||||
if (!strip->buffer) {
|
||||
free(strip);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
*ret_strip = strip;
|
||||
ESP_LOGI(TAG, "Novo LED strip criado (%lu LEDs)", (unsigned long)strip->length);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint8_t red, uint8_t green, uint8_t blue) {
|
||||
if (!strip || index >= strip->length) return ESP_ERR_INVALID_ARG;
|
||||
grb_pixel_t *pixels = (grb_pixel_t *)strip->buffer;
|
||||
pixels[index].g = green;
|
||||
pixels[index].r = red;
|
||||
pixels[index].b = blue;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t led_strip_refresh(led_strip_handle_t strip) {
|
||||
if (!strip) return ESP_ERR_INVALID_ARG;
|
||||
// Envia os dados via RMT
|
||||
rmt_transmit_config_t tx_conf = { .loop_count = 0 };
|
||||
ESP_ERROR_CHECK(rmt_transmit(strip->channel, NULL, strip->buffer, strip->length * sizeof(grb_pixel_t), &tx_conf));
|
||||
ESP_ERROR_CHECK(rmt_tx_wait_all_done(strip->channel, portMAX_DELAY));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t led_strip_clear(led_strip_handle_t strip) {
|
||||
if (!strip) return ESP_ERR_INVALID_ARG;
|
||||
memset(strip->buffer, 0, strip->length * sizeof(grb_pixel_t));
|
||||
return led_strip_refresh(strip);
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "driver/rmt_tx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Handle para a instância de LED strip
|
||||
*/
|
||||
typedef struct led_strip_t *led_strip_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Configuração para criar um LED strip
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t strip_length; // número de LEDs
|
||||
uint32_t resolution_hz; // resolução do RMT
|
||||
rmt_channel_handle_t rmt_channel;// canal RMT a usar
|
||||
} led_strip_config_t;
|
||||
|
||||
/**
|
||||
* @brief Cria uma nova instância de LED strip
|
||||
*/
|
||||
esp_err_t led_strip_new_rmt_device(const led_strip_config_t *config, led_strip_handle_t *ret_strip);
|
||||
|
||||
/**
|
||||
* @brief Define a cor de um LED (index base 0)
|
||||
*/
|
||||
esp_err_t led_strip_set_pixel(led_strip_handle_t strip, uint32_t index, uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/**
|
||||
* @brief Atualiza os LEDs com as cores definidas
|
||||
*/
|
||||
esp_err_t led_strip_refresh(led_strip_handle_t strip);
|
||||
|
||||
/**
|
||||
* @brief Limpa todos os LEDs (define para preto)
|
||||
*/
|
||||
esp_err_t led_strip_clear(led_strip_handle_t strip);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "led_strip_encoder.h"
|
||||
|
||||
static const char *TAG = "led_encoder";
|
||||
|
||||
typedef struct {
|
||||
rmt_encoder_t base;
|
||||
rmt_encoder_t *bytes_encoder;
|
||||
rmt_encoder_t *copy_encoder;
|
||||
int state;
|
||||
rmt_symbol_word_t reset_code;
|
||||
} rmt_led_strip_encoder_t;
|
||||
|
||||
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder, rmt_channel_handle_t channel, const void *primary_data, size_t data_size, rmt_encode_state_t *ret_state)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||
rmt_encode_state_t session_state = RMT_ENCODING_RESET;
|
||||
rmt_encode_state_t state = RMT_ENCODING_RESET;
|
||||
size_t encoded_symbols = 0;
|
||||
switch (led_encoder->state) {
|
||||
case 0: // send RGB data
|
||||
encoded_symbols += bytes_encoder->encode(bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||
led_encoder->state = 1; // switch to next state when current encoding session finished
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||
state |= RMT_ENCODING_MEM_FULL;
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
// fall-through
|
||||
case 1: // send reset code
|
||||
encoded_symbols += copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||
sizeof(led_encoder->reset_code), &session_state);
|
||||
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||
led_encoder->state = RMT_ENCODING_RESET; // back to the initial encoding session
|
||||
state |= RMT_ENCODING_COMPLETE;
|
||||
}
|
||||
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||
state |= RMT_ENCODING_MEM_FULL;
|
||||
goto out; // yield if there's no free space for encoding artifacts
|
||||
}
|
||||
}
|
||||
out:
|
||||
*ret_state = state;
|
||||
return encoded_symbols;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
free(led_encoder);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder)
|
||||
{
|
||||
rmt_led_strip_encoder_t *led_encoder = __containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||
led_encoder->state = RMT_ENCODING_RESET;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config, rmt_encoder_handle_t *ret_encoder)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
|
||||
led_encoder = rmt_alloc_encoder_mem(sizeof(rmt_led_strip_encoder_t));
|
||||
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG, "no mem for led strip encoder");
|
||||
led_encoder->base.encode = rmt_encode_led_strip;
|
||||
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||
// different led strip might have its own timing requirements, following parameter is for WS2812
|
||||
rmt_bytes_encoder_config_t bytes_encoder_config = {
|
||||
.bit0 = {
|
||||
.level0 = 1,
|
||||
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
|
||||
.level1 = 0,
|
||||
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
|
||||
},
|
||||
.bit1 = {
|
||||
.level0 = 1,
|
||||
.duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
|
||||
.level1 = 0,
|
||||
.duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
|
||||
},
|
||||
.flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder), err, TAG, "create bytes encoder failed");
|
||||
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||
ESP_GOTO_ON_ERROR(rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder), err, TAG, "create copy encoder failed");
|
||||
|
||||
uint32_t reset_ticks = config->resolution / 1000000 * 50 / 2; // reset code duration defaults to 50us
|
||||
led_encoder->reset_code = (rmt_symbol_word_t) {
|
||||
.level0 = 0,
|
||||
.duration0 = reset_ticks,
|
||||
.level1 = 0,
|
||||
.duration1 = reset_ticks,
|
||||
};
|
||||
*ret_encoder = &led_encoder->base;
|
||||
return ESP_OK;
|
||||
err:
|
||||
if (led_encoder) {
|
||||
if (led_encoder->bytes_encoder) {
|
||||
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||
}
|
||||
if (led_encoder->copy_encoder) {
|
||||
rmt_del_encoder(led_encoder->copy_encoder);
|
||||
}
|
||||
free(led_encoder);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include "driver/rmt_tx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configuração do encoder de LED strip (usado pelo RMT)
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t resolution; // resolução em Hz
|
||||
} led_strip_encoder_config_t;
|
||||
|
||||
/**
|
||||
* @brief Cria um novo encoder para enviar dados WS2812 via RMT.
|
||||
*
|
||||
* @param config Configuração do encoder (resolução)
|
||||
* @param ret_encoder Ponteiro de retorno do handle do encoder
|
||||
*
|
||||
* @return ESP_OK se criado com sucesso
|
||||
*/
|
||||
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
||||
rmt_encoder_handle_t *ret_encoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
42
main/led_task.c
Normal file
42
main/led_task.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "led_task.h"
|
||||
#include "led_effects.h"
|
||||
#include "eeprom_animacao.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "LED_TASK";
|
||||
|
||||
void led_task(void *pv)
|
||||
{
|
||||
ESP_LOGI(TAG, "💡 LED task iniciada");
|
||||
|
||||
while (1) {
|
||||
|
||||
switch (animacao) {
|
||||
|
||||
case 0:
|
||||
// modo idle (pontinho azul)
|
||||
led_idle_animation();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// modo relógio
|
||||
led_clock_animation();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// jackpot non-blocking
|
||||
led_jackpot_animation();
|
||||
break;
|
||||
|
||||
default:
|
||||
// fallback seguro
|
||||
led_idle_animation();
|
||||
break;
|
||||
}
|
||||
|
||||
// controla a velocidade de TODAS as animações
|
||||
vTaskDelay(pdMS_TO_TICKS(40)); // ~25 FPS
|
||||
}
|
||||
}
|
||||
114
main/main.c
114
main/main.c
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -11,31 +12,38 @@
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_spiffs.h"
|
||||
#include "esp_sntp.h"
|
||||
#include "wifi_config_portal.h"
|
||||
#include "mqtt_handler.h"
|
||||
#include "led_driver.h"
|
||||
#include "esp_random.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"
|
||||
|
||||
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;
|
||||
|
||||
static const char *TAG = "APP";
|
||||
static uint32_t segundos = 0;
|
||||
static bool wifi_ready = false;
|
||||
|
||||
// === Contador simples de debug ===
|
||||
// ============================
|
||||
// Task contador simples
|
||||
// ============================
|
||||
void segundos_task(void *pv) {
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
segundos++;
|
||||
// ESP_LOGI("TIMER", "⏱ %lu segundos", segundos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,55 +51,48 @@ uint32_t get_segundos(void) {
|
||||
return segundos;
|
||||
}
|
||||
|
||||
// === Task de LEDs ===
|
||||
void led_task(void *pv) {
|
||||
bool tem_creditos = false;
|
||||
while (1) {
|
||||
if (wifi_ready && tem_creditos) {
|
||||
uint16_t target = esp_random() % LED_COUNT;
|
||||
led_spin_to(target, 2, 12, 80);
|
||||
tem_creditos = false;
|
||||
} else if (wifi_ready) {
|
||||
led_idle_animation();
|
||||
} else {
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // espera Wi-Fi
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}
|
||||
|
||||
// === Callback quando Wi-Fi e IP estão prontos ===
|
||||
// ============================
|
||||
// Callback Wi-Fi pronto
|
||||
// ============================
|
||||
static void on_wifi_connected(void) {
|
||||
wifi_ready = true;
|
||||
ESP_LOGI(TAG, "✅ Wi-Fi conectado, IP obtido — iniciando MQTT e LEDs...");
|
||||
|
||||
ESP_LOGI(TAG, "✅ Wi-Fi conectado — iniciando MQTT...");
|
||||
mqtt_handler_start();
|
||||
|
||||
ESP_LOGI(TAG, "🕒 Inicializando SNTP...");
|
||||
ESP_LOGI(TAG, "🕒 SNTP...");
|
||||
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
esp_sntp_setservername(0, "pool.ntp.org");
|
||||
esp_sntp_init();
|
||||
|
||||
ESP_LOGI(TAG, "💡 Inicializando LEDs...");
|
||||
led_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);
|
||||
}
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
// ============================
|
||||
// Stack Overflow Handler
|
||||
// ============================
|
||||
void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
|
||||
{
|
||||
esp_rom_printf("\n🧨 Stack overflow em %s!\n", pcTaskName);
|
||||
// NÃO reinicia aqui — isso bloqueia o WiFi event task e causa WDT
|
||||
// apenas marca para reiniciar depois
|
||||
esp_task_wdt_reset();
|
||||
esp_task_wdt_reset();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
|
||||
// === Função principal ===
|
||||
// ============================
|
||||
// MAIN
|
||||
// ============================
|
||||
void app_main(void) {
|
||||
// ---------- EEPROM ----------
|
||||
|
||||
// -------- EEPROM virtual --------
|
||||
eeprom_virtual_init();
|
||||
|
||||
contadores_t contadores = {100, 25};
|
||||
@ -108,49 +109,32 @@ void app_main(void) {
|
||||
ESP_LOGW("EEPROM", "⚠️ Falha ao ler dados!");
|
||||
}
|
||||
|
||||
// ---------- NVS ----------
|
||||
// -------- NVS normal --------
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
|
||||
// ---------- LOG ----------
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
animacao_load();
|
||||
ESP_LOGI("ANIM", "🎨 Animação carregada = %u", animacao);
|
||||
|
||||
// ---------- SPIFFS ----------
|
||||
ESP_LOGI(TAG, "🔧 Montando SPIFFS...");
|
||||
esp_vfs_spiffs_conf_t spiffs_conf = {
|
||||
.base_path = "/spiffs",
|
||||
.partition_label = "storage",
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = true
|
||||
};
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&spiffs_conf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "❌ Falha ao montar SPIFFS (%s)", esp_err_to_name(ret));
|
||||
} else {
|
||||
size_t total = 0, used = 0;
|
||||
esp_spiffs_info(spiffs_conf.partition_label, &total, &used);
|
||||
ESP_LOGI(TAG, "📦 SPIFFS OK: total=%d bytes, usado=%d", total, used);
|
||||
}
|
||||
|
||||
// ---------- Wi-Fi ----------
|
||||
// -------- 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 encontradas no NVS: SSID=%s", cfg.sta.ssid);
|
||||
ESP_LOGI(TAG, "📂 Credenciais no NVS: SSID=%s", cfg.sta.ssid);
|
||||
have_creds = true;
|
||||
}
|
||||
}
|
||||
|
||||
wifi_config_portal_init(on_wifi_connected, have_creds);
|
||||
|
||||
// ---------- Tasks ----------
|
||||
xTaskCreate(segundos_task, "segundos_task", 12288, NULL, 5, NULL);
|
||||
xTaskCreate(led_task, "led_task", 12288, NULL, 5, NULL);
|
||||
// -------- Criar tasks iniciais --------
|
||||
xTaskCreate(segundos_task, "segundos_task", 4096, NULL, 5, NULL);
|
||||
|
||||
// ---------- Loop principal (livre) ----------
|
||||
// -------- Loop principal --------
|
||||
while (1) {
|
||||
if (wifi_ready) {
|
||||
mqtt_handler_loop(); // mantém MQTT ativo
|
||||
mqtt_handler_loop();
|
||||
}
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
@ -1,89 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "cJSON.h"
|
||||
#include "eeprom_virtual.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#include "led_driver.h"
|
||||
#include "led_effects.h"
|
||||
#include "creditos.h"
|
||||
#include "eeprom_animacao.h"
|
||||
|
||||
static const char *TAG = "MQTT_CMD";
|
||||
extern esp_mqtt_client_handle_t mqtt_client;
|
||||
|
||||
#define TOPIC_RESP "esp/esp32-002/resp"
|
||||
// Estes tópicos vêm do mqtt_handler.c
|
||||
extern char topic_resp[];
|
||||
|
||||
void mqtt_comandos_handle(cJSON *root) {
|
||||
cJSON *id = cJSON_GetObjectItem(root, "id");
|
||||
void mqtt_comandos_handle(cJSON *root)
|
||||
{
|
||||
cJSON *cmd = cJSON_GetObjectItem(root, "cmd");
|
||||
if (!cJSON_IsNumber(id) || !cJSON_IsString(cmd)) {
|
||||
ESP_LOGW(TAG, "⚠️ Comando inválido");
|
||||
if (!cJSON_IsString(cmd)) {
|
||||
ESP_LOGW(TAG, "⚠️ Comando inválido (sem 'cmd')");
|
||||
return;
|
||||
}
|
||||
|
||||
int req_id = id->valueint;
|
||||
const char *comando = cmd->valuestring;
|
||||
const char *c = cmd->valuestring;
|
||||
ESP_LOGI(TAG, "📩 CMD: %s", c);
|
||||
|
||||
// -------- FS_LIST --------
|
||||
if (strcmp(comando, "FS_LIST") == 0) {
|
||||
DIR *dir = opendir("/spiffs");
|
||||
if (!dir) {
|
||||
char resp[128];
|
||||
snprintf(resp, sizeof(resp), "{\"id\":%d,\"error\":\"fs_not_mounted\"}", req_id);
|
||||
esp_mqtt_client_publish(mqtt_client, TOPIC_RESP, resp, 0, 1, false);
|
||||
return;
|
||||
}
|
||||
|
||||
char json[2048];
|
||||
snprintf(json, sizeof(json), "{\"id\":%d,\"files\":[", req_id);
|
||||
|
||||
struct dirent *entry;
|
||||
int first = 1;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
char path[512];
|
||||
snprintf(path, sizeof(path), "/spiffs/%.255s", entry->d_name);
|
||||
struct stat st;
|
||||
if (stat(path, &st) == 0) {
|
||||
// 🔧 Correção: buffer maior e limite de nome seguro
|
||||
char file_json[320];
|
||||
snprintf(file_json, sizeof(file_json),
|
||||
"{\"name\":\"%.200s\",\"size\":%ld}", entry->d_name, (long)st.st_size);
|
||||
if (!first) strlcat(json, ",", sizeof(json));
|
||||
strlcat(json, file_json, sizeof(json));
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
strlcat(json, "]}", sizeof(json));
|
||||
esp_mqtt_client_publish(mqtt_client, TOPIC_RESP, json, 0, 1, false);
|
||||
// ======================================================
|
||||
// LED ON / OFF
|
||||
// ======================================================
|
||||
if (strcmp(c, "LED_ON") == 0) {
|
||||
led_all_on(50, 50, 50);
|
||||
}
|
||||
|
||||
// -------- CERT_REQ --------
|
||||
else if (strcmp(comando, "CERT_REQ") == 0) {
|
||||
char json[128];
|
||||
snprintf(json, sizeof(json), "{\"id\":%d,\"cmd\":\"CERT_REQ\"}", req_id);
|
||||
esp_mqtt_client_publish(mqtt_client, TOPIC_RESP, json, 0, 1, false);
|
||||
ESP_LOGI(TAG, "📤 Pedido de certificado enviado");
|
||||
else if (strcmp(c, "LED_OFF") == 0) {
|
||||
led_all_off();
|
||||
}
|
||||
|
||||
// -------- CERT_SAVE --------
|
||||
} else if (strcmp(comando, "CERT_SAVE") == 0) {
|
||||
cJSON *cert = cJSON_GetObjectItem(root, "cert");
|
||||
if (!cJSON_IsString(cert)) {
|
||||
char resp[128];
|
||||
snprintf(resp, sizeof(resp), "{\"id\":%d,\"error\":\"missing_cert\"}", req_id);
|
||||
esp_mqtt_client_publish(mqtt_client, TOPIC_RESP, resp, 0, 1, false);
|
||||
// ======================================================
|
||||
// SPIN
|
||||
// ======================================================
|
||||
else if (strcmp(c, "SPIN") == 0) {
|
||||
uint16_t p = esp_random() % led_get_count();
|
||||
led_spin_to(p, 2, 12, 80);
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// JACKPOT
|
||||
// ======================================================
|
||||
else if (strcmp(c, "JACKPOT") == 0) {
|
||||
led_jackpot_animation();
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// DAR CRÉDITO
|
||||
// ======================================================
|
||||
else if (strcmp(c, "CREDITO") == 0) {
|
||||
creditos_dar();
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// ESTADO DO SISTEMA
|
||||
// ======================================================
|
||||
else if (strcmp(c, "STATUS") == 0) {
|
||||
char resp[128];
|
||||
snprintf(resp, sizeof(resp),
|
||||
"{\"status\":\"ok\",\"heap\":%lu,\"anim\":%u}",
|
||||
(unsigned long)esp_get_free_heap_size(),
|
||||
animacao);
|
||||
|
||||
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// SET ANIMAÇÃO (NVS)
|
||||
// ======================================================
|
||||
else if (strcmp(c, "SET_ANIM") == 0) {
|
||||
cJSON *v = cJSON_GetObjectItem(root, "value");
|
||||
if (!cJSON_IsNumber(v)) {
|
||||
ESP_LOGW(TAG, "❌ SET_ANIM sem valor numérico");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *cert_str = cert->valuestring;
|
||||
uint8_t novo = v->valueint;
|
||||
animacao_save(novo); // GRAVA NA NVS
|
||||
animacao = novo; // atualiza RAM
|
||||
|
||||
// 🔧 Correção: usar versão binária (string + terminador)
|
||||
if (eeprom_virtual_write_bin("cert", cert_str, strlen(cert_str) + 1) == ESP_OK) {
|
||||
ESP_LOGI(TAG, "💾 Certificado gravado na EEPROM (%d bytes)", (int)strlen(cert_str));
|
||||
char resp[128];
|
||||
snprintf(resp, sizeof(resp), "{\"id\":%d,\"cmd\":\"CERT_SAVE\",\"ok\":true}", req_id);
|
||||
esp_mqtt_client_publish(mqtt_client, TOPIC_RESP, resp, 0, 1, false);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "❌ Falha ao gravar certificado");
|
||||
}
|
||||
ESP_LOGI(TAG, "🎨 Animação alterada para %u", novo);
|
||||
|
||||
char resp[64];
|
||||
snprintf(resp, sizeof(resp), "{\"anim\":%u}", novo);
|
||||
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// REBOOT
|
||||
// ======================================================
|
||||
else if (strcmp(c, "REBOOT") == 0) {
|
||||
|
||||
ESP_LOGW(TAG, "♻️ Reinício seguro agendado...");
|
||||
|
||||
// callback C normal
|
||||
void reboot_cb(void *arg) {
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
// criar timer
|
||||
esp_timer_handle_t reboot_timer;
|
||||
const esp_timer_create_args_t args = {
|
||||
.callback = reboot_cb,
|
||||
.arg = NULL,
|
||||
.name = "reboot_safe"
|
||||
};
|
||||
|
||||
esp_timer_create(&args, &reboot_timer);
|
||||
esp_timer_start_once(reboot_timer, 200000); // 200 ms
|
||||
|
||||
return; // evita continuar dentro do handler
|
||||
}
|
||||
|
||||
|
||||
// ======================================================
|
||||
// COMANDO DESCONHECIDO
|
||||
// ======================================================
|
||||
else {
|
||||
ESP_LOGW(TAG, "⚠️ Comando desconhecido: %s", c);
|
||||
|
||||
char resp[128];
|
||||
snprintf(resp, sizeof(resp),
|
||||
"{\"error\":\"unknown_cmd\",\"cmd\":\"%s\"}", c);
|
||||
|
||||
esp_mqtt_client_publish(mqtt_client, topic_resp, resp, 0, 1, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
static const char *TAG = "MQTT";
|
||||
|
||||
// -------- CONFIG --------
|
||||
#define BROKER_HOST "mtqq.xupas.mywire.org"
|
||||
#define BROKER_HOST "mqtt.xupas.mywire.org"
|
||||
#define BROKER_PORT_TLS 8883
|
||||
#define BROKER_PORT_TCP 1883
|
||||
#define MQTT_USER "xupa"
|
||||
@ -26,10 +26,10 @@ esp_mqtt_client_handle_t mqtt_client = NULL;
|
||||
static esp_timer_handle_t mqtt_watchdog = NULL;
|
||||
static bool mqtt_connected = false;
|
||||
|
||||
static char topic_status[64];
|
||||
static char topic_cmd[64];
|
||||
static char topic_resp[64];
|
||||
static char topic_lwt[64];
|
||||
char topic_status[64];
|
||||
char topic_cmd[64];
|
||||
char topic_resp[64];
|
||||
char topic_lwt[64];
|
||||
|
||||
// ======================================================
|
||||
// HEARTBEAT / STATUS
|
||||
@ -67,8 +67,11 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
mqtt_connected = true;
|
||||
led_set(0, 0, 50, 0);
|
||||
|
||||
// LED verde no pixel 0
|
||||
led_set_pixel(0, 0, 50, 0);
|
||||
led_show();
|
||||
|
||||
ESP_LOGI(TAG, "✅ MQTT conectado");
|
||||
esp_mqtt_client_publish(mqtt_client, topic_status, "online", 0, 1, true);
|
||||
esp_mqtt_client_subscribe(mqtt_client, topic_cmd, 1);
|
||||
@ -79,26 +82,46 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
|
||||
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
mqtt_connected = false;
|
||||
led_set(0, 50, 0, 0);
|
||||
|
||||
// LED vermelho no pixel 0
|
||||
led_set_pixel(0, 50, 0, 0);
|
||||
led_show();
|
||||
|
||||
ESP_LOGW(TAG, "⚠️ MQTT desconectado");
|
||||
if (mqtt_watchdog) esp_timer_start_periodic(mqtt_watchdog, 120000000);
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_DATA: {
|
||||
ESP_LOGI(TAG, "📩 [%.*s] %.*s",
|
||||
event->topic_len, event->topic,
|
||||
event->data_len, event->data);
|
||||
// Copia o payload para um buffer legível
|
||||
char json_clean[256];
|
||||
int len = event->data_len;
|
||||
|
||||
if (len >= sizeof(json_clean)) len = sizeof(json_clean) - 1;
|
||||
memcpy(json_clean, event->data, len);
|
||||
json_clean[len] = 0; // NULL terminate
|
||||
|
||||
// Remove quebras de linha
|
||||
for (int i = 0; json_clean[i]; i++) {
|
||||
if (json_clean[i] == '\r' || json_clean[i] == '\n')
|
||||
json_clean[i] = ' ';
|
||||
}
|
||||
|
||||
// Mostrar tópico + JSON limpo
|
||||
ESP_LOGI(TAG, "📩 [%.*s] %s",
|
||||
event->topic_len, event->topic,
|
||||
json_clean);
|
||||
|
||||
// JSON parse
|
||||
cJSON *root = cJSON_Parse(json_clean);
|
||||
if (root) {
|
||||
mqtt_comandos_handle(root);
|
||||
cJSON_Delete(root);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "❌ JSON inválido");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cJSON *root = cJSON_ParseWithLength(event->data, event->data_len);
|
||||
if (root) {
|
||||
mqtt_comandos_handle(root);
|
||||
cJSON_Delete(root);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "❌ JSON inválido");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGE(TAG, "❌ Erro MQTT");
|
||||
@ -109,6 +132,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ======================================================
|
||||
// HEARTBEAT TASK
|
||||
// ======================================================
|
||||
@ -143,65 +167,40 @@ void mqtt_handler_start(void) {
|
||||
mqtt_cfg.credentials.client_id = device_id;
|
||||
mqtt_cfg.credentials.username = MQTT_USER;
|
||||
mqtt_cfg.credentials.authentication.password = MQTT_PASS;
|
||||
// ======================================================
|
||||
// MQTT TLS — usa SEMPRE o certificado embutido
|
||||
// ======================================================
|
||||
mqtt_cfg.broker.address.hostname = BROKER_HOST;
|
||||
mqtt_cfg.broker.address.port = BROKER_PORT_TLS;
|
||||
mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_SSL;
|
||||
|
||||
// ======================================================
|
||||
// TENTA CARREGAR CERTIFICADO E USAR TLS
|
||||
// ======================================================
|
||||
bool tls_ok = false;
|
||||
static char cert_buf[4096];
|
||||
size_t cert_len = sizeof(cert_buf) - 1;
|
||||
// Certificado raiz (ISRG Root X1)
|
||||
mqtt_cfg.broker.verification.certificate = ca_cert_pem;
|
||||
ESP_LOGI(TAG, "🔐 TLS ativo (cert embutido, EEPROM ignorada)");
|
||||
|
||||
if (eeprom_virtual_read_bin("cert", cert_buf, &cert_len) == ESP_OK && cert_len > 0) {
|
||||
cert_buf[cert_len] = '\0';
|
||||
mqtt_cfg.broker.verification.certificate = strdup(cert_buf);
|
||||
mqtt_cfg.broker.address.hostname = BROKER_HOST;
|
||||
mqtt_cfg.broker.address.port = BROKER_PORT_TLS;
|
||||
mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_SSL;
|
||||
tls_ok = true;
|
||||
ESP_LOGI(TAG, "🔐 Certificado TLS carregado da EEPROM (%d bytes)", (int)cert_len);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "⚠️ Certificado TLS não encontrado — vai tentar padrão embutido...");
|
||||
mqtt_cfg.broker.verification.certificate = (const char *)ca_cert_pem;
|
||||
mqtt_cfg.broker.address.hostname = BROKER_HOST;
|
||||
mqtt_cfg.broker.address.port = BROKER_PORT_TLS;
|
||||
mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_SSL;
|
||||
tls_ok = true;
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// TESTE: se TLS falhar, cai para TCP (sem SSL)
|
||||
// ======================================================
|
||||
if (!tls_ok) {
|
||||
ESP_LOGW(TAG, "⚠️ TLS indisponível — a usar MQTT sem SSL.");
|
||||
mqtt_cfg.broker.address.hostname = BROKER_HOST;
|
||||
mqtt_cfg.broker.address.port = BROKER_PORT_TCP;
|
||||
mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_TCP;
|
||||
}
|
||||
|
||||
// -------- LWT --------
|
||||
// -------- LWT --------
|
||||
mqtt_cfg.session.last_will.topic = topic_lwt;
|
||||
mqtt_cfg.session.last_will.msg = "offline";
|
||||
mqtt_cfg.session.last_will.qos = 1;
|
||||
mqtt_cfg.session.last_will.retain = true;
|
||||
|
||||
// ======================================================
|
||||
// INICIALIZAÇÃO DO CLIENTE
|
||||
// ======================================================
|
||||
// ======================================================
|
||||
// INICIALIZAÇÃO DO CLIENTE MQTT (TLS OBRIGATÓRIO)
|
||||
// ======================================================
|
||||
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
if (mqtt_client == NULL) {
|
||||
ESP_LOGE(TAG, "❌ Falha a inicializar MQTT — a tentar fallback TCP...");
|
||||
mqtt_cfg.broker.address.transport = MQTT_TRANSPORT_OVER_TCP;
|
||||
mqtt_cfg.broker.address.port = BROKER_PORT_TCP;
|
||||
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
}
|
||||
ESP_LOGE(TAG, "❌ Falha a inicializar MQTT (TLS). Abortado.");
|
||||
return; // Nem vale a pena continuar, sem MQTT não há vida
|
||||
}
|
||||
|
||||
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_start(mqtt_client);
|
||||
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
|
||||
esp_mqtt_client_start(mqtt_client);
|
||||
|
||||
ESP_LOGI(TAG, "🚀 MQTT inicializado em %s:%lu (%s)",
|
||||
ESP_LOGI(TAG, "🚀 MQTT inicializado em %s:%lu (TLS)",
|
||||
mqtt_cfg.broker.address.hostname,
|
||||
(unsigned long)mqtt_cfg.broker.address.port,
|
||||
mqtt_cfg.broker.address.transport == MQTT_TRANSPORT_OVER_SSL ? "TLS" : "TCP");
|
||||
(unsigned long)mqtt_cfg.broker.address.port);
|
||||
|
||||
|
||||
|
||||
// -------- WATCHDOG MQTT --------
|
||||
const esp_timer_create_args_t wd_args = {
|
||||
|
||||
12
sdkconfig
12
sdkconfig
@ -317,14 +317,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
||||
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
||||
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
||||
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
|
||||
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
||||
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
||||
@ -338,12 +338,12 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||
#
|
||||
# Partition Table
|
||||
#
|
||||
# CONFIG_PARTITION_TABLE_SINGLE_APP is not set
|
||||
CONFIG_PARTITION_TABLE_SINGLE_APP=y
|
||||
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
|
||||
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
# CONFIG_PARTITION_TABLE_CUSTOM is not set
|
||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||
CONFIG_PARTITION_TABLE_MD5=y
|
||||
# end of Partition Table
|
||||
|
||||
1858
sdkconfig.old
1858
sdkconfig.old
File diff suppressed because it is too large
Load Diff
@ -10,8 +10,8 @@
|
||||
"board/esp32-wrover-kit-3.3v.cfg"
|
||||
],
|
||||
"idf.port": "COM3",
|
||||
"idf.flashBaudRate": 921600,
|
||||
"idf.monitorBaudRate": 115200,
|
||||
"idf.flashBaudRate": "921600",
|
||||
"idf.monitorBaudRate": "115200",
|
||||
"cmake.sourceDirectory": "${workspaceFolder}"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user