首页 / 资讯中心 / 文章详情

基于ESP32的智能太阳能路灯设计与实现

基于ESP32的智能太阳能路灯设计与实现 ★ FEATURED ARTICLE
路灯是城市里最容易忽略却最离不开的基础设施之一。传统路灯布线成本高、维护靠人工巡检、白天太阳再好晚上也照旧拉闸。我花了两周时间基于ESP32做了一套智能太阳能路灯的完整方案光控电路决定什么时候亮锂电池精细监测防止过充过放无线视频监控直接看现场画面还有配套APP随时调参。这套方案硬件加软件都能落地低成本、可量产也能当课程设计和嵌入式入门实战项目。下面我把整个设计和踩过的坑完整拆出来从系统架构到每一条ADC采样代码全部按可直接复制的标准来写。整个项目跑下来可以用“模块化硬件 轻量化协议 看板式APP”来概括。ESP32是主控核心太阳能板负责取电锂电池负责储能光照传感器负责环境感知摄像头负责现场画面后端用MQTT做数据和视频通道前端App负责控制和展示。听起来模块很多但选型和接口全部向“少引脚、低功耗、易调试”靠拢。1. 整体系统设计与核心思路1.1 用ESP32做路灯主控底气在哪很多人一听路灯第一反应是STM32或者51单片机但ESP32在这个场景几乎是碾压级的。先说成本ESP32模组批量采购价压到十块钱以内但片上集成了双核240MHz CPU、WiFi、蓝牙、ADC、触摸引脚、RTC、CAN控制器外设丰富度远超同价位MCU。再说联网能力路灯的核心诉求是感知和控制无线化ESP32自带WiFi模块省掉外接ESP8266或者透传模块的麻烦单芯片把“采数据、联网、跑协议栈”全干完了。功耗这块ESP32也有讲究。阳光下跑全速没毛病阴雨天要靠电池余粮我用了Modem Sleep和Light Sleep搭配视频关闭状态整机功耗能压到0.8W左右实际测试夜间纯光控模式连20Wh的小电池都能撑两三天。当然视频监控开启时功耗会飙升到1.5W以上这块我会在第五节单独讲怎么取舍。从开发效率来说ESP32直接吃Arduino生态和ESP-IDF库函数齐全OTA升级、MQTT客户端、摄像头驱动都有现成的实现两周出原型完全来得及。A同学试过用51方案做同款光调TCP/IP协议栈就折腾了一周半ESP32这边一个小时就出活了。1.2 硬件架构的模块划分整个系统我拆成六个功能块每块单独设计、单独测试再合体联调出问题好定位。电源管理模块太阳能板输入经过降压稳压芯片转为电池充电电流电池再通过升压芯片稳定输出5V/3.3V给系统供电这一块决定整个路灯的续航天花板。感知模块光照传感器我用的BH1750实时读取环境光强度夜晚自动开灯、白天自动关灯还可以叠加阈值延时避免瞬时遮挡误触发。电量监测模块锂电池电压和电量百分比直接关系到设备续航判断我用INA226做库仑计采样同时用ESP32内部ADC做双保险。控制模块MOS管驱动电路控制LED灯板的开关支持PWM调光可以根据不同时段前半夜全亮、后半夜半亮自动调节亮度。无线视频模块ESP32-CAM子板负责抓拍和视频流推送通过WiFi传到APP端实时查看现场画面同时支持本地SD卡存储。人机交互模块手机APP通过MQTT协议下发控制指令、接收监测数据不需要复杂的P2P穿透公网代理即可完成。这样的模块化设计还有一个额外好处量产维修时不用整机返工哪块坏了换哪块成本极低。1.3 为什么光照检测不用光敏电阻一开始我把光照检测想简单了直接用光敏电阻加分压电路接ADC结果阴天、晴天倒是能区分但黄昏和黎明的那几个小时输出严重不准。原因是光敏电阻的阻值和照度不是线性关系温度漂移还特别大同一时间两个光敏电阻能差出30%的读数。后来换成了BH1750数字光照传感器。这是I2C接口的芯片直接输出勒克斯Lux单位量程0-65535Lx分辨率能到1Lx完全覆盖路灯场景的需求而且内置16位ADC不需要自己做线性标定。用I2C的另一个好处是抗干扰能力强线束可以拉到1米以上不像模拟信号线一长就被电机或开关电源干扰。注意BH1750有两个I2C地址可选0x23或0x5C如果板子上同时挂了其他I2C设备要注意地址冲突。我这次地址选了0x23和SSD1306 OLED屏错开。1.4 通信协议与数据链路的取舍数据链路我直接选MQTT没有走自定义TCP协议理由是MQTT的发布订阅模型天然适配“多个路灯对应一个APP”的场景每盏路灯是一个client_idAPP通过通配符订阅所有路灯的状态。QoS级别可以保证指令不丢失我用QoS 1下发开关灯指令实测在弱网环境下重试机制能有效避免指令丢失。MQTT broker我用的EMQX可去平台化部署自带心跳和遗嘱机制路灯掉线APP能立刻感知。视频流没走MQTT这玩意儿不适合传大流量二进制。视频走HTTP MJPEG流APP用WebView或者VideoView直接拉取两条链路互不干扰。这是很多新手容易踩的坑非要把视频塞进MQTT最后把整个broker和带宽都搞死了。2. 核心硬件模块的详细设计与选型2.1 太阳能板与充电控制电路太阳能路灯的源头是太阳能板组件不能随便拿一块单晶板直接怼到电池上。我用的是18V/30W的单晶硅太阳能板开路电压在21-22V最大功率点电压约18V之所以选18V而不是6V或12V是因为18V板子才能在阴天弱光下依然输出高于电池电压的充电电压。充电控制芯片我用了CN3791兼容TI的BQ24650方案但便宜很多。这是一颗专门针对太阳能板最大功率点跟踪MPPT的升压型充电管理芯片它通过调节PWM占空比让太阳能板始终工作在最大功率点附近避免传统PWM充电在阴天时电流不足的问题。关键参数设置充电目标电压4.2V针对单节18650锂电池充电电流上限2A由外接采样电阻设定这个用公式算2A/0.05Ω40mV基准电压输入电压范围9V-28V匹配18V板子的输出范围MPPT使能引脚接太阳能板正极分压电阻低于8V时自动进入待机状态实际测试数据晴天正午18V/30W板子对3.7V/10Ah电池组充电峰值充电电流达2.8A略超设定上限因为电池内阻低CN3791限流了日均有效充电容量约22Wh足够支撑10W LED整晚点亮的能耗10W×10小时100Wh配合电池容量和阴天策略足够。2.2 锂电池电压与电量检测方案对比锂电池电量检测是整个系统的“仪表盘”做不好就会出现“前一秒电量20%下一秒直接关机”的尴尬。我先对比了几种方案方案一电阻分压ADC。成本最低但只能测电压不能测电量锂电池放电平台电压在3.7V到3.3V之间变化很平缓无法精确估算SOC荷电状态。而且ESP32内部ADC在3.3V供电时有非线性误差直接测4.2V还得加分压和电压跟随精度雪上加霜。方案二库仑计芯片INA226电压采样。INA226是TI的高侧电流/电压监测芯片可以同时测电池电压和充放电电流内部累加电量库仑计数实现真正的SOC估算精度可以做到5%以内。I2C接口16位ADC电压分辨率0.625mV电流分辨率0.1mA配合合适的采样电阻。价格大概两三块钱性价比极高。方案三MAX17048电量计。号称免校准电量计用专利算法估算SOC但价格贵一倍而且对小容量电池1000mAh适配一般。我最后选了INA226。为什么不用MAX17048因为路灯电池容量通常在10Ah以上INA226的采样电阻功耗可以忽略不计而MAX17048的算法在10Ah级别精度反而不如库仑计直接累加准确。INA226接线注意采样电阻Rshunt我用的是5mΩ5毫欧合金电阻高侧采样放在电池正极和负载之间。I2C地址通过A0/A1引脚组合设定我设成0x40。读取寄存器时要注意先写配置寄存器Configuration Register使能电压和电流同时采样然后读总线电压寄存器Bus Voltage Register和电流寄存器Current Register两个值乘起来就是实时功率。下面是一段ESP32读取INA226的示例代码Arduino框架#include Wire.h #include INA226.h INA226 ina226; void setup() { Wire.begin(21, 22); // 自定义I2C引脚 ina226.begin(0x40); ina226.setMaxCurrentShunt(10.0f, 0.005f); // 设置最大电流10A采样电阻5mΩ ina226.setAverage(INA226_AVERAGE_64); // 64次平均滤掉开关噪声 ina226.setAlertPol(INA226_ALERT_POL_LOW); } void loop() { float voltage ina226.getBusVoltage(); // 单位V float current ina226.getCurrent(); // 单位A float power ina226.getPower(); // 单位W float shuntVoltage ina226.getShuntVoltage(); // 单位mV printf(电池电压: %.3f V, 电流: %.3f A, 功率: %.3f W\n, voltage, current, power); delay(1000); }实测校准用电子负载设定1.000A放电读到的INA226电流是0.998A误差0.2%完全够用。2.3 光照检测模块的精确配置BH1750的数据读取也走I2C。芯片需要大约120ms完成一次采样高分辨率模式所以在循环里不要狂读100ms间隔足够。还要注意一点BH1750分连续测量和单次测量两种模式电池供电场景推荐用单次测量。我用的库是SparkFun_BH1750兼容各种Arduino板初始化时设置MTreg值。默认MTreg69对应测量范围1-65535Lx。想要更低的功耗或者更宽高量程可以调MTreg值范围31-254。高量程场景可以把MTreg调小但分辨率会下降。路灯场景我设MTreg80这样黄昏和正午都能区分。开机后第一次读取会返回一个比较大的值芯片内部校准时间需要在程序初始化完成后延时500ms再读第一个有效值不然判断光控阈值会误判。2.4 LED驱动与MOS管控制电路LED灯板这块我用了一颗大功率白光LED阵列3.3V/10W配合恒流驱动芯片PT4115。PT4115是降压型LED恒流驱动IC输入电压范围6V-30V输出电流由外接电阻设定我用0.1Ω的采样电阻对应1A恒流输出实测LED灯板电压降3.1V功率约3.1W10W灯板降到3W是为了控制电池功耗实际亮度足够夜间照明。控制开关和调光用了两颗AO3400 N沟道MOS管。一颗接LED驱动芯片的EN引脚使能控制实现开关灯一颗接PWM信号实现亮度调节。ESP32的GPIO输出3.3V可以完全开启AO3400其开启电压VGS(th)典型1.35V但为了保险我加了1kΩ栅极串联电阻和10kΩ下拉电阻防止上电瞬间GPIO悬空导致LED闪亮。PWM调光我用了ESP32的LEDC外设频率设20kHz。为什么不用1kHz因为人耳能听到20kHz以下的开关频率造成的啸叫电感啸叫LED灯珠虽然人耳听不到但驱动电感的磁性材料会发出机械噪声。20kHz正好超过人耳听觉上限同时LEDC在这个频率下的占空比分辨率也足够。2.5 无线视频监控的硬件实现视频监控模块我选了ESP32-CAMAI-Thinker版。它自带ESP32-S芯片和OV2640摄像头支持JPEG抓拍和MJPEG视频流像素最高1600x1200在局域网内可以跑流畅的VGA640x48015fps视频流。模块包含一个Micro SD卡槽用于本地录像存储。为什么视频不直接接在主控ESP32上因为ESP32处理视频流会占用大量CPU和内存分享处理光照检测和MQTT协议的能力会被挤占。用独立ESP32-CAM做视频采集通过UART或Socket送给主控ESP32或者更简单——两个ESP32各自独立连WiFi主控只管控制和数据CAM只管视频互不干扰。我在主控和CAM之间用UART通信波特率115200协议很简单主控发“CAPTURE”命令CAM拍摄一张JPEG照片通过UART发送回来。这样设计功耗可控平时CAM处于深度睡眠只有收到命令才唤醒拍照非常适合路灯这种非24小时监控的场景。如果要做实时视频流建议直接用WiFi直连方式CAM模块通过STREAM_URL广播自己的HTTP服务APP直接用WebView访问不需要经过主控中转。3. 软件架构与APP设计3.1 主控ESP32的程序框架主控程序基于Arduino框架FreeRTOS实现三个核心任务光照感知与控制任务每500ms读取一次光照传感器通过滑动平均滤波消除偶发干扰然后与阈值比较决定开灯还是关灯通过LEDC调节PWM亮度。电池管理任务每2秒读取一次INA226计算SOC并调用校准系数修正超过阈值则触发报警剩余电量低于20%时通过MQTT推送低电量告警。MQTT通信任务负责订阅主题、解析指令、发布状态数据同时维护心跳包和遗嘱消息。任务间用FreeRTOS队列传递数据避免全局变量互相覆盖。比如光照传感器任务把测量值打包成结构体发送到队列控制任务从队列接收后决定输出PWM。这样数据流清晰出问题也好排查。主循环轮询的方式我也写过但一旦加入WiFi和MQTT500ms延时经常因为WiFi事件处理被拉长到2秒响应不及时。所以别偷懒直接用多线程任务。3.2 MQTT主题设计与数据协议主题设计是整个通信系统的骨架我按照“设备类型/安装位置/设备ID/属性”的规范来做路灯/光照强度/{device_id} # 发布光照传感器读数单位Lx 路灯/电池状态/{device_id} # 发布电压、电流、SOC、功率 路灯/控制指令/{device_id} # 订阅控制指令ON、OFF、PWM、视频抓拍 路灯/在线状态/{device_id} # 发布在线状态和遗嘱消息 路灯/视频流/{device_id} # 发布视频流URL仅在视频开启时MQTT消息体我用JSON格式因为好解析、好扩展。举一个例子{ device_id: SL01, type: status, payload: { light_lux: 356, battery_voltage: 3.82, battery_current: -0.42, soc: 87, pwm: 200, timestamp: 1735700000 } }订阅端APP需要支持通配符“#”这样一台手机就能订阅“路灯/#”查看所有路灯状态。注意MQTT client_id必须全局唯一多路灯场景不要用默认的随机ID直接用设备ID如SL01、SL02否则会导致broker互相踢线。3.3 APP功能设计与开发路线APP这一层有三种实现路线我对比过微信小程序/公众号H5上线审核相对简单适合个人开发者快速验证但因为视频流和长连接限制流畅度一般。原生Android APPJava/Kotlin适合做深度定制视频流和控制体验最流畅但开发周期长要考虑手机权限适配。MQTT面板型APP如某开源物联网平台APP最快改改配置就能用但定制性差控制界面不灵活。我最后选了原生Android APP基于Android Studio用Java写理由是需要实时视频流叠加MQTT控制而且要做离线缓存和本地推送。核心功能模块设备列表页罗列所有接入的路灯设备显示在线/离线状态点击进入详情。设备详情页显示光照强度、电池电压、电量SOC、功率等实时数据以折线图方式展示历史趋势本地SQLite存储历史数据断网也能看。控制面板开关灯、PWM亮度调节滑块、视频抓拍按钮、视频流开关。设置页调节光照阈值、低电量报警阈值、设备校时等参数。APP通过Eclipse Paho Android Client库连接MQTT broker视频流用WebView加载MJPEG地址来显示。Paho库自带断线自动重连机制配合MQTT遗嘱消息能实时感知路灯掉线。下面是APP端连接MQTT并订阅主题的核心代码JavaMqttClient mqttClient new MqttClient(tcp://broker_ip:1883, APP_DEVICE, new MemoryPersistence()); MqttConnectOptions options new MqttConnectOptions(); options.setCleanSession(false); options.setConnectionTimeout(10); options.setKeepAliveInterval(20); options.setWill(new MqttTopic(路灯/在线状态/RoadLight1), new byte[]{0}, 0, true); mqttClient.setCallback(new MqttCallback() { Override public void messageArrived(String topic, MqttMessage message) { runOnUiThread(() - updateUI(topic, message.toString())); } Override public void connectionLost(Throwable cause) { /* 自动重连逻辑 */ } Override public void deliveryComplete(IMqttDeliveryToken token) { } }); mqttClient.connect(options); mqttClient.subscribe(路灯/#, 1);3.4 本地显示与调试利器OLED屏虽然APP能看数据但现场调试总掏手机太麻烦。我在主控板上加了一块0.96寸OLED显示屏SSD1306通过I2C挂在同一条总线上显示四行滚动信息第一行当前光照值Lx和PWM占空比第二行电池电压和电流第三行SOC百分比和低电量报警状态第四行MQTT连接状态和WiFi信号RSSIOLED在灯光下亮度也够功耗很低20mA左右但要注意别让它一直全亮屏我用5秒刷新一次、无操作10分钟后关屏省电效果明显。4. 光照检测与电池电量计算的实操细节4.1 光照阈值的标定方法光照传感器输出的数值本身没有绝对意义必须在实际场景标定阈值。我在不同时间点记录了传感器读数正午阳光直射约32000Lx阴天白天约800-3000Lx黄昏日落前30分钟约120-300Lx夜晚无月光约0-2Lx夜晚路灯亮起约5-20Lx开灯阈值我设在80Lx关灯阈值设在350Lx中间的区间是滞回区间防止光在阈值附近跳动导致继电器反复通断。以80Lx和350Lx为例当光照从亮变暗从1000Lx降到200Lx时还没到80Lx所以不动作继续降到80Lx以下才开灯从暗变亮同理要超过350Lx才关灯。这样上下阈值之间至少差4倍抗抖效果极好。此外实际路灯还要考虑“黄昏延时”逻辑如果光照在临界线上跳绳比如被云层遮挡露出一丝阳光可以用软件滤波来处理比如连续3次采样都低于80Lx才执行开灯单次瞬时低于80Lx不动作。4.2 锂电池SOC的计算模型直接用电压估算SOC容易翻车我的做法是“库仑计为主电压校准为辅”。库仑计算法SOC 初始SOC ∫(I_bat dt) / C_bat需要INA226实时累加电流和时间片。ESP32上我开了1秒定时器每秒读取一次电流值乘以1秒再累加到累计电量变量里。电压校准法当电池处于长时间静置状态比如连续5分钟电流小于50mA认为电池电压已经稳定用当前电压查表校正SOC。我用的3.7V锂电池放电曲线分段如下4.15V以上电量约100%4.05V约90%3.92V约75%3.80V约50%3.70V约25%3.55V约10%3.30V以下基本放空必须保护性关机配合INA226的库仑计累计实际误差控制在±5%以内。低电量阈值我设在20%低于20%强制降亮度低于10%彻底关闭LED只保留控制板待机最大程度保护锂电池寿命。4.3 ESP32内部ADC的注意点虽然用INA226做主采样我还保留了一个ESP32内部ADCGPIO34接电池电压分压作为备用。实测发现ESP32 ADC有两大坑3.3V供电的ADC基准电压是内部LDO参考不是外部Vref偏差能到0.1V一定要做多点校准至少两点。GPIO34之类的引脚悬空噪声大需要加100nF电容滤波。校准方法是找一台可调电源给分压电路输入3.2V、3.6V、4.0V、4.2V四个电压点记录ESP32 ADC原始值然后做线性插值得到修正系数。否则直接读ADC会把满电4.2V读成3.9V低电量判断就会提前。4.4 硬件防反接与保险丝设计电池、太阳能板、负载回路的极性接反是烧板子的第一原因。我在电源输入入口做了三个保护一个5x20mm保险丝3A慢断型串在太阳能板正极过流时熔断。一颗SS34肖特基二极管做防反接压降0.3V左右。一颗TVS管SMBJ15A并联在太阳能板输入端吸收雷击浪涌防止高压脉冲击穿CN3791。TVS管的选择要按太阳能板的开路电压来定。18V板子开路电压约22VSMBJ15A击穿电压在16.7V左右可以钳位住大部分感应浪涌同时不会在正常充电电压下漏电导通。5. 实操过程与核心环节实现5.1 7步完整搭建流程动手之前先把材料裱好名称型号/规格数量主控板ESP32 DevKit1视频模块ESP32-CAMOV26401光照传感器BH17501电量计INA226模块1太阳能板18V/30W1锂电池3.7V/10Ah聚合物电池1充电管理CN37911LED灯板3.3V/10W1OLED屏0.96寸 SSD13061MOS管及驱动AO3400等4搭建顺序先把太阳能板和CN3791接好输出接电池确认电池电压能被正常拉高到4.2V万用表测充电电流在预期范围。接LED驱动电路先用直流电源给灯板供电测试EN和PWM调光功能别急着上电池。接I2C总线ESP32 GPIO21→SDAGPIO22→SCL把BH1750、INA226、OLED屏都挂上去跑I2C扫描确认三个地址都在。烧录基础固件调通传感器读取OLED上能看到实时数据了。接着接ESP32-CAM先单独烧录摄像头测试固件确认SD卡初始化正常、视频流能在浏览器访问。在主控上实现UART协议控制和MQTT对接编辑EMQX的ACL权限确保只有合法设备能发布和订阅。最后做整机联调把路灯装到模拟光照箱里测光控逻辑再装到室外实测太阳能充电和电池放电一整夜。5.2 部分核心代码实现光照检测读取和滤波BH1750 lightMeter; float lightValue 0; const float filterCoeff 0.2; // 低通滤波系数 void readLightSensor() { float lux lightMeter.readLightLevel(); lightValue filterCoeff * lux (1 - filterCoeff) * lightValue; Serial.print(Light: ); Serial.print(lightValue); Serial.println( lx); }这个一阶低通滤波的系数很关键。系数越小滤波越平滑但响应越慢。0.2的系数对应约1秒的时间常数对路灯光控这种慢变量刚刚好既能滤掉云层瞬间遮挡的抖动又能保证黄昏时光照下降能及时开灯。LED PWM调光#define LEDC_CHANNEL 0 #define LEDC_TIMER_13BIT 13 #define LEDC_BASE_FREQ 20000 void setupLed() { ledcSetup(LEDC_CHANNEL, LEDC_BASE_FREQ, LEDC_TIMER_13BIT); ledcAttachPin(LED_PIN, LEDC_CHANNEL); } void setLedBrightness(uint8_t brightness) { uint32_t duty (4096L * brightness) / 100; // 0-100%对应0-4096 ledcWrite(LEDC_CHANNEL, duty); }注意13位分辨率的满值是8191但ESP32的LEDC在20kHz频率下建议用8位分辨率0-255这样精度对路灯足够了占空比调整的量化噪声也小。上面用4096是按12位分辨率写的二者语义相同按需调整即可。MQTT数据发布#include PubSubClient.h WiFiClient espClient; PubSubClient mqtt(espClient); void publishStatus() { StaticJsonDocument256 doc; doc[device_id] SL01; doc[lux] lightValue; doc[volt] batteryVoltage; doc[soc] batterySOC; char buffer[256]; serializeJson(doc, buffer); mqtt.publish(路灯/状态/SL01, buffer); }5.3 装调优化与参数标定整机调通后继续做了三项优化把MQTT的心跳间隔从默认的15秒调到30秒降低无效网络流量代价是掉线感知延迟变慢我同时启用了遗嘱消息设备掉线时broker自动推送离线消息到APP弥补了延迟问题。电量的100%校准第一次充满电时记录一个基准值之后每次充电到4.15V以上时自动重置满电量标志。这样长期使用累积误差会被定期清零。增加“电池休眠深度保护”SOC低于10%时彻底断开LED和非必要外设只保留INA226和RTC唤醒让路灯“冬眠”等第二天太阳能板充电充到15%后再自动唤醒。实测这个模式待机电流只有2mA几乎是微安级保护作用明显。5.4 OLED显示屏加持下的现场调试体验调试阶段OLED屏帮了大忙。之前调MQTT连接只能看串口助手人在户外根本看不清楚。现在直接在屏上显示HTTP状态码、MQTT连接日志和WiFi信号强度遇到连接不上问题时一看屏就能定位是IP、网关还是认证的问题。OLED显示模块的驱动我用的u8g2库这个库资料多、字体全就是内存占用稍微大一点。ESP32的320KB RAM完全够用但如果你用的是Arduino Uno这种2KB内存的板子就需要换库了。6. 常见问题与排查技巧实录6.1 问题速查表症状可能原因排查步骤解决方案白天灯不亮晚上也不亮LED驱动EN引脚损坏或电池亏空测电池电压低于3.0V先充电测EN引脚电压是否被拉高更换MOS管补焊驱动电路确保电池SOC10%才允许开灯灯闪烁不停PWM频率太低或电源纹波大用示波器抓LED驱动输出PWM频率升到20kHz电源端并联470uF电解电容光照读数一直为0BH1750接线反或I2C地址冲突跑I2C扫描确认0x23是否存在重新焊接SDA/SCL避免和OLED共用地址电量计显示漂移采样电阻接触不良或未校准检查Rshunt两端电压是否和INA226读数一致重新焊接采样电阻做两点校准MQTT连不上服务器broker IP、端口、账号密码错误先在PC上用MQTT客户端测试同一个broker检查防火墙确认密码配置正确视频流卡顿不流畅WiFi信号弱或带宽不足看RSSI值低于-70dBm属于弱信号调整天线角度改用5GHz频段或降低分辨率到VGA白天正常晚上掉线电池电量耗尽触发保护关机看SOC历史记录增大太阳能板功率或调低夜间亮度OLED不亮I2C地址冲突或复位引脚悬空单独测试OLED模块核对模块地址复位引脚接3.3VAPP收不到数据MQTT主题前缀不匹配在broker后台看订阅列表统一主题命名规范确认订阅通配符正确太阳能板充电电流太小角度不对或灰尘遮挡用万用表测板子短路电流调整板子朝向定期清洁6.2 几个特别的坑第一太阳能板的“24V虚电压”问题。拿万用表测空载电压有22V一接上CN3791就掉到6V这是板子输出电流能力不足的典型表现不是充电控制坏了。判断标准是短路电流至少要在标称电流的80%以上。第二ESP32-CAM的PSRAM必须开启。我在Arduino IDE的Tools目录下选错Flash Mode导致摄像头初始化失败报“Camera init failed”折腾了一晚上才发现是PSRAM未启用。必须要选“Enable PSRAM”选项。第三充电接口和电池之间不能接反。CN3791的BAT引脚直连电池正极但电池本身有极性接反轻则芯片烧毁重则电池鼓包。我以前吃过亏后来所有电源接口都用了防反插端子XH2.54带卡扣物理上杜绝插反可能。第四太阳能板接地问题。金属支架的感应电压在雷雨天能到几十伏不接大地会把TVS管烧穿。虽然城市路灯有避雷针保护但DIY场景还是建议加一块可靠的TVS同时在太阳能板支架底部做等电位连接。6.3 精准调试分享分享一个定位莫名重启的经验某次路灯每天晚上九点准时重启我一开始怀疑是光控逻辑写错后来发现是MQTT每30秒发布一次心跳凌晨正好和夜间全亮模式切换撞在一起ESP32同时处理视频流抓帧、PWM调光、MQTT发布内存暴涨触发看门狗复位。后来我把MQTT发布频率降到30秒一次再把视频抓拍放到独立线程重启问题彻底消失。另一个小技巧是给ESP32加一个手动复位按钮通过EN引脚接地装在防水盒盖里现场调试重启再也不用拔电池线。7. 项目影响与场景扩展这套系统不只是个路灯demo。把光照检测、电池管理、无线监控、远程控制四件事做扎实后它几乎就是一个通用的低功耗物联网节点样板。后续扩展场景很明确庭园灯、草坪灯去掉视频监控把功率降到3W同样的方案直接量产。农业大棚补光灯光照检测从“开/关”变成“调光曲线”根据日照时长动态调整补光强度APP上加一个光积算功能。牧场围栏警示灯视频监控功能保留夜间动物靠近时自动亮灯并拍一张照片触发报警推送到手机。交通临时施工牌使用太阳能供电灯牌的亮度根据环境光自动调整电池低压自动切换为闪烁模式更加省电。灾害监测临时节点摄像头定时抓拍光照异常、电池异常通过MQTT上报后台实现无人值守预警。这些场景的共同点都是“能源约束强、环境变化大、需要远程感知和控制”恰好是我这套系统全部覆盖的。最后说一个我自己用的经验做这种硬件加软件的综合项目一定要先花半天时间把模块单独测试通过再开始联调别指望“接上去就能跑”。我给每个模块画了一张接线图标注清每个引脚的电压范围、I2C地址、串口波特率联调时对着图查问题至少能省一半的排错时间。另外买模块时留好备用件ESP32和BH1750这类小元件容易在焊接过程中损坏一次性买个三五套就能确保项目连贯推进不会因为等一个快递卡壳。这套方案是真正从头到尾跑通了的你按文档走至少要少踩三四个大坑。
阅读完成 · 觉得有帮助?
咨询建站