1. 项目概述SimpleSiren是什么如果你对Arduino有点兴趣或者曾经想过自己动手做个能响能亮的警报装置那“SimpleSiren”这个项目标题应该能立刻抓住你的眼球。简单来说这就是一个基于Arduino平台的自制电子警报器。它不是什么复杂的工业级产品核心目标就是用最少的元件、最简单的代码实现一个功能明确、可自定义的声光报警系统。你可以把它理解为一个电子爱好者的“乐高积木”基础框架搭好后想让它模拟火警、车用报警器甚至是一个搞怪的派对提醒装置都完全由你说了算。我最初想做这个东西是因为工作室里一些精密仪器需要温湿度监控但市面上的报警器要么太贵要么功能臃肿不符合我的简单需求。于是一个念头就冒出来了为什么不自己用手边的Arduino Uno和几个基础元件攒一个呢这就是SimpleSiren的由来——它源于一个具体的、未被满足的小需求。这个项目的魅力在于它完美契合了Arduino“快速原型设计”的哲学低成本、易上手、高自由度。无论你是刚入门想找个练手项目的新手还是想给某个自动化小项目增加报警功能的老手SimpleSiren都能提供一个清晰、完整的实现路径。从技术角度看它涉及了Arduino的数字信号输出控制、模拟信号读取如果你扩展传感器的话、无源蜂鸣器的PWM驱动以及LED的闪烁控制。这些恰恰是玩转Arduino最核心、最基础的知识点。通过完成这个项目你不仅能收获一个实用的工具更能透彻理解如何让单片机“听话”去控制外部设备并响应外部条件。这比单纯点亮一个LED灯要有成就感得多也实用得多。2. 核心设计思路与方案选型2.1 为什么选择Arduino Uno作为主控提到Arduino型号众多从Nano到Mega再到功能更强的ESP32系列。对于SimpleSiren我毫不犹豫地选择了经典的Arduino Uno R3。原因有几个方面首先是生态和稳定性。Uno拥有最庞大、最成熟的社区支持任何你遇到的问题几乎都能找到现成的解决方案或讨论。它的ATmega328P芯片性能对于本项目绰绰有余——我们不需要Wi-Fi连接、不需要复杂的多任务处理只需要稳定地读取输入、控制输出。Uno的5V工作电压也完美匹配大多数常见的无源蜂鸣器和LED省去了电平转换的麻烦。其次是接口的便利性。Uno板载了电源稳压可以直接用USB供电或7-12V直流电源适配器供电这对于一个可能需要长时间待机的报警器来说非常可靠。它的数字I/O口足够多预留了充足的扩展空间。比如基础版只用2个口一个给蜂鸣器一个给LED但你可以轻松增加一个按键用于测试再增加一个电位器用来调节音量或音调甚至接入DHT11温湿度传感器来触发报警Uno的接口都应付得来。最后是成本与可获得性。Arduino Uno或它的兼容板是市场上最容易买到、价格也最透明的开发板之一。这对于项目复现至关重要我不希望因为推荐了一个小众或昂贵的板子而提高了大家的入门门槛。选择Uno意味着任何人都能几乎无成本地开始。2.2 声光报警元件的选型考量报警的核心是“声”和“光”。在“声”的方面我选择了最常见的无源电磁式蜂鸣器而不是有源蜂鸣器。这里有个关键区别有源蜂鸣器内部自带振荡电路通电就响音调固定而无源蜂鸣器内部没有振荡源需要外部提供一定频率的方波PWM信号才能发声其发声频率等于你所提供方波的频率。选择无源蜂鸣器核心优势在于“可控”。我们可以通过编程任意改变输出方波的频率从而模拟出警笛声频率由低到高再到低循环、急促的“滴滴”声甚至简单的音乐旋律。这赋予了SimpleSiren灵魂。在“光”的方面我选择了普通的5mm红色LED并串联一个220欧姆的限流电阻。选择红色是因为在人类视觉感知中红色光在同样亮度下更具警示性。为什么不直接用高亮LED或者LED模块主要还是为了保持项目的“Simple”特质。一个普通LED加一个电阻是最基础、最经典的电路理解它对于学习电子电路至关重要。当然你完全可以后期替换成高亮LED、RGB LED甚至LED灯带驱动原理是相通的。2.3 系统架构与信号流设计整个SimpleSiren的工作流可以概括为一个简单的“感知-决策-执行”循环尽管在基础版本中“感知”部分可能只是一个手动触发开关。其核心架构如下输入层这是系统的“感官”。最简情况下它可以是一个连接在数字引脚上的轻触开关用于手动触发报警。但它的设计是开放的你可以接入各类传感器来构成自动触发数字传感器如人体红外PIR传感器检测到移动时输出高电平。模拟传感器如MQ-2烟雾传感器、土壤湿度传感器通过模拟引脚读取其电压值当超过设定阈值时触发。复杂信号如通过串口接收来自电脑或其他主控板的指令。处理层由Arduino UnoATmega328P担当大脑。它持续扫描输入层的状态。一旦检测到触发条件如按键按下、传感器数值超限就立刻调用预设在程序中的“报警响应例程”。输出层这是系统的“手脚”。处理层决定报警后同时向两个通道发送命令声音通道向连接无源蜂鸣器的数字引脚输出特定频率和占空比的PWM波。通过程序循环改变频率就能生成起伏的警笛声。光通道向连接LED的数字引脚输出高低电平信号控制其闪烁。闪烁模式如常亮、快闪、慢闪可以与声音同步或独立编程。这个架构清晰且易于扩展。比如你可以为不同的触发源火灾、入侵定义不同的声光模式让系统具备初步的“智能”判断能力。3. 核心电路搭建与元件详解3.1 所需元件清单与作用解析动手之前请清点以下元件。这些都是电子爱好者手边常备或极易购得的Arduino Uno R3开发板 x1系统主控核心。无源电磁式蜂鸣器 x1发声元件。关键点务必确认是“无源”Passive通常底部是密封的有两个引脚正负极不敏感但通常长脚为正。有源蜂鸣器底部可能带有一个小电路板或有一个贴纸标签。5mm红色发光二极管LED x1光报警元件。220欧姆碳膜电阻 x1用于限制LED电流防止烧毁。色环为“红-红-棕-金”。10k欧姆电阻 x1可选用于按键消抖作为上拉或下拉电阻。轻触开关 x1可选用于手动触发测试。面包板 x1用于免焊接电路搭建和测试。杜邦线公对公若干连接各元件。USB数据线A to B型x1为Arduino供电和上传程序。注意购买无源蜂鸣器时可以留意其额定电压常见3V, 5V, 12V和共振频率。我们选用5V的其共振频率如2.5kHz是它发声最灵敏、最响亮的频率编程时可以围绕这个频率设计音调变化效果更好。3.2 电路连接图与接线原理让我们在面包板上搭建电路。遵循“先电源后信号”的原则确保连接牢固。核心接线步骤如下供电准备将Arduino Uno通过USB线连接电脑。此时Uno板上的“POWER”LED应亮起。Uno板会从USB口获得5V电压并通过板上的排针提供给面包板。你可以用一根杜邦线将Uno的5V引脚连接到面包板的红色正极总线将GND引脚连接到面包板的蓝色负极总线。连接无源蜂鸣器将蜂鸣器的一个引脚通常为正极通过杜邦线连接到Arduino的数字引脚 ~9注意引脚号前有波浪线~的表示支持PWM输出这是产生可变频率方波的关键。将蜂鸣器的另一个引脚连接到面包板的负极总线GND。连接LED指示灯将LED的长脚阳极正极与一个220欧姆电阻的一端连接可以在面包板的同一行孔内实现。将这个电阻的另一端通过杜邦线连接到Arduino的数字引脚 13引脚13板载了一个LED方便调试但我们这里用作控制外接LED。将LED的短脚阴极负极直接连接到面包板的负极总线GND。可选连接触发按键将轻触开关跨接在面包板的中缝两侧。开关的一端连接到面包板的负极总线GND。开关的另一端一方面通过一个10k欧姆电阻连接到面包板的正极总线5V这个电阻称为“上拉电阻”另一方面通过杜邦线连接到Arduino的数字引脚 2。这种连接方式构成了一个“上拉电阻按键接地”的经典电路。当按键未按下时引脚2通过10k电阻被“拉高”到5V读取为HIGH当按键按下时引脚2直接接地读取为LOW。10k电阻的作用是限制电流并在按键断开时提供一个确定的高电平防止引脚悬空产生不确定信号。电路原理简述在这个电路中数字引脚9和13扮演了“开关”的角色。当程序将它们设置为HIGH5V时电路导通电流流过蜂鸣器和LED。对于蜂鸣器我们通过tone()函数快速切换HIGH和LOW形成特定频率的方波驱动其振动发声。对于LEDHIGH则点亮LOW则熄灭。通过控制HIGH和LOW的持续时间就能实现闪烁。3.3 搭建过程中的实操心得与避坑指南蜂鸣器正负极判断虽然无源蜂鸣器对直流极性不敏感但通常印有“”号或引脚较长的一侧为正极。按标识连接是更好的习惯。LED必串电阻这是新手最容易忽略导致烧毁元件的一步。没有限流电阻5V电压直接加在LED上电流会远超其承受能力通常20-30mA瞬间损坏。220欧姆电阻在5V下能将电流限制在约(5V - LED压降约2V)/220Ω ≈ 13.6mA处于安全范围。面包板连接要稳固杜邦线要插到底元件引脚不能松动。接触不良会导致报警时有时无是排查故障时首要检查的点。善用引脚功能为什么用引脚9和13引脚9支持PWM这是驱动无源蜂鸣器的基础。引脚13方便是因为板载LED即使外接LED不亮也可以通过板载LED观察输出状态辅助调试。引脚2和3支持外部中断适合连接触发信号响应更及时我们在基础版用轮询但你可以为升级版预留这个特性。电源稳定性如果报警声音微弱或LED昏暗检查电源。USB口供电能力有限约500mA如果同时驱动多个外围设备可能不足。可以考虑使用9V直流电源适配器插入Uno的桶形插座以获得更稳定的电源。4. 核心代码实现与逻辑剖析电路搭好只是躯干代码才是灵魂。下面我们分步拆解SimpleSiren的核心程序。4.1 基础报警音效tone()函数的妙用Arduino驱动无源蜂鸣器的核心是tone()函数。与简单的digitalWrite()不同tone()能自动在指定引脚生成特定频率的方波。// 基础发声示例 int buzzerPin 9; // 蜂鸣器连接的引脚 void setup() { pinMode(buzzerPin, OUTPUT); } void loop() { tone(buzzerPin, 1000); // 在引脚9产生1000Hz频率的声音 delay(1000); // 持续1秒 noTone(buzzerPin); // 停止发声 delay(1000); // 静音1秒 }这段代码会让蜂鸣器发出1kHz的单调声音响1秒停1秒。但警笛声不是单调的它是滑动的。如何实现答案是在循环中连续改变tone()的频率参数。// 模拟警笛声上升下降 void loop() { // 频率从低到高上升 for (int freq 800; freq 1200; freq 10) { tone(buzzerPin, freq); delay(10); // 每个频率持续10毫秒决定滑音速度 } // 频率从高到低下降 for (int freq 1200; freq 800; freq - 10) { tone(buzzerPin, freq); delay(10); } // 可选中间加入短暂停顿模拟另一种警笛节奏 noTone(buzzerPin); delay(50); }通过两个for循环频率在800Hz到1200Hz之间平滑地上升和下降就形成了经典的“呜~嗯~呜~嗯~”警笛效果。调整delay(10)的值可以改变音调变化的速度调整频率范围如500Hz-1500Hz可以改变音高。实操心得tone()函数有一个限制它一次只能在一个引脚上产生声音。如果你需要同时驱动多个蜂鸣器发出不同声音则需要使用第三方库如ToneAC或者更高级的定时器中断技术。对于SimpleSiren一个蜂鸣器足矣。4.2 同步光效控制让LED“跳起舞来”声音有了光也要同步。我们希望LED在警笛声上升时快速闪烁在下降时慢速闪烁或者采用其他模式。int ledPin 13; // LED连接的引脚 void setup() { pinMode(ledPin, OUTPUT); } void loop() { // 模式1与声音同步的闪烁上升快闪下降慢闪 for (int freq 800; freq 1200; freq 10) { tone(buzzerPin, freq); digitalWrite(ledPin, HIGH); delay(5); // LED亮5ms digitalWrite(ledPin, LOW); delay(5); // LED灭5ms整体周期10ms即100Hz闪烁肉眼可见快闪 } for (int freq 1200; freq 800; freq - 10) { tone(buzzerPin, freq); digitalWrite(ledPin, HIGH); delay(20); // LED亮20ms digitalWrite(ledPin, LOW); delay(20); // LED灭20ms整体周期40ms即25Hz闪烁肉眼可见慢闪 } noTone(buzzerPin); digitalWrite(ledPin, LOW); // 确保停止时LED熄灭 delay(50); }这里的关键是在同一个循环中我们同时控制声音频率和LED的亮灭节奏。delay()函数会阻塞整个程序所以声音和光是严格同步的。如果你想实现更复杂的异步光效比如LED按照固定模式闪烁不受声音循环影响则需要用到millis()函数进行非阻塞式定时这将是代码优化的方向。4.3 完整代码整合与触发逻辑现在我们把蜂鸣器控制、LED控制和触发判断整合到一个完整的、可用的SimpleSiren程序中。这里我们使用可选的按键作为触发源。// SimpleSiren 完整示例代码 v1.0 // 定义引脚 const int buzzerPin 9; // 蜂鸣器连接引脚 (~PWM) const int ledPin 13; // LED连接引脚 const int buttonPin 2; // 触发按键连接引脚 // 变量定义 int buttonState 0; // 存储按键状态的变量 bool alarmActive false; // 报警激活标志 void setup() { // 初始化引脚模式 pinMode(buzzerPin, OUTPUT); pinMode(ledPin, OUTPUT); pinMode(buttonPin, INPUT_PULLUP); // 使用内部上拉电阻按键另一端接地 // 注意使用INPUT_PULLUP后按键未按下时为HIGH按下时为LOW // 初始状态关闭声光 digitalWrite(ledPin, LOW); noTone(buzzerPin); // 启动串口监视器用于调试可选 Serial.begin(9600); Serial.println(SimpleSiren 就绪...); } void loop() { // 1. 读取触发信号 buttonState digitalRead(buttonPin); // 2. 判断触发条件按键按下即LOW if (buttonState LOW) { // 防抖延时避免机械按键抖动误触发 delay(50); // 再次确认按键状态 if (digitalRead(buttonPin) LOW) { alarmActive true; // 激活报警 Serial.println(报警触发); } } // 3. 执行报警逻辑 if (alarmActive) { playSiren(); // 播放警笛声光效果 // 这里可以添加其他停止条件比如再次按下按键停止 // 本例中报警一旦触发会一直响直到复位或断电 } else { // 非报警状态确保一切关闭 noTone(buzzerPin); digitalWrite(ledPin, LOW); } } // 警笛效果子函数 void playSiren() { // 上升音调快闪 for (int freq 800; freq 1200; freq 8) { tone(buzzerPin, freq); flashLED(80); // 快闪参数周期短 } // 下降音调慢闪 for (int freq 1200; freq 800; freq - 8) { tone(buzzerPin, freq); flashLED(200); // 慢闪参数周期长 } // 循环间短暂停顿 noTone(buzzerPin); delay(30); } // LED闪烁子函数 void flashLED(int interval) { // interval控制闪烁半周期单位毫秒 digitalWrite(ledPin, HIGH); delayMicroseconds(interval * 100); // 使用微秒延迟获得更精确控制 digitalWrite(ledPin, LOW); delayMicroseconds(interval * 100); }代码逻辑剖析初始化(setup)配置引脚模式。特别注意pinMode(buttonPin, INPUT_PULLUP)它启用了Arduino内部的上拉电阻省去了我们外接10k上拉电阻的步骤使电路更简洁。按键另一端只需接地即可。主循环(loop)读取持续读取按键状态。判断如果检测到按键被按下LOW先进行一个简单的软件防抖delay(50)再次确认后将报警标志alarmActive设为true。执行根据alarmActive标志决定是调用playSiren()函数执行报警还是关闭所有输出。报警函数(playSiren)封装了上升/下降音调和对应的LED闪烁模式。音调变化步长和闪烁速度可以通过参数调整。闪烁函数(flashLED)一个独立的LED控制函数通过interval参数灵活控制闪烁频率。这里使用了delayMicroseconds()以获得比delay()更精细的时间控制。这个版本实现了基本的触发和持续报警。你可以通过修改playSiren函数内的频率范围、步进值和flashLED的参数创造出属于自己的独特报警音效和光效。5. 功能扩展与高级玩法基础版SimpleSiren已经能工作但它的潜力远不止于此。下面介绍几个实用的扩展方向让你的报警器变得更聪明、更强大。5.1 接入传感器实现自动报警将手动按键触发替换为传感器是项目质的飞跃。这里以常见的HC-SR501人体红外PIR传感器为例将其输出引脚连接到Arduino的数字引脚如引脚3。// 使用PIR传感器的部分代码示例 const int pirPin 3; // PIR传感器输出引脚 int pirState LOW; // 初始状态 void setup() { pinMode(pirPin, INPUT); // ... 其他初始化 } void loop() { pirState digitalRead(pirPin); if (pirState HIGH) { // 检测到人体移动 alarmActive true; Serial.println(检测到移动报警启动。); // 可以添加一个持续触发的时间比如检测到后报警30秒 } // ... 后续报警逻辑同上 }关键调整PIR传感器通常有灵敏度调节和延时时间调节电位器。你需要根据安装环境调整灵敏度并设置合理的延时即触发后输出高电平的持续时间避免持续移动导致报警不停。同理你可以接入MQ-2烟雾传感器模拟引脚读取其电压值当电压超过安全阈值时触发火灾报警接入DHT11温湿度传感器当温度超过设定值时触发高温报警。只需将触发判断逻辑从digitalRead改为analogRead并与阈值比较即可。5.2 设计多模式报警与静音功能一个实用的报警器应该有不同模式。我们可以通过增加一个模式切换开关或按钮和状态指示灯来实现。硬件增加一个3位拨码开关或两个按钮模式上/下。一个双色LED或另一个单色LED作为状态指示灯。逻辑设计模式0待机。声光全关状态灯常绿。模式1警笛模式。即基础版效果状态灯红色快闪。模式2急促蜂鸣模式。发出“滴滴滴滴”的急促声音LED同步快闪适用于提醒。模式3仅光报警。蜂鸣器静音只有LED闪烁适用于夜间或需要安静的场合。通过读取模式开关的状态在loop()中使用switch-case语句来执行不同模式的报警例程。同时可以再设置一个“消音/复位”按钮在任何模式下按下都能强制停止当前报警并返回待机模式。5.3 使用中断实现即时响应在基础版中我们使用digitalRead()在loop中轮询按键状态。如果loop中的playSiren()函数正在执行一个长循环那么在此期间按下停止按钮程序可能无法立即响应因为CPU正忙于产生声音和光效。为了解决这个问题可以使用外部中断。Arduino Uno的引脚2和3支持外部中断。我们可以将“停止按钮”连接到引脚2并配置为中断触发。const int stopButtonPin 2; // 停止按钮接中断引脚2 void setup() { // ... 其他初始化 // 配置中断当引脚2由高电平变为低电平时FALLING触发中断函数stopAlarm attachInterrupt(digitalPinToInterrupt(stopButtonPin), stopAlarm, FALLING); } void loop() { if (alarmActive) { playSiren(); // 主循环中正常播放报警 } // ... 其他逻辑 } // 中断服务函数 void stopAlarm() { alarmActive false; // 立即停止报警 noTone(buzzerPin); digitalWrite(ledPin, LOW); Serial.println(报警被手动停止); }中断的优势无论CPU正在执行loop中的什么任务只要中断引脚的电平发生变化本例是下降沿CPU会立即暂停当前工作跳转到stopAlarm()函数执行执行完毕后再返回原任务。这实现了真正的即时响应。注意事项中断服务函数ISR应该尽可能短小只做最关键的标志位设置或简单操作。避免在ISR中使用delay()、Serial.print()等耗时函数也不要在ISR中调用tone()这可能导致程序行为异常。5.4 电源管理与低功耗优化如果你的SimpleSiren需要电池供电并长期待机功耗就变得至关重要。基础版中即使报警未触发Arduino和传感器也一直在全速运行消耗电流可能达到几十毫安。优化策略睡眠模式利用avr/sleep.h库让Arduino在待机时进入深度睡眠。当触发传感器如PIR产生信号时这个信号可以连接到中断引脚将单片机从睡眠中唤醒。唤醒后执行报警完成后再次进入睡眠。这可以将待机电流降至微安级别。关闭无用外设在睡眠前通过代码关闭ADC模数转换器、定时器等未使用的外设模块。传感器供电控制对于功耗较高的传感器可以通过一个MOSFET或三极管开关电路由Arduino的一个引脚控制其电源仅在需要检测时才上电。实现低功耗是一个相对高级的话题需要对Arduino的硬件和寄存器有更深了解但它能极大延长电池寿命是制作真正“可部署”报警设备的关键一步。6. 常见问题排查与调试技巧即使按照步骤操作你也可能会遇到一些问题。这里汇总了一些常见故障和解决方法。6.1 蜂鸣器不响或声音异常症状完全无声。检查1电源和接地。用万用表测量蜂鸣器两端电压在程序执行tone()时应有约2.5V的交流电压因PWM方波导致。确保蜂鸣器引脚与Arduino连接正确且牢固。检查2蜂鸣器类型。再次确认你使用的是无源蜂鸣器。有源蜂鸣器接上tone()函数可能不响或声音很小。检查3引脚和代码。确认代码中buzzerPin的引脚号与实际连接一致。尝试用最简单的测试代码如tone(9, 1000); delay(1000);单独测试蜂鸣器。症状声音小、嘶哑或音调不对。检查1驱动能力。Arduino单个I/O引脚的驱动电流有限约20mA。如果蜂鸣器额定电流较大可能需要增加一个三极管如S8050进行电流放大。检查2频率范围。无源蜂鸣器有其最佳谐振频率。尝试将tone()的频率设置在1000Hz到3000Hz之间找到最响亮、最清晰的点。通常2kHz左右效果较好。检查3PWM引脚。确保蜂鸣器连接在支持PWM的引脚Uno上是3, 5, 6, 9, 10, 11。6.2 LED不亮或常亮症状LED完全不亮。检查1极性。LED长脚正极必须通过电阻接电源引脚输出短脚负极接GND。接反了不会亮。检查2电阻。确认限流电阻已正确串联在电路中且阻值合适常用220Ω-1kΩ。检查3代码控制。确认代码中ledPin定义正确且在需要点亮时执行了digitalWrite(ledPin, HIGH)。可以用digitalWrite(ledPin, HIGH); delay(1000);测试。症状LED常亮不受控制。检查1引脚模式。在setup()中是否用pinMode(ledPin, OUTPUT)正确初始化了引脚检查2逻辑错误。检查loop()中的逻辑是否在报警停止后忘记执行digitalWrite(ledPin, LOW)或者条件判断有误导致alarmActive一直为真。6.3 触发不灵敏或误触发症状按键按下没反应或需要按很多次。检查1上拉电阻与接线。如果使用外部上拉电阻10k确保连接正确。更推荐使用INPUT_PULLUP模式简化电路。检查2按键消抖。机械按键在按下和弹起时会产生信号抖动。我们的代码中使用了delay(50)进行软件消抖。如果问题依旧可以尝试增加这个延时或者使用更可靠的消抖库如Bounce2。症状传感器如PIR一直触发或从不触发。检查1传感器调节。PIR传感器上的两个电位器一个是灵敏度SENS一个是延时时间TIME。调整它们并给传感器一段初始化时间约1分钟。检查2环境干扰。PIR对热源敏感避免将其对准暖气、窗户阳光或宠物经常活动的区域。确保传感器透镜清洁。检查3供电电压。确保传感器工作在额定电压下HC-SR501通常是5V-12V。电压不稳可能导致工作异常。6.4 程序上传失败或运行不稳定症状Arduino IDE无法上传程序。检查1板卡和端口。在“工具”菜单下确认选择的板卡是“Arduino Uno”并且选择了正确的COM端口。检查2驱动。如果是第一次使用可能需要安装CH340或FTDI的USB转串口驱动取决于你的Uno是原版还是兼容版。检查3连接与干扰。拔掉连接在数字引脚0RX和1TX上的任何设备它们与串口通信冲突。确保USB线连接良好。症状程序运行一段时间后死机或复位。检查1电源不足。特别是当蜂鸣器鸣响时瞬时电流较大可能引起电源电压跌落导致单片机复位。尝试使用外部9V电源适配器供电而非USB口。检查2代码逻辑。检查是否有数组越界、无限递归或堆栈溢出等问题。确保中断服务函数尽可能短。检查3看门狗复位。如果代码中启用了看门狗Watchdog Timer且未及时喂狗会导致自动复位。除非你明确使用了看门狗否则一般不会是这个原因。调试时串口监视器是你的最佳朋友。在代码关键位置添加Serial.print()语句输出变量状态如alarmActive、传感器读数等可以让你清晰地了解程序的运行流程快速定位问题所在。养成“先编译、再上传、看串口”的调试习惯能解决大部分软件层面的问题。