1. 项目概述为什么我们需要一个“物理外挂”来重启路由器如果你家里或者管理的远程设备比如办公室、出租屋、或者像我一样在佛罗里达的度假屋的网络设备隔三差五就“假死”需要拔插电源才能恢复那你一定懂这种抓狂的感觉。尤其是在你人不在现场的时候这种小问题能直接让整个远程监控或智能家居系统瘫痪。市面上的智能插座大多只能实现简单的定时开关但无法在断电后“记住”时间一旦市电波动导致插座重启定时程序就乱了套更别提精确到每天凌晨执行一次毫秒级的重启操作了。这正是我设计这个“路由器自动重启器II代”Router Restarter II的初衷。它不是一个复杂的物联网云设备而是一个纯粹、可靠、离线的“物理看门狗”。其核心逻辑非常简单利用一块带电池备份的实时时钟DS3231 RTC保持精准计时由Arduino Nano作为大脑每天在预设的“维护窗口”比如凌晨3点控制继电器切断路由器或光猫的电源一分钟然后再恢复供电。这个短暂的断电足以清除设备内存中的临时错误状态相当于给设备做了一次强制重启但又不会中断服务太久因为通常选在无人使用的深夜。这个方案完美解决了远程位置网络设备“卡死”无人处理的问题成本低廉且完全独立于家庭网络运行即使主网络瘫痪它也能依靠自身RTC继续工作并在预定时间执行任务。2. 核心硬件选型与设计思路解析2.1 微控制器为何是Arduino Nano在这个项目中选择Arduino Nano几乎是必然的。首先它的核心ATmega328P单片机性能对于简单的定时逻辑和I2C通信绰绰有余。其次Nano的尺寸非常小巧可以直接插在定制PCB上作为DIP芯片使用极大地简化了硬件集成。相比UNO它省去了笨重的USB接口和电源模块使整个设备可以做得更紧凑。最后Arduino生态拥有海量的库和社区支持无论是驱动DS3231还是LCD屏都有成熟的库函数能让我把精力集中在应用逻辑而非底层驱动上。对于这类一次性烧录、长期稳定运行的应用Nano的性价比和易用性是无与伦比的。2.2 计时核心从DS3234到DS3231的进化在第一代设计中我使用了DS3234 RTC芯片。它是SPI接口精度极高但有两个痛点一是它采用表面贴装SMT封装手工焊接对爱好者不太友好二是SPI接线需要占用更多IO口。在第二代中我果断换成了DS3231模块。这是一个已经焊好在小型PCB上的“分线板”直接提供了I2C接口和CR2032电池座。I2C只需要两根数据线SDA, SCL大大简化了布线。DS3231的精度±2ppm对于日级定时任务来说完全足够其内置的温度补偿晶体振荡器保证了即使在温度变化下也能走时精准。最关键的是电池备份功能让它在主电源断开时时间和日期信息毫发无损这是实现“离线精准定时”的基石。注意DS3231模块的I2C地址通常是0x68但市面上也有些模块通过地址跳线可以设置为0x69。在编程时需要确认。此外务必在首次使用前安装好CR2032电池否则断电后时间会丢失。2.3 执行机构继电器 vs. 可控硅Triac的抉择控制交流电的通断常见方案有继电器和可控硅。我选择了5V双通道继电器模块原因有三完全电气隔离继电器通过线圈吸合机械触点控制侧低压直流和被控侧高压交流在物理上是隔离的安全性高抗干扰能力强。驱动简单负载能力强常见的继电器模块如SRD-05VDC-SL-C触点容量可达10A/250VAC轻松驱动路由器、光猫这种小功率设备通常功耗20W。驱动它只需要Arduino的一个IO口输出低电平即可无需复杂的过零检测驱动电路。无发热问题继电器在吸合或断开状态线圈只在状态切换瞬间耗电长期处于稳定状态时几乎不发热因此不需要散热片。而可控硅在导通时存在管压降会持续产生热量需要根据负载计算并配备合适的散热器增加了复杂性和空间占用。我特意使用了继电器的常闭NC触点来连接负载。这意味着设备正常工作时继电器线圈是不通电的触点处于常闭状态电源畅通。只有当需要重启时Arduino才给继电器一个信号线圈得电触点断开切断电源。一分钟后撤销信号线圈失电触点恢复闭合通电。这种“常态不耗电”的设计进一步降低了设备的整体功耗和发热。2.4 电源与显示稳定与信息的保障整个系统由一颗9V/1A的直流电源适配器俗称“墙插电源”供电。9V电压直接接入Arduino Nano的Vin引脚其内部线性稳压器会将其降至5V为单片机供电。同时这9V输入也接入一个经典的7805三端稳压芯片为DS3231模块、LCD显示屏和继电器模块提供纯净、稳定的5V电源。虽然继电器模块和Arduino的5V可以共用但独立一路7805供电可以避免继电器动作时产生的电压毛刺干扰到核心的MCU和RTC提升系统稳定性。显示部分采用了一块20x4字符的I2C液晶屏。它只用了两根数据线就实现了四行文字的显示可以实时展示当前时间、日期以及两个通道的定时状态“等待中”或“重启中”。这对于现场调试和设备状态确认非常有用。当然如果为了极致简化显示屏是可以省略的通过一个LED状态指示灯也能实现基本功能。3. 电路设计与PCB布局实战3.1 原理图详解信号与电源的脉络整个系统的电路原理并不复杂但清晰的规划是成功的关键。下图是核心部分的连接逻辑文字描述电源路径9V输入正极分为两路一路至Arduino Nano的Vin一路至7805的输入端。7805输出端产生系统5VVCC为所有模块供电。输入输出端均需并联滤波电容如100uF电解电容和0.1uF陶瓷电容以平滑电压。控制信号Arduino Nano的D2、D3引脚分别连接到两个继电器模块的IN1、IN2信号输入端。这些输入端内部通过光耦隔离另一端接VCC。因此当D2/D3输出**低电平LOW**时光耦导通继电器吸合常闭触点断开。Arduino Nano的A4SDA、A5SCL引脚分别连接到DS3231模块和I2C LCD屏的对应引脚。注意I2C总线需要上拉电阻通常模块已内置若没有则需在SDA和SCL线上各接一个4.7kΩ电阻上拉到5V。负载连接交流市电的火线L先接入继电器模块的公共端COM。每个继电器的常闭NC触点引出分别连接到输出插座的两个插孔。零线N则直接并联到输出插座。务必确保交流接线部分绝缘处理完好最好使用螺丝端子固定并在通电前用万用表仔细检查防止短路。3.2 PCB设计从软件到实物的桥梁为了获得整洁、可靠且可复制的作品我使用ExpressPCB免费软件设计了定制电路板。将Arduino Nano、7805稳压电路、滤波电容、I2C和继电器接口的排针都集成到一块板上能彻底告别面包板的杂乱和杜邦线的脆弱。在设计PCB时我遵循了以下原则电源走线优先加粗特别是9V输入和5V主干线路采用更宽的线宽以减少阻抗和压降。数字与模拟/电源分离虽然本项目数字信号不多但仍尽量让MCU的数字信号线如D2D3远离模拟部分和电源线平行走线时保持距离。良好的接地采用单点接地或星型接地思路让7805的地、Arduino的地、继电器模块的地最终都汇集到电源输入的地端避免地环路噪声。预留测试点和丝印在关键电源点和信号点预留了测试焊盘并在丝印层清晰标注了每个接口的功能如“9V_IN”、“RELAY1”、“I2C_LCD”极大方便了焊接和调试。将设计好的PCB文件发给厂家打样通常只需几十元就能得到三五块高质量的板子。焊接时先焊高度最低的器件如电阻、IC座再焊较高的如电容、排针最后插接Arduino Nano和各类模块。3.3 外壳与安全不止于美观一个裸露的电路板既不安全也不专业。我使用SketchUp设计了适配PCB和所有元件尺寸的项目外壳并用3D打印机将其制作出来。外壳设计要点包括充分的内部空间除了PCB还要容纳电源适配器的DC头、交流电的入线和出线端子以及LCD屏的开孔。内部空间要充裕便于布线散热。明确的接口标识在外壳上丝印或粘贴标签注明“AC INPUT”、“OUTLET 1”、“OUTLET 2”和“DC 9V”防止误接。通风与隔离虽然设备发热不大但仍需在外壳上下设计一些通风孔。更重要的是在内部用塑料挡板或空气间隙将高压交流部分继电器端子、电源线与低压直流部分PCB进行物理隔离这是最重要的安全措施。可靠的固定PCB通过铜柱固定电源适配器和交流插座通过螺丝或卡扣固定所有线缆用扎带整理确保设备在移动或运输时内部元件不会松动脱落。4. 软件编程让硬件按计划行动4.1 开发环境与库的配置代码在Arduino IDE中编写。首先需要安装两个必要的库DS3231库我使用的是NorthernWidget/DS3231这个库。在Arduino IDE中点击“项目” - “加载库” - “管理库”搜索“DS3231”找到并安装即可。这个库提供了简洁的接口来读取和设置RTC的时间。LiquidCrystal_I2C库用于驱动I2C接口的LCD屏。同样在库管理中搜索“LiquidCrystal I2C”进行安装。需要特别注意不同厂商的LCD屏驱动芯片通常是PCF8574的I2C地址可能不同常见的是0x27或0x3F。你可以在代码中修改地址或者用I2C扫描示例程序来探测地址。#include Wire.h #include DS3231.h #include LiquidCrystal_I2C.h // 初始化DS3231对象 DS3231 rtc; // 初始化LCD对象参数为(I2C地址, 列数, 行数) LiquidCrystal_I2C lcd(0x27, 20, 4);4.2 核心逻辑状态机与时间判断程序的主体结构是一个简单的状态机循环在loop()函数中不断执行以下步骤读取当前时间从DS3231获取当前的时、分、秒。更新显示将时间、日期和通道状态刷新到LCD屏上。检查并控制继电器将当前时间与预设的“开始时间”和“结束时间”进行比较决定继电器的状态。短暂延迟使用delay(100)或类似短延时避免循环过快消耗CPU资源虽然对Arduino来说不是大问题。定时控制的逻辑是核心。我为两个输出通道分别定义了开始和结束时间。例如想让通道1在凌晨3:00断电3:01恢复通道2紧接着在3:01断电3:02恢复。// 定义重启时间窗口 unsigned int start_hour1 3, start_minute1 0; // 通道1开始断电时间 unsigned int end_hour1 3, end_minute1 1; // 通道1恢复供电时间 unsigned int start_hour2 3, start_minute2 1; // 通道2开始断电时间 unsigned int end_hour2 3, end_minute2 2; // 通道2恢复供电时间 void controlRelays() { int currentHour rtc.getHour(); int currentMinute rtc.getMinute(); int currentSecond rtc.getSecond(); // 将时、分转换为从午夜开始的分钟数便于比较 unsigned long currentTimeInMinutes currentHour * 60 currentMinute; unsigned long start1 start_hour1 * 60 start_minute1; unsigned long end1 end_hour1 * 60 end_minute1; unsigned long start2 start_hour2 * 60 start_minute2; unsigned long end2 end_hour2 * 60 end_minute2; // 控制继电器1 if (currentTimeInMinutes start1 currentTimeInMinutes end1) { digitalWrite(RELAY1_PIN, LOW); // 输出低电平继电器吸合断电 } else { digitalWrite(RELAY1_PIN, HIGH); // 输出高电平继电器释放通电 } // 控制继电器2 if (currentTimeInMinutes start2 currentTimeInMinutes end2) { digitalWrite(RELAY2_PIN, LOW); } else { digitalWrite(RELAY2_PIN, HIGH); } }这段代码的精妙之处在于它比较的是“分钟数”这意味着重启窗口的精度是分钟级。对于路由器重启来说这完全足够。如果你需要秒级精度可以加入currentSecond的判断。4.3 首次烧录与RTC时间设置DS3231模块出厂时时间是不对的或者电池没电后时间会丢失。因此首次使用需要校准。在代码中我预留了一段被注释掉的“设置时间”代码。void setup() { // ... 其他初始化代码 // 首次烧录时取消下面几行的注释并设置正确的时间日期 // rtc.setClockMode(false); // false为24小时制 // rtc.setSecond(0); // rtc.setMinute(30); // 例如设置分钟为30 // rtc.setHour(14); // 设置小时为14下午2点 // rtc.setDoW(5); // 设置星期几1周日2周一...7周六 // rtc.setDate(15); // 设置日期 // rtc.setMonth(5); // 设置月份 // rtc.setYear(23); // 设置年份2023 // 设置完成后编译上传一次程序。 // 然后重新注释掉这些行再编译上传一次。这样时间就被“烧录”进RTC并由电池保持了。 }操作流程至关重要确保DS3231模块已安装CR2032电池。在setup()函数中取消注释时间设置行填入你电脑当前的准确时间建议使用网络时间同步。编译并上传代码到Arduino Nano。此时程序运行会将你设置的时间写入DS3231。不要断电立即回到代码中将那几行设置时间的代码重新注释掉。再次编译并上传代码。这次上传的程序setup()里就没有设置时间的命令了它会直接从DS3231读取已经校准好的时间。此后无论设备断电多久只要电池有电时间就会一直保持准确。实操心得很多初学者会忘记“注释-上传-再注释-再上传”的第二步导致每次设备重启程序都重新用旧的不正确时间覆盖RTC。务必按步骤操作。上传后可以通过串口监视器打印RTC时间或者观察LCD屏来验证时间是否设置成功并持续走时。5. 组装、调试与部署全记录5.1 分步组装指南焊接PCB按照PCB丝印依次焊接IC座、电容、电阻、排针等。7805稳压芯片记得装上小型散热片。最后将Arduino Nano小心插入IC座。连接模块使用4Pin杜邦线或排针将DS3231模块、LCD屏、继电器模块分别连接到PCB上对应的接口。务必对照原理图确认VCC、GND、SDA、SCL等线序完全正确接反可能烧毁模块。安装入箱将PCB用铜柱固定在外壳底板上。将LCD屏从外壳正面放入并卡紧。把电源适配器的DC插头从外壳侧面的孔穿入焊接到PCB的电源输入端子。将交流输入线接插头和交流输出插座也固定好并接线。连接负载将继电器模块上标有“COM”和“NC”的端子分别接到输出插座的两个独立插孔的火线上。这里有一个关键细节常见的双位插座duplex outlet背面两个插孔的接线片可能是连通的。你需要用钳子将连接这两个接线片的小金属桥掰断这样才能实现两个插孔独立控制。否则两个插孔会一直同时通断电。最终检查在通电前用万用表通断档检查① 电源输入是否短路② 5V输出是否正常③ 继电器在默认状态下Arduino未启动NC触点是否导通。5.2 上电调试与功能验证首次上电接通9V电源观察Arduino Nano上的电源指示灯是否亮起LCD屏是否背光亮起并显示内容。如果无显示检查I2C地址和接线。检查时间LCD屏第一行应显示当前日期和时间。如果不正确回顾第4.3节的时间设置流程。手动测试继电器你可以临时修改代码在loop()里添加一段测试逻辑让两个继电器每隔10秒动作一次。观察继电器模块上的指示灯是否随之亮灭同时用万用表测量输出插座是否有相应的通断变化。进行此测试时输出插座不要接任何设备模拟定时测试将重启时间设置为当前时间的几分钟后。比如现在是14:25你可以设置通道1在14:26断电14:27恢复。观察时间走到14:26时对应的继电器指示灯是否亮起LCD状态是否更新。时间走到14:27时指示灯是否熄灭。这是验证整个定时逻辑是否正确的关键一步。5.3 现场部署与长期运行建议负载选择确认你的路由器、光猫等设备的功率在继电器额定容量通常10A/250VAC以内。一般网络设备功率很小完全没问题。连接顺序先将重启器的输入插头插入墙上的电源插座再将路由器/光猫的电源插头插入重启器的输出插座。确保重启器自身供电稳定。观察周期部署后的头几天建议在设定的重启时间点通过远程摄像头如果网络恢复或请当地朋友确认设备是否完成了重启动作。也可以观察设备指示灯的状态变化。维护主要维护就是每隔几年检查/更换一次DS3231模块上的CR2032电池。锂电池的寿命通常为3-5年。当发现设备断电再上电后时间重置就说明该换电池了。6. 常见问题排查与进阶优化6.1 问题速查表现象可能原因排查步骤LCD屏无显示1. 电源未接通或接反2. I2C地址错误3. 对比度电位器未调好4. 背光未开启1. 检查5V和GND连接。2. 运行I2C扫描程序确认地址。3. 调节LCD模块背面的电位器。4. 检查代码中是否调用了lcd.backlight()。时间显示不正确或重置1. DS3231电池没电或未安装2. 首次时间设置流程错误3. I2C总线通信故障1. 检查CR2032电池电压应3V。2. 严格按照4.3节流程重新设置时间。3. 检查SDA、SCL线是否接好上拉电阻是否正常。继电器不动作1. 控制信号线接错2. 继电器模块供电错误3. 程序引脚定义错误4. 继电器模块跳线帽未接1. 确认信号线接在IN1/IN2且另一端接VCC。2. 确认继电器模块VCC、GND接对。3. 检查代码中RELAY1_PIN等定义与实际接线是否一致。4. 确认继电器模块上JD-VCC和VCC的跳线帽已接上低电平触发模式。继电器动作但插座无电1. 交流线接错接到常开端子NO2. 插座内部连接片未掰断3. 接线松动1. 用万用表确认继电器NC触点在未动作时导通。2. 检查插座背面火线接线片是否已物理分离。3. 紧固所有螺丝端子。设备运行一段时间后死机1. 电源适配器功率不足或纹波大2. 程序陷入死循环或内存泄漏罕见3. 继电器动作干扰导致MCU复位1. 更换质量更好的9V/1A电源。2. 在代码中增加看门狗Watchdog复位功能。3. 在7805输入输出端并联更大的滤波电容如470uF。6.2 进阶优化思路这个基础版本已经非常可靠但你可以根据需求进行增强增加手动触发按钮在外壳上增加一个按钮连接到Arduino的某个引脚。当按下按钮时可以立即执行一次重启流程而不用等到预定时间。这在临时需要重启网络时非常方便。网络状态检测智能化这是更高级的玩法。可以增加一个ESP8266或ESP32模块让重启器连接Wi-Fi。程序可以定期Ping一个外网地址如8.8.8.8如果连续多次Ping失败则判断为网络故障自动触发重启而不是傻等每天一次的定时任务。这实现了真正的“按需重启”。状态上报与远程控制结合上面的网络模块可以通过MQTT协议将设备状态时间、继电器状态、网络状态上报到家庭自动化平台如Home Assistant甚至可以从平台远程手动触发重启。多时段与随机化修改程序支持设置多个重启时段。或者在设定的重启时间窗口内加入一个随机延迟比如0-5分钟避免同一小区内多个类似设备同时重启对局部网络造成微小冲击。功耗进一步优化目前LCD屏是常亮的。可以修改程序让LCD屏只在有按键操作时亮起一段时间后自动关闭背光可以节省少量电能。这个项目最让我满意的地方在于它的“简单粗暴”和“绝对可靠”。它不依赖任何云服务不依赖家庭主网络仅仅依靠一个精准的时钟和一段简单的逻辑就解决了一个实实在在的痛点。在部署到佛罗里达的度假屋后整个夏季我再也没有收到过智能温控器离线报警。这种用几十元成本和一晚上手工时间换来的安心感正是DIY乐趣的核心所在。如果你也受困于不稳定的网络设备不妨动手做一个它比你想象的要简单也更有用。