feat: update codigo local (display, buzzer, net_weather)

This commit is contained in:
XupaMisto 2026-01-28 20:50:35 +00:00
parent 87afe944bc
commit a26b421d75
10 changed files with 215 additions and 5 deletions

View File

@ -16,6 +16,8 @@ idf_component_register(
"i2c_helper.c"
"display.c"
"ui.c"
"net_weather.c"
"buzzer.c"
INCLUDE_DIRS
"include"
@ -28,5 +30,6 @@ idf_component_register(
json
driver
esp_http_server
esp_http_client
)

26
main/buzzer.c Normal file
View File

@ -0,0 +1,26 @@
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_rom_sys.h"
#define BUZ_GPIO GPIO_NUM_19
void buzzer_init(void)
{
gpio_reset_pin(BUZ_GPIO);
gpio_set_direction(BUZ_GPIO, GPIO_MODE_OUTPUT);
}
void buzzer_beep(uint32_t ms)
{
const int period_us = 500; // ~2 kHz
int cycles = (ms * 1000) / period_us;
for (int i = 0; i < cycles; i++) {
gpio_set_level(BUZ_GPIO, 1);
esp_rom_delay_us(period_us / 2);
gpio_set_level(BUZ_GPIO, 0);
esp_rom_delay_us(period_us / 2);
}
}

View File

@ -25,6 +25,7 @@ static const char *TAG = "DISPLAY";
// FLAG GLOBAL
// =======================================================
static bool s_display_enabled = false;
void display_temperature_bottom(float temp);
void display_set_enabled(bool en) { s_display_enabled = en; }
bool display_is_enabled(void) { return s_display_enabled; }
@ -376,3 +377,48 @@ void display_debug_segment(uint16_t bitmask)
// if (!display_is_enabled()) return;
// display_raw_top(0, bitmask);
}
// =======================================================
// TEMPERATURA (BOTTOM) ex: 23.5
// =======================================================
void display_temperature_bottom(float temp)
{
if (!s_display_enabled) return;
// limites práticos
if (temp > 99.9f) temp = 99.9f;
if (temp < -9.9f) temp = -9.9f;
bool neg = false;
if (temp < 0) {
neg = true;
temp = -temp;
}
int inteiro = (int)temp;
int decimal = (int)((temp - inteiro) * 10 + 0.5f);
display_clear_bottom();
if (neg) {
// formato: C-5.2 (raro, mas pronto)
display_char_bottom(0, 'C');
display_raw_bottom(1, SEG_G); // '-'
display_raw_bottom(2, digit_mask[inteiro] | SEG_DP);
display_digit_bottom(3, decimal);
} else {
if (inteiro >= 10) {
// formato: C13.8
display_char_bottom(0, 'C');
display_digit_bottom(1, inteiro / 10);
display_raw_bottom(2, digit_mask[inteiro % 10] | SEG_DP);
display_digit_bottom(3, decimal);
} else {
// formato: C 7.2
display_char_bottom(0, 'C');
display_raw_bottom(1, 0);
display_raw_bottom(2, digit_mask[inteiro] | SEG_DP);
display_digit_bottom(3, decimal);
}
}
}

8
main/include/buzzer.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
// inicializa o buzzer (PWM / GPIO19)
void buzzer_init(void);
// bip simples em milissegundos
void buzzer_beep(uint32_t ms);

View File

@ -45,6 +45,7 @@ void display_number_bottom(int num);
// RELÓGIO (HH:MM com DP entre horas)
// =======================================================
void display_set_time_top(int horas, int minutos);
void display_temperature_bottom(float temp);
// =======================================================
// DEBUG

View File

@ -0,0 +1,4 @@
#pragma once
#include <stdbool.h>
bool net_weather_update(float *out_temp);

View File

@ -32,6 +32,11 @@
#include "display.h"
#include <stdbool.h>
#include "net_weather.h"
#include "buzzer.h"
esp_err_t i2c_init(void);
esp_err_t display_init(void);
@ -53,6 +58,37 @@ typedef struct {
} contadores_t;
static void weather_task(void *arg)
{
float temp;
ESP_LOGI("WEATHER", "🌡️ weather_task arrancou");
// 🔥 leitura IMEDIATA (antes do delay)
ESP_LOGI("WEATHER", "🌐 a pedir temperatura (primeira vez)");
if (net_weather_update(&temp)) {
ESP_LOGI("WEATHER", "🌡️ temperatura recebida: %.1f", temp);
display_temperature_bottom(temp);
} else {
ESP_LOGE("WEATHER", "❌ net_weather_update falhou");
}
while (1) {
vTaskDelay(pdMS_TO_TICKS(15 * 60 * 1000));
ESP_LOGI("WEATHER", "🌐 a pedir temperatura (loop)");
if (net_weather_update(&temp)) {
ESP_LOGI("WEATHER", "🌡️ temperatura recebida: %.1f", temp);
display_temperature_bottom(temp);
} else {
ESP_LOGE("WEATHER", "❌ net_weather_update falhou");
}
}
}
// ============================
// Task contador simples
// ============================
@ -88,6 +124,10 @@ static void on_wifi_connected(void) {
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);
// 🌡️ TASK DO TEMPO (AQUI!)
ESP_LOGI(TAG, "🌡️ Iniciando task de temperatura (Open-Meteo)");
xTaskCreate(weather_task, "weather_task", 4096, NULL, 4, NULL);
}
@ -218,7 +258,9 @@ void app_main(void) {
// 4) Teste simples no display (se existir)
display_text_top("INIT");
// 🔔 6) buzzer (AQUI!)
buzzer_init();
buzzer_beep(500);
// -------- Wi-Fi --------

80
main/net_weather.c Normal file
View File

@ -0,0 +1,80 @@
#include "esp_http_client.h"
#include "esp_log.h"
#include <string.h>
#include <stdlib.h>
#include "buzzer.h"
static const char *TAG = "WEATHER";
static bool parse_temperature_from_json(const char *json, float *out_temp)
{
if (!json || !out_temp) return false;
// 1) ir para o bloco "current"
const char *p = strstr(json, "\"current\"");
if (!p) return false;
// 2) procurar temperature_2m DENTRO de current
p = strstr(p, "\"temperature_2m\"");
if (!p) return false;
// 3) ir para o valor
p = strchr(p, ':');
if (!p) return false;
*out_temp = strtof(p + 1, NULL);
return true;
}
bool net_weather_update(float *out_temp)
{
char buf[512];
esp_http_client_config_t cfg = {
.url = "http://api.open-meteo.com/v1/forecast?latitude=38.75&longitude=-9.125&current=temperature_2m",
.method = HTTP_METHOD_GET,
.transport_type = HTTP_TRANSPORT_OVER_TCP,
.timeout_ms = 10000,
.user_agent = "esp32-weather",
};
ESP_LOGI(TAG, "➡️ HTTP init");
esp_http_client_handle_t client = esp_http_client_init(&cfg);
if (!client) {
ESP_LOGE(TAG, "❌ http_client_init falhou");
return false;
}
esp_err_t err = esp_http_client_open(client, 0);
if (err != ESP_OK) {
ESP_LOGE(TAG, "❌ http_client_open falhou: %s", esp_err_to_name(err));
esp_http_client_cleanup(client);
return false;
}
int content_length = esp_http_client_fetch_headers(client);
ESP_LOGI(TAG, "📦 content-length = %d", content_length);
int len = esp_http_client_read(client, buf, sizeof(buf) - 1);
if (len <= 0) {
ESP_LOGE(TAG, "❌ http_client_read falhou");
esp_http_client_close(client);
esp_http_client_cleanup(client);
return false;
}
buf[len] = 0;
ESP_LOGI(TAG, "📩 JSON: %s", buf);
esp_http_client_close(client);
esp_http_client_cleanup(client);
if (!parse_temperature_from_json(buf, out_temp)) {
ESP_LOGE(TAG, "❌ parse_temperature_from_json falhou");
return false;
}
return true;
}

View File

@ -602,7 +602,7 @@ CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y
# ESP HTTP client
#
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set
CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH=y
# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set
# end of ESP HTTP client

View File

@ -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=y
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# 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="2MB"
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set