from machine import ADC, Pin
import time
# 配置引脚 - 可根据实际连接修改
MQ2_ANALOG_PIN = 34 # 模拟输入引脚
MQ2_DIGITAL_PIN = 2 # 数字输入引脚(如果使用数字输出)
LED_ALARM_PIN = 13 # 报警LED输出引脚
# 初始化传感器和外设
mq2_analog = ADC(Pin(MQ2_ANALOG_PIN))
mq2_digital = Pin(MQ2_DIGITAL_PIN, Pin.IN)
led_alarm = Pin(LED_ALARM_PIN, Pin.OUT)
# 设置ADC参数(ESP32特定)
mq2_analog.atten(ADC.ATTN_11DB) # 配置为3.3V范围
mq2_analog.width(ADC.WIDTH_12BIT) # 12位分辨率(0-4095)
# 校准参数 - 建议实际环境中校准
RL_VALUE = 5 # 负载电阻值(kΩ)
RO_CLEAN_AIR_FACTOR = 9.83 # MQ-2在洁净空气中的Ro值
# 气体类型常量
GAS_LPG = 0
GAS_CO = 1
GAS_SMOKE = 2
# 曲线系数 - 根据传感器datasheet
class Curve:
def __init__(self, a, b):
self.a = a # 斜率
self.b = b # Y轴截距
# 不同气体的曲线参数
CURVES = {
GAS_LPG: Curve(-0.45, 2.95),
GAS_CO: Curve(-0.38, 3.21),
GAS_SMOKE: Curve(-0.42, 3.54)
}
# 报警阈值(ppm)
ALARM_THRESHOLDS = {
GAS_LPG: 1000,
GAS_CO: 50,
GAS_SMOKE: 500
}
def calibrate_ro_in_clean_air(samples=10, delay=1):
"""在洁净空气中校准Ro值"""
print("开始洁净空气校准,请确保环境空气清新...")
total = 0
for i in range(samples):
adc_value = mq2_analog.read()
voltage = adc_value * (3.3 / 4095)
rs_value = ((3.3 / voltage) - 1) * RL_VALUE
total += rs_value
print(f"采样 {i+1}/{samples}: Rs = {rs_value:.2f} kΩ")
time.sleep(delay)
average_rs = total / samples
ro_value = average_rs / RO_CLEAN_AIR_FACTOR
print(f"校准完成! Ro = {ro_value:.2f} kΩ")
return ro_value
def get_correction_factor(temperature, humidity):
"""根据环境温湿度修正读数"""
# 此函数基于传感器特性曲线,需根据实际传感器调整
if temperature < 20:
return 0.98
elif temperature < 30:
return 1.0
else:
return 1.02
def get_rs_ro_ratio(rs_value, ro_value):
"""计算RS/RO比值"""
return rs_value / ro_value
def get_gas_ppm(rs_ro_ratio, gas_type):
"""根据RS/RO比值和气体类型计算浓度(ppm)"""
curve = CURVES[gas_type]
return 10 ** ((rs_ro_ratio - curve.b) / curve.a)
def read_mq2(ro_value):
"""读取MQ2传感器数据"""
# 读取模拟值
adc_value = mq2_analog.read()
# 转换为电压
voltage = adc_value * (3.3 / 4095)
# 计算RS值(传感器电阻)
rs_value = ((3.3 / voltage) - 1) * RL_VALUE
# 应用温湿度修正(实际应用中应从DHT传感器读取)
temperature = 25 # 示例值
humidity = 60 # 示例值
correction_factor = get_correction_factor(temperature, humidity)
rs_corrected = rs_value / correction_factor
# 计算不同气体浓度
rs_ro_ratio = get_rs_ro_ratio(rs_corrected, ro_value)
lpg_ppm = get_gas_ppm(rs_ro_ratio, GAS_LPG)
co_ppm = get_gas_ppm(rs_ro_ratio, GAS_CO)
smoke_ppm = get_gas_ppm(rs_ro_ratio, GAS_SMOKE)
# 读取数字输出
digital_value = mq2_digital.value()
return {
"adc_value": adc_value,
"voltage": voltage,
"rs_value": rs_value,
"digital_value": digital_value,
"temperature": temperature,
"humidity": humidity,
"gas_concentrations": {
"lpg": lpg_ppm,
"co": co_ppm,
"smoke": smoke_ppm
}
}
def check_alarms(results):
"""检查是否触发任何报警"""
alarms = []
for gas_type, ppm in results["gas_concentrations"].items():
gas_name = {GAS_LPG: "LPG", GAS_CO: "CO", GAS_SMOKE: "烟雾"}.get(gas_type, "未知气体")
threshold = ALARM_THRESHOLDS.get(gas_type, float('inf'))
if ppm > threshold:
alarms.append(f"{gas_name}浓度过高: {ppm:.2f} ppm")
return alarms
# 主程序
try:
print("MQ-2传感器测试程序启动...")
# 校准Ro值(首次使用或环境变化时建议运行)
# ro_value = calibrate_ro_in_clean_air()
# 或者使用预设值
ro_value = 10.0 # 根据实际校准结果修改
print("传感器预热中,请等待...")
time.sleep(20) # MQ-2传感器需要预热时间
while True:
result = read_mq2(ro_value)
# 打印结果
print("\n===== MQ-2传感器读数 =====")
print(f"ADC值: {result['adc_value']}")
print(f"电压值: {result['voltage']:.2f}V")
print(f"传感器电阻(Rs): {result['rs_value']:.2f} kΩ")
print(f"数字输出: {'有烟雾' if result['digital_value'] else '无烟雾'}")
# 打印气体浓度
print("\n气体浓度:")
for gas_type, ppm in result["gas_concentrations"].items():
gas_name = {GAS_LPG: "LPG", GAS_CO: "CO", GAS_SMOKE: "烟雾"}.get(gas_type, "未知气体")
print(f" {gas_name}: {ppm:.2f} ppm")
# 检查报警
alarms = check_alarms(result)
if alarms:
print("\n⚠️ 警告:")
for alarm in alarms:
print(f"- {alarm}")
led_alarm.on() # 触发报警LED
else:
led_alarm.off() # 关闭报警LED
time.sleep(1) # 每秒读取一次
except KeyboardInterrupt:
print("\n程序已停止")
finally:
led_alarm.off() # 确保程序退出时LED关闭