2026-06-24 23:13:57 +02:00

153 lines
4.3 KiB
C

#include <stdio.h>
#include <string.h>
#include "bme680.h"
#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "i2cdev.h"
#include "sdkconfig.h"
#include "wifi_mqtt.h"
#define BME680_I2C_PORT I2C_NUM_0
#define BME680_SDA_GPIO GPIO_NUM_21
#define BME680_SCL_GPIO GPIO_NUM_22
#define BME680_ADDR BME680_I2C_ADDR_0
#define BME680_I2C_CLOCK_HZ 100000
#define BME680_INIT_RETRY_MS 2000
#define BME680_READ_INTERVAL_MS 3000
static const char *TAG = "bme680-demo";
static esp_err_t init_i2c_subsystem(void)
{
esp_err_t err;
do {
err = i2cdev_init();
if (err != ESP_OK) {
ESP_LOGE(TAG, "I2C subsystem init failed: %s. Retrying in %d ms",
esp_err_to_name(err), BME680_INIT_RETRY_MS);
vTaskDelay(pdMS_TO_TICKS(BME680_INIT_RETRY_MS));
}
} while (err != ESP_OK);
return ESP_OK;
}
static esp_err_t init_sensor(bme680_t *sensor)
{
memset(sensor, 0, sizeof(*sensor));
esp_err_t err = bme680_init_desc(sensor, BME680_ADDR, BME680_I2C_PORT,
BME680_SDA_GPIO, BME680_SCL_GPIO);
if (err != ESP_OK) {
return err;
}
sensor->i2c_dev.cfg.master.clk_speed = BME680_I2C_CLOCK_HZ;
err = bme680_init_sensor(sensor);
if (err != ESP_OK) {
bme680_free_desc(sensor);
return err;
}
err = bme680_set_ambient_temperature(sensor, 25);
if (err != ESP_OK) {
bme680_free_desc(sensor);
return err;
}
return ESP_OK;
}
static void wait_for_sensor(bme680_t *sensor)
{
esp_err_t err;
do {
err = init_sensor(sensor);
if (err != ESP_OK) {
ESP_LOGE(TAG,
"BME680 init failed on SDA=%d SCL=%d addr=0x%02x: %s. Retrying in %d ms",
BME680_SDA_GPIO,
BME680_SCL_GPIO,
BME680_ADDR,
esp_err_to_name(err),
BME680_INIT_RETRY_MS);
vTaskDelay(pdMS_TO_TICKS(BME680_INIT_RETRY_MS));
}
} while (err != ESP_OK);
ESP_LOGI(TAG,
"Sensor initialized on I2C port %d, SDA=%d, SCL=%d, address=0x%02x",
BME680_I2C_PORT,
BME680_SDA_GPIO,
BME680_SCL_GPIO,
BME680_ADDR);
}
static esp_err_t publish_reading(const bme680_values_float_t *values, uint32_t uptime_s)
{
char topic[128];
char payload[256];
snprintf(topic, sizeof(topic), "%s/%s/%s/telemetry",
CONFIG_BME680_TOPIC_PREFIX,
CONFIG_BME680_ROOM,
CONFIG_BME680_DEVICE_ID);
int written = snprintf(payload, sizeof(payload),
"{\"device_id\":\"%s\",\"room\":\"%s\",\"temperature\":%.2f,\"humidity\":%.2f,\"pressure\":%.2f,\"gas_resistance\":%.0f,\"uptime_s\":%lu}",
CONFIG_BME680_DEVICE_ID,
CONFIG_BME680_ROOM,
values->temperature,
values->humidity,
values->pressure,
values->gas_resistance,
(unsigned long)uptime_s);
if (written < 0 || written >= (int)sizeof(payload)) {
return ESP_ERR_INVALID_SIZE;
}
return wifi_mqtt_publish(topic, payload);
}
void app_main(void)
{
bme680_t sensor;
uint32_t uptime_s = 0;
ESP_ERROR_CHECK(wifi_mqtt_start());
init_i2c_subsystem();
wait_for_sensor(&sensor);
while (1) {
bme680_values_float_t values;
esp_err_t err = bme680_measure_float(&sensor, &values);
if (err == ESP_OK) {
ESP_LOGI(TAG,
"Temp: %.2f C Humidity: %.2f %% Pressure: %.2f hPa Gas: %.0f ohm",
values.temperature,
values.humidity,
values.pressure,
values.gas_resistance);
err = publish_reading(&values, uptime_s);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Telemetry publish skipped or failed: %s", esp_err_to_name(err));
}
} else {
ESP_LOGE(TAG, "BME680 read failed: %s", esp_err_to_name(err));
}
uptime_s += BME680_READ_INTERVAL_MS / 1000;
vTaskDelay(pdMS_TO_TICKS(BME680_READ_INTERVAL_MS));
}
}