153 lines
4.3 KiB
C
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));
|
|
}
|
|
}
|