添加 MQ-2 传感器支持,初始化 ADC 通道并读取气体浓度
This commit is contained in:
3
components/MQ-2/CMakeLists.txt
Normal file
3
components/MQ-2/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
idf_component_register(SRCS "MQ-2.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES esp_adc)
|
||||||
67
components/MQ-2/MQ-2.c
Normal file
67
components/MQ-2/MQ-2.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include "MQ-2.h"
|
||||||
|
|
||||||
|
#include "esp_adc/adc_oneshot.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
|
||||||
|
#define MQ2_ADC_UNIT ADC_UNIT_1
|
||||||
|
#define MQ2_ADC_CHANNEL ADC_CHANNEL_7
|
||||||
|
#define MQ2_SAMPLE_COUNT 8
|
||||||
|
|
||||||
|
static const char *TAG = "MQ2";
|
||||||
|
static adc_oneshot_unit_handle_t s_adc_handle = NULL;
|
||||||
|
static bool s_inited = false;
|
||||||
|
|
||||||
|
esp_err_t mq2_init(void)
|
||||||
|
{
|
||||||
|
if (s_inited) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_oneshot_unit_init_cfg_t init_cfg = {
|
||||||
|
.unit_id = MQ2_ADC_UNIT,
|
||||||
|
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||||
|
};
|
||||||
|
ESP_RETURN_ON_ERROR(adc_oneshot_new_unit(&init_cfg, &s_adc_handle), TAG, "adc new unit failed");
|
||||||
|
|
||||||
|
adc_oneshot_chan_cfg_t chan_cfg = {
|
||||||
|
.atten = ADC_ATTEN_DB_12,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
ESP_RETURN_ON_ERROR(adc_oneshot_config_channel(s_adc_handle, MQ2_ADC_CHANNEL, &chan_cfg),
|
||||||
|
TAG, "adc channel config failed");
|
||||||
|
|
||||||
|
s_inited = true;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t mq2_read_raw(int *raw_out)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(raw_out != NULL, ESP_ERR_INVALID_ARG, TAG, "raw_out is null");
|
||||||
|
ESP_RETURN_ON_FALSE(s_inited, ESP_ERR_INVALID_STATE, TAG, "mq2 not inited");
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
for (int i = 0; i < MQ2_SAMPLE_COUNT; ++i) {
|
||||||
|
int sample = 0;
|
||||||
|
ESP_RETURN_ON_ERROR(adc_oneshot_read(s_adc_handle, MQ2_ADC_CHANNEL, &sample),
|
||||||
|
TAG, "adc read failed");
|
||||||
|
sum += sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
*raw_out = sum / MQ2_SAMPLE_COUNT;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t mq2_read_percent(float *percent_out)
|
||||||
|
{
|
||||||
|
ESP_RETURN_ON_FALSE(percent_out != NULL, ESP_ERR_INVALID_ARG, TAG, "percent_out is null");
|
||||||
|
|
||||||
|
int raw = 0;
|
||||||
|
ESP_RETURN_ON_ERROR(mq2_read_raw(&raw), TAG, "read raw failed");
|
||||||
|
*percent_out = (raw * 100.0f) / 4095.0f;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mq2_is_alarm(float percent, float threshold_percent)
|
||||||
|
{
|
||||||
|
return percent >= threshold_percent;
|
||||||
|
}
|
||||||
37
components/MQ-2/include/MQ-2.h
Normal file
37
components/MQ-2/include/MQ-2.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ESP32-S3: GPIO8 -> ADC1_CHANNEL_7
|
||||||
|
#define MQ2_ADC_GPIO 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化 MQ-2 ADC 通道
|
||||||
|
*/
|
||||||
|
esp_err_t mq2_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取 MQ-2 原始 ADC 值(0~4095)
|
||||||
|
*/
|
||||||
|
esp_err_t mq2_read_raw(int *raw_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 读取 MQ-2 归一化百分比(0~100)
|
||||||
|
*/
|
||||||
|
esp_err_t mq2_read_percent(float *percent_out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 根据阈值判断是否疑似有害气体/烟雾超标
|
||||||
|
*/
|
||||||
|
bool mq2_is_alarm(float percent, float threshold_percent);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
idf_component_register(SRCS "main.cpp"
|
idf_component_register(SRCS "main.cpp"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES nvs_flash esp_wifi sntp_time aht30 esp_event esp_system wifi-connect ui lvgl_st7789_use efuse relay_ctrl bh1750)
|
REQUIRES nvs_flash esp_wifi sntp_time aht30 esp_event esp_system wifi-connect ui lvgl_st7789_use efuse relay_ctrl bh1750 MQ-2)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "esp_efuse_table.h"
|
#include "esp_efuse_table.h"
|
||||||
#include "bh1750_use.h"
|
#include "bh1750_use.h"
|
||||||
#include "aht30.h"
|
#include "aht30.h"
|
||||||
|
#include "MQ-2.h"
|
||||||
|
|
||||||
#define TAG "MAIN"
|
#define TAG "MAIN"
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ typedef struct
|
|||||||
float lux;
|
float lux;
|
||||||
float temp;
|
float temp;
|
||||||
float humidity;
|
float humidity;
|
||||||
|
float gas_percent;
|
||||||
} env_data_t;
|
} env_data_t;
|
||||||
|
|
||||||
static env_data_t s_env_data;
|
static env_data_t s_env_data;
|
||||||
@@ -109,12 +111,15 @@ extern "C" void app_main(void)
|
|||||||
aht30_handle_t aht30_dev = NULL;
|
aht30_handle_t aht30_dev = NULL;
|
||||||
ESP_ERROR_CHECK(aht30_create(i2c_bus, AHT30_I2C_ADDRESS, &aht30_dev));
|
ESP_ERROR_CHECK(aht30_create(i2c_bus, AHT30_I2C_ADDRESS, &aht30_dev));
|
||||||
|
|
||||||
|
// MQ-2 使用 ADC(GPIO8)
|
||||||
|
ESP_ERROR_CHECK(mq2_init());
|
||||||
|
|
||||||
// 6. 创建传感器读取任务
|
// 6. 创建传感器读取任务
|
||||||
xTaskCreate([](void *arg)
|
xTaskCreate([](void *arg)
|
||||||
{
|
{
|
||||||
aht30_handle_t aht30 = (aht30_handle_t)arg;
|
aht30_handle_t aht30 = (aht30_handle_t)arg;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
float lux = 0.0f, temp = 0.0f, hum = 0.0f;
|
float lux = 0.0f, temp = 0.0f, hum = 0.0f, gas_percent = 0.0f;
|
||||||
// 读取 BH1750
|
// 读取 BH1750
|
||||||
if (bh1750_user_read(&lux) == ESP_OK) {
|
if (bh1750_user_read(&lux) == ESP_OK) {
|
||||||
set_var_light_val(lux);
|
set_var_light_val(lux);
|
||||||
@@ -124,6 +129,17 @@ extern "C" void app_main(void)
|
|||||||
set_var_temp(temp);
|
set_var_temp(temp);
|
||||||
set_var_humity_val(hum);
|
set_var_humity_val(hum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 读取 MQ-2,更新空气质量变量
|
||||||
|
if (mq2_read_percent(&gas_percent) == ESP_OK) {
|
||||||
|
set_var_air_quity(gas_percent);
|
||||||
|
|
||||||
|
if (s_env_data_lock) {
|
||||||
|
xSemaphoreTake(s_env_data_lock, portMAX_DELAY);
|
||||||
|
s_env_data.gas_percent = gas_percent;
|
||||||
|
xSemaphoreGive(s_env_data_lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 数据存入共享结构体
|
// 数据存入共享结构体
|
||||||
|
|||||||
Reference in New Issue
Block a user