火焰传感器(4针) 双模式检测与中断触发代码例程

知识库
知识库文档
/firmware/传感器/火焰传感器-4针/火焰传感器(4针) 双模式检测与中断触发代码例程.md

文档

火焰传感器(4针) 双模式检测与中断触发代码例程

一、Arduino - AO+DO双路读取

// 4针火焰传感器 - 模拟量+数字量双模式
#define FLAME_AO_PIN    A0      // 模拟量
#define FLAME_DO_PIN    2       // 数字量
#define BUZZER_PIN      5

void setup() {
    Serial.begin(115200);
    pinMode(FLAME_DO_PIN, INPUT);
    pinMode(BUZZER_PIN, OUTPUT);
    
    Serial.println("4针火焰传感器检测系统启动");
    Serial.println("AO=火焰强度, DO=0表示检测到火焰");
}

void loop() {
    int analogVal = analogRead(FLAME_AO_PIN);
    bool flameDetected = !digitalRead(FLAME_DO_PIN);  // DO低电平有效
    
    float voltage = (analogVal / 1024.0) * 5.0;
    
    Serial.print("AO: "); Serial.print(analogVal);
    Serial.print(" ("); Serial.print(voltage, 3); Serial.print("V)");
    Serial.print(" | DO: "); Serial.print(flameDetected ? "🔥火焰!" : "正常");
    
    if (flameDetected) {
        Serial.print(" | 火焰强度: ");
        // 根据AO值判断火焰强度等级
        if (analogVal > 800)       Serial.print("极强");
        else if (analogVal > 600)  Serial.print("强");
        else if (analogVal > 400)  Serial.print("中");
        else                       Serial.print("弱");
        
        digitalWrite(BUZZER_PIN, HIGH);
    } else {
        digitalWrite(BUZZER_PIN, LOW);
    }
    
    Serial.println();
    delay(200);
}

二、Arduino - DO引脚中断方式(低功耗)

// 使用外部中断监控DO引脚,火焰触发时立即响应
#define FLAME_DO_PIN    2       // Arduino Uno: INT0 = D2
#define BUZZER_PIN      5
#define LED_PIN         13

volatile bool fireAlarm = false;
volatile unsigned long lastFireTime = 0;

void IRAM_ATTR onFireDetected() {
    // 中断服务程序(尽量简短)
    fireAlarm = true;
    lastFireTime = millis();
}

void setup() {
    Serial.begin(115200);
    pinMode(FLAME_DO_PIN, INPUT_PULLUP);
    pinMode(BUZZER_PIN, OUTPUT);
    pinMode(LED_PIN, OUTPUT);
    
    // 配置外部中断(DO低电平触发即火焰检测)
    attachInterrupt(digitalPinToInterrupt(FLAME_DO_PIN), 
                    onFireDetected, FALLING);
    
    Serial.println("火焰监控系统启动(中断模式)");
    Serial.println("等待火焰触发...");
}

void loop() {
    if (fireAlarm) {
        fireAlarm = false;
        
        Serial.print("🔥 火焰报警! 触发时间: ");
        Serial.println(lastFireTime);
        
        // 报警动作
        digitalWrite(BUZZER_PIN, HIGH);
        digitalWrite(LED_PIN, HIGH);
        delay(3000);                     // 报警持续3秒
        
        digitalWrite(BUZZER_PIN, LOW);
        digitalWrite(LED_PIN, LOW);
        
        Serial.println("报警解除,继续监控...");
    }
    
    // 主循环可执行其他任务(低功耗模式此处可sleep)
    delay(100);
}

三、Arduino - 多级报警系统

// AO用于精细分级,DO用于快速确认
#define FLAME_AO_PIN    A0
#define FLAME_DO_PIN    2
#define BUZZER_PIN      5
#define RELAY_PIN       6       // 控制灭火装置
#define LED_GREEN       7
#define LED_YELLOW      8
#define LED_RED         9

enum AlarmLevel {
    LEVEL_SAFE = 0,      // 安全
    LEVEL_WARNING,       // 警告(微弱火源)
    LEVEL_DANGER,        // 危险(确认火焰)
    LEVEL_CRITICAL       // 紧急(强火焰)
};

AlarmLevel currentLevel = LEVEL_SAFE;

void setup() {
    Serial.begin(115200);
    pinMode(FLAME_DO_PIN, INPUT);
    pinMode(BUZZER_PIN, OUTPUT);
    pinMode(RELAY_PIN, OUTPUT);
    pinMode(LED_GREEN, OUTPUT);
    pinMode(LED_YELLOW, OUTPUT);
    pinMode(LED_RED, OUTPUT);
    
    digitalWrite(RELAY_PIN, LOW);
    digitalWrite(LED_GREEN, HIGH);
    
    Serial.println("多级火焰报警系统");
}

void loop() {
    int ao = analogRead(FLAME_AO_PIN);
    bool doTriggered = !digitalRead(FLAME_DO_PIN);
    
    // 分级判断
    AlarmLevel newLevel;
    if (ao > 800 && doTriggered) {
        newLevel = LEVEL_CRITICAL;
    } else if (ao > 500 && doTriggered) {
        newLevel = LEVEL_DANGER;
    } else if (ao > 300) {
        newLevel = LEVEL_WARNING;
    } else {
        newLevel = LEVEL_SAFE;
    }
    
    // 级别变化时执行相应动作
    if (newLevel != currentLevel) {
        currentLevel = newLevel;
        
        switch (currentLevel) {
            case LEVEL_SAFE:
                Serial.println("🟢 安全 - 无火焰");
                digitalWrite(LED_GREEN, HIGH);
                digitalWrite(LED_YELLOW, LOW);
                digitalWrite(LED_RED, LOW);
                digitalWrite(BUZZER_PIN, LOW);
                digitalWrite(RELAY_PIN, LOW);
                break;
                
            case LEVEL_WARNING:
                Serial.println("🟡 警告 - 检测到微弱红外源");
                digitalWrite(LED_GREEN, LOW);
                digitalWrite(LED_YELLOW, HIGH);
                digitalWrite(LED_RED, LOW);
                // 短促蜂鸣
                tone(BUZZER_PIN, 1000, 200);
                break;
                
            case LEVEL_DANGER:
                Serial.println("🟠 危险 - 确认火焰存在!");
                digitalWrite(LED_GREEN, LOW);
                digitalWrite(LED_YELLOW, LOW);
                digitalWrite(LED_RED, HIGH);
                digitalWrite(BUZZER_PIN, HIGH);     // 持续报警
                digitalWrite(RELAY_PIN, HIGH);      // 启动灭火
                break;
                
            case LEVEL_CRITICAL:
                Serial.println("🔴 紧急 - 强火焰! 全力灭火!");
                digitalWrite(LED_GREEN, LOW);
                digitalWrite(LED_YELLOW, LOW);
                digitalWrite(LED_RED, HIGH);
                digitalWrite(BUZZER_PIN, HIGH);
                digitalWrite(RELAY_PIN, HIGH);
                break;
        }
    }
    
    delay(100);
}

四、ESP-IDF - 双路检测+FreeRTOS任务通知

// esp32_flame_4pin.c
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_adc/adc_oneshot.h"

#define FLAME_DO_GPIO       25
#define FLAME_ADC_CHANNEL   ADC_CHANNEL_7
#define BUZZER_GPIO         26

static TaskHandle_t alarm_task_handle = NULL;

// DO引脚中断回调
static void IRAM_ATTR flame_isr_handler(void *arg) {
    // 通知报警任务
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(alarm_task_handle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void alarm_task(void *pvParameters) {
    while (1) {
        // 等待中断通知(最多等1秒)
        if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) > 0) {
            printf("🔥 火焰中断触发! 执行报警...\n");
            gpio_set_level(BUZZER_GPIO, 1);
            vTaskDelay(pdMS_TO_TICKS(3000));
            gpio_set_level(BUZZER_GPIO, 0);
            printf("报警解除\n");
        }
    }
}

void app_main(void) {
    // GPIO初始化
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << FLAME_DO_GPIO) | (1ULL << BUZZER_GPIO),
        .mode = GPIO_MODE_INPUT | GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .intr_type = GPIO_INTR_NEGEDGE,     // 下降沿触发(火焰检测)
    };
    gpio_config(&io_conf);
    gpio_set_direction(BUZZER_GPIO, GPIO_MODE_OUTPUT);
    
    // 安装中断
    gpio_install_isr_service(0);
    gpio_isr_handler_add(FLAME_DO_GPIO, flame_isr_handler, NULL);
    
    // 创建报警任务
    xTaskCreate(alarm_task, "alarm", 2048, NULL, 5, &alarm_task_handle);
    
    printf("4针火焰传感器监控系统就绪\n");
    
    // 主循环读取AO模拟量
    while (1) {
        // ... ADC读取代码(参考3针版本的ESP-IDF例程)
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

五、电位器调校助手程序

// 辅助调整4针模块的电位器阈值
#define FLAME_DO_PIN    2

void setup() {
    Serial.begin(115200);
    pinMode(FLAME_DO_PIN, INPUT_PULLUP);
    Serial.println("=== 电位器调校助手 ===");
    Serial.println("1. 将传感器置于检测目标距离");
    Serial.println("2. 逆时针旋转电位器直到DO=0(LOW)");
    Serial.println("3. 缓慢顺时针旋转直到DO刚刚变为1(HIGH)");
    Serial.println("4. 此时阈值最优,固定电位器即可");
    Serial.println("=======================");
}

void loop() {
    int doState = digitalRead(FLAME_DO_PIN);
    Serial.print("DO状态: ");
    if (doState == LOW) {
        Serial.println("LOW  ← 已触发(火焰/红外源太强或阈值太低)");
    } else {
        Serial.println("HIGH ← 未触发");
    }
    delay(300);
}

信息

路径
/firmware/传感器/火焰传感器-4针/火焰传感器(4针) 双模式检测与中断触发代码例程.md
更新时间
2026/5/26