💡 划重点

  • 今日项目为「果园夜间动物驱赶器」,不可更改为其他主题。
  • 主控芯片采用 ESP32,PIR 接 GPIO13,LDR 光敏电阻接 A0(GPIO34),高频 buzzer 接 PWM(GPIO25),LED 阵列接 GPIO27。
  • 总物料成本严格控制在 55 元人民币以内,适合果农小批量自建。
  • 采用"感知层-控制层-执行层-日志/联网层"四层架构设计。
  • 本方案不支持图像/插图/外链图片,所有说明以文字与代码/图表流程形式呈现。

---

需求洞察

目标用户特征

真实痛点

为什么值得做

---

方案设计

1. 感知层

2. 控制层

- 夜间 + PIR 触发 -> 启动 buzzer 扫频(2kHz~5kHz) 持续5秒。

- 白天或光照超过阈值 -> 忽略 PIR 触发以省电。

- 同一 PIR 信号在触发后 3 秒内不重复触发(去抖/锁定)。

- 若 30 分钟内连续被触发三次,执行"持续驱赶模式"即蜂鸣器扫频 32s + LED 阵列高频闪烁。

3. 执行层

4. 日志/联网层

---

物料清单

序号 物料 数量 用途 估算单价(元) 合计(元)
1 ESP32-WROOM-32 开发板 1 主控制核心 12.5 12.5
2 HC-SR501 PIR 模块 1 动物红外感知 3.8 3.8
3 LDR 光敏电阻 5516 1 昼夜判定 0.3 0.3
4 10k 电阻 1 LDR 分压下拉 0.1 0.1
5 高频有源蜂鸣器 4kHz 1 吓阻发声 1.2 1.2
6 白光 LED 5mm 高亮 4 闪烁闪光驱赶 0.4*4=1.6 1.6
7 330Ω 电阻 4 LED 限流 0.1*4=0.4 0.4
8 2N2222 三极管 1 buzzer 驱动器 0.6 0.6
9 面包板/洞洞板 1 接线固定 2.5 2.5
10 杜邦线公对母若干 16根 传感器连接 1.0 1.0
11 18650 1节 + 电池盒(或USB 5V 充电宝供电) 1 野外供电 6.5 6.5
12 DC-DC 降压或 AMS1117-3.3/5V(视供电方式) 1 稳压 2.0 2.0
13 IP65 防水塑料接线盒 1 户外保护 4.0 4.0
14 探针/鳄鱼线等杂项 - 安装固定 1.2 1.2

合计预算:37.7 元(低于预算 55 元,预留一定浮动余量,也可增买一个小容量太阳能板和充电管理模块升至48元左右)。

---

接线与结构

组件 连接至 ESP32 说明
PIR 模块 VCC → VIN(5V) 5V HC-SR501 电平输出为 3.3V,ESP32 输入引脚兼容
PIR 模块 OUT → GPIO13 13 (INPUT_PULLDOWN) 下降沿 / 高电平触发均可,使用 CHANGE 中断
PIR GND → GND GND 共地
LDR 第二脚 → A0 (即 GPIO34) GPIO34(ADC1_CH6) 接10k电阻到 GND;LDR 第一脚连 3.3V
buzzer(集电极) → 2N2222 C C 接 5V/VIN,B 接经 1k 电阻连 GPIO25 采用主动高电平驱动三极管
蜂鸣器负极(发射极) → GND GND 2N2222 E 极
LED 阵列 阳极(负极串 330Ω)→ GPIO27 GPIO27 低电平点亮,做闪烁
通讯/烧录 开发板自带 USB 调试日志输出使用 UART0

结构布置建议:整体设备装于透明防水盒内,PIR 探头伸出盒壁并用热熔胶密封,LDR 朝上偏 45 度避开遮挡,蜂鸣器朝动物来路方向开孔扩声。用 PVC 管 1.5m 竖立固定,离地 1m,传感器向下倾斜 15 度角度扫掠果园干道。

---

核心代码

以下为 Arduino 框架可编译骨架,包含实时控制逻辑:


#include <Arduino.h>

// 引脚定义
const uint8_t PIR_PIN = 13;
const uint8_t LDR_PIN = 34;      // ADC 通道6
const uint8_t BUZZER_PIN = 25;
const uint8_t LED_PIN = 27;

volatile bool pirTriggered = false;
unsigned long lastTriggerTime = 0;
unsigned long ignoreUntil = 0;
uint8_t triggerCountIn30Min = 0;
unsigned long logWindowStart = 0;

const int LDR_NIGHT_THRESHOLD = 800;  // 低于此值视为夜间
const uint8_t SCARE_DURATION_MS = 5000;
const uint8_t COOLDOWN_MS = 3000;
const uint16_t SUSTAINED_THRESHOLD = 3;

void IRAM_ATTR onPirRise() {
  if (millis() > ignoreUntil) {      // 去抖/忽略时段内不动作
    pirTriggered = true;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(LDR_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  digitalWrite(BUZZER_PIN, LOW);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH); // 熄灭 LED
  lastTriggerTime = millis();
  logWindowStart = millis();
}

void loop() {
  // 滚动30分钟窗口计数(若事件跨窗口则重置)
  if (millis() - logWindowStart > 1800000UL) {
    triggerCountIn30Min = 0;
    logWindowStart = millis();
  }

  int lightRaw = analogRead(LDR_PIN);
  bool isNight = (lightRaw < LDR_NIGHT_THRESHOLD);

  if (pirTriggered) {
    pirTriggered = false;
    if (isNight && (millis() - lastTriggerTime > COOLDOWN_MS)) {
      lastTriggerTime = millis();
      triggerCountIn30Min++;
      Serial.printf("[LOG] Night detect #%d, light=%d\n", triggerCountIn30Min, lightRaw);
      // 连续三次则长时间吓阻
      if (triggerCountIn30Min >= SUSTAINED_THRESHOLD) {
        sustainedScare();          // 32秒扫频 + LED 闪烁
        triggerCountIn30Min = 0;
      } else {
        quickScare();              // 5秒 扫频
      }
      ignoreUntil = millis() + 1500UL; // 触发保护
    }
  }

  delay(200);
}

// 高频扫频吓阻,模拟动物天敌或异响
void quickScare() {
  for (int i = 0; i < 50; i++) {
    for (int freq = 2000; freq <= 5000; freq += 400) {
      tone(BUZZER_PIN, freq, 30);
      delay(30);
    }
    blinkLed(3);
  }
  noTone(BUZZER_PIN);
  digitalWrite(LED_PIN, HIGH);
}

// 持续模式 - 更强
void sustainedScare() {
  unsigned long stateTimer = millis();
  while (millis() - stateTimer < 32000) {
    for (int freq = 1800; freq <= 5500; freq += 500) {
      tone(BUZZER_PIN, freq, 80);
      delay(120);
    }
    // 高频闪烁
    for (int j=0; j<15; j++) {
      digitalWrite(LED_PIN, LOW);
      delay(45);
      digitalWrite(LED_PIN, HIGH);
      delay(45);
    }
  }
  noTone(BUZZER_PIN);
  digitalWrite(LED_PIN, HIGH);
}

void blinkLed(uint8_t times) {
  for (uint8_t i = 0; i < times; i++) {
    digitalWrite(LED_PIN, LOW);
    delay(40);
    digitalWrite(LED_PIN, HIGH);
    delay(40);
  }
}

说明:使用 tone() 可以产生 2k~5kHz 扫频,搭配 2N2222 三极管即可驱动蜂鸣器发出刺耳变调声,比固定频率更让动物不适。

---

调试步骤

  1. 基础电源检查:用充电宝或锂电池供电,用万用表确认 ESP32 5V 和 3.3V 输出正常,蜂鸣器在不接 GPIO 情况下保持静音。
  2. LDR 光线标定:将代码单独运行,打开串口监视器(波特率 115200)观察 lightRaw 值,在傍晚遮光时读数应低于 800,白天在 2500-4000 之间。根据环境微调阈值。
  3. PIR 触发测试:安装好 PIR,等待 1 分钟稳定期后,在传感器前 3 米处走动查看串口是否打印“Night detect”日志以及蜂鸣器是否发声 5 秒。若触发过于频繁或失灵,用十字螺丝刀调节 PIR 板上灵敏度与延时旋钮,灵敏度逆时针减小 30%。
  4. 去抖/连续计数验证:在触发三次后确认是否进入了 32 秒长时间驱赶模式。若模式切换不正确,调整阈值常量。
  5. 实际室外部署:拿出果园点亮 LED 阵列,确认夜间肉眼可视,白天朝光方向是否能看清 LED 闪烁效果。整机放入防水盒后测试 PIR 感应距离是否因外壳衰减,若有壳体阻碍,应开小圆孔且避开阳光直射。
  6. 负载功耗测量:在电池端串联万用表,待机时电流应小于 50mA,蜂鸣器满载时 100-180mA。若电流过高,检查 PIR 是否错用 5V 供电。

---

设计图

果园夜间动物驱赶器结构flow
1
感知输入
2
控制处理
3
执行反馈
4
数据上报

结构展开说明(配合上图)

  • 感知输入:PIR红外热释移动检测、LDR光照强弱,二者逻辑与后激活执行。
  • 控制处理:ESP32 采用 GPIO 中断处理输入的触发,判断昼夜、去抖和连续计数,维护触发状态机。
  • 执行反馈:PWM 信号驱动三极管放大后带动高频压电蜂鸣器,在 GPIO27 控制 LED 阵列闪烁形成视觉惊吓。
  • 数据上报:预留串口日志(UART0),后续可联网 Blynk 推送动物频繁出现时段,量化数据辅助果园巡逻管理。

整个系统无一块多余模块,造价压进 37.7 元,比市售产品便宜一半以上,且安装自由度更高,非常适合果园主自己动手复刻。