ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

ESP32-S3水下机器人遥控平台:硬件选型、软件架构与防水实战

2026/9/24 9:43:52 拓冰建站 浏览量
ESP32-S3水下机器人遥控平台:硬件选型、软件架构与防水实战 1. 项目缘起与整体方案拆解1.1 为什么选择ESP32-S3做水下遥控平台做水下机器人这件事我前前后后折腾了差不多两年。最早用的是STM32F103加NRF24L01的方案2.4G信号在水面衰减得厉害稍微下潜半米就断连体验极差。后来换过树莓派加图传模块视频延迟高得离谱而且功耗大电池续航撑不住二十分钟。直到ESP32-S3出来我才觉得找到了一个真正适合这个场景的主控芯片。ESP32-S3的核心优势在于三点第一它原生支持2.4GHz Wi-Fi和蓝牙5.0Wi-Fi的穿透力和带宽在近水面场景下完全够用第二它带向量指令加速能跑轻量级的图像处理任务配合OV5640这类摄像头模组可以直接输出JPEG格式的图传数据第三它的GPIO数量和PWM通道足够驱动多个舵机、电机和传感器不需要额外挂一堆扩展芯片。这三点加在一起基本上就是一个水下机器人主控的理想形态。我最终确定的方案是ESP32-S3作为主控负责Wi-Fi通信、视频采集、传感器读取和执行器控制OV5640摄像头模组通过DVP接口连接输出QVGA或VGA分辨率的JPEG图像压载水舱用一个微型水泵加电磁阀来实现注排水控制潜艇的浮沉推进系统用两个有刷电机加舵机实现方向和深度微调。整个系统由一块3.7V 2000mAh锂电池供电通过升压模块给ESP32-S3提供5V电机单独走一路供电避免干扰。这个方案最大的好处是“单芯片搞定所有事”。以前用STM32的时候通信、视频、控制要分三块板子接线复杂、故障点多。现在一块ESP32-S3开发板就能覆盖全部功能体积缩小了至少一半对于潜艇这种空间极其有限的应用来说这是决定性的优势。1.2 水下场景对无线控制的特殊要求很多人做遥控车、遥控船的经验直接搬到水下会翻车因为水对2.4GHz信号的衰减是空气的几十倍。我实测过ESP32-S3在空气中通信距离能到100米以上但把天线泡在水里超过30厘米就基本没信号了。所以潜艇的通信方案必须做特殊处理。我的做法是把天线引出来固定在潜艇背部的防水舱顶部只露出水面一点点。这样信号通过空气传播衰减就小得多。具体操作是用一根IPEX转SMA的馈线把ESP32-S3板载的陶瓷天线换成外置的2.4GHz全向天线天线座用防水胶密封在舱体顶部。实测下来潜艇在水面下潜10厘米以内天线露出水面的情况下通信距离能稳定在50米左右延迟在20到40毫秒之间对于FPV操控来说完全够用。另一个关键点是Wi-Fi的工作模式。ESP32-S3可以配置为AP模式自己建热点或STA模式连接路由器。我推荐用AP模式因为水下环境没有现成的路由器而且AP模式下手机或电脑直连潜艇少了一层网络跳转延迟更低。具体配置是在代码里调用WiFi.softAP()设置SSID和密码信道选1或11这两个信道干扰相对少带宽设为20MHz而不是40MHz因为20MHz的穿透力更强虽然理论速率低一半但实际图传够用。注意AP模式下ESP32-S3的默认IP是192.168.4.1手机连上后直接访问这个地址就能看到视频流和控制页面。如果你要传视频建议用UDP协议而不是TCP因为UDP没有重传机制延迟更低丢几帧画面比卡顿要好得多。1.3 压载水舱的工作原理与选型考量压载水舱是潜艇浮沉的核心机构原理很简单注水就下沉排水就上浮。但实现起来有几个坑。我最早用的是注射器加步进电机的方案通过推拉注射器活塞来改变水舱容积。这个方案的问题是响应慢而且注射器密封圈在水下容易老化漏水。后来改用微型水泵加电磁阀的方案效果好很多。具体结构是这样的一个50毫升的塑料注射器去掉活塞作为水舱主体底部开一个进水口通过硅胶管连接到一个微型水泵。水泵的另一端连接一个三通电磁阀电磁阀的一个口通向外部水体另一个口通向一个小的储气罐其实就是一段密封的PVC管。当需要下潜时电磁阀切换到外部水体水泵把水抽进水舱需要上浮时电磁阀切换到储气罐水泵把水舱里的水排出去同时储气罐里的空气被吸入水舱改变整体密度。这个方案的关键参数是水舱容积和潜艇总重量的匹配。根据阿基米德原理潜艇要下潜需要排开的水的重量小于潜艇自身重量。我实测的数据是潜艇总重约450克水舱容积50毫升当水舱注满水时额外增加50克重量总重变成500克而潜艇排水体积对应的浮力大约是480克所以能下潜。当水舱排空时总重450克浮力480克净浮力30克能上浮。这个余量留得比较保守实际调试时可以通过配重块微调。提示水泵选型要注意扬程和流量。我用的是一款3.7V微型隔膜泵流量约0.5升/分钟扬程1米。对于50毫升的水舱注满水大约需要6秒排水也差不多。这个速度对于潜艇操控来说偏慢但胜在结构简单可靠。如果你追求快速响应可以换更大流量的泵但功耗和体积都会增加。2. 核心硬件选型与电路连接细节2.1 ESP32-S3开发板的选型与引脚分配市面上ESP32-S3的开发板很多我试过五六款最后锁定在两款上一款是官方ESP32-S3-DevKitC-1另一款是国产的ESP32-S3-WROOM-1模组自制的板子。官方板的好处是引脚定义清晰、文档齐全缺点是尺寸偏大约6cm x 3cm对于潜艇来说有点占地方。自制板可以把尺寸压到4cm x 2.5cm但需要自己处理USB转串口和电源管理。如果你刚开始做我建议先用官方DevKitC-1把功能跑通然后再考虑缩小体积。引脚分配方面我用的方案是这样的GPIO 1到GPIO 4分配给OV5640的DVP数据线D0-D3GPIO 5和GPIO 6给摄像头的XCLK和PCLKGPIO 7给VSYNCGPIO 8给HREFGPIO 9和GPIO 10走I2C给摄像头的SCCB配置接口。电机控制用GPIO 11和GPIO 12走PWM舵机用GPIO 13和GPIO 14。水泵和电磁阀用GPIO 15和GPIO 16通过MOSFET驱动。电池电压检测用GPIO 17接分压电阻。这里有个坑要注意ESP32-S3的GPIO 19和GPIO 20是USB的D和D-如果你要用USB下载程序这两个脚不能占用。另外GPIO 0是BOOT模式选择脚上电时不能拉低否则会进入下载模式而不是正常运行。我在第一版设计时把GPIO 0用来驱动LED结果每次上电都进下载模式排查了半天才发现是这个问题。2.2 OV5640摄像头模组的驱动与配置OV5640是一颗500万像素的摄像头支持JPEG输出这对于ESP32-S3来说非常关键因为如果输出RGB原始数据ESP32-S3的内存根本扛不住。OV5640的JPEG输出模式可以直接输出压缩后的图像QVGA分辨率下一帧大约10到20KBVGA分辨率下大约30到50KBESP32-S3的PSRAM完全能缓冲。驱动OV5640需要用到ESP32-S3的LCD_CAM外设这个外设在ESP-IDF里有现成的驱动库。配置流程大致是先初始化I2CSCCB总线然后通过SCCB写入OV5640的寄存器序列设置分辨率、帧率、JPEG质量等参数。OV5640的寄存器配置比较繁琐我建议直接参考ESP-IDF例程里的ov5640_init函数把里面的寄存器表抄过来然后根据实际效果微调。我实测下来QVGA分辨率下帧率能到15到20帧VGA分辨率下能到8到10帧。对于FPV操控来说15帧已经能用了但如果你要看得更清楚可以降到QVGA但提高JPEG质量。JPEG质量参数在OV5640里是0x44寄存器值越小质量越高、文件越大。我一般设成0x30左右画质和带宽比较平衡。注意OV5640的XCLK需要24MHz的时钟输入ESP32-S3的LCD_CAM外设可以输出这个时钟但需要配置好分频系数。如果XCLK不对摄像头根本不出图。我踩过的坑是分频系数算错了输出的是12MHz结果摄像头一直初始化失败。后来用示波器量了一下才找到问题。2.3 电机驱动与电源管理方案推进电机我用的是两个3.7V有刷空心杯电机型号是720转速约30000转/分钟配合减速比1:4的齿轮组输出转速约7500转/分钟。这个转速对于潜艇来说偏快所以我在PWM上做了限制最大占空比只给到60%。电机驱动用的是DRV8833双路H桥模块支持1.5A持续电流峰值2A对于720电机来说绰绰有余。电源管理是水下机器人最容易出问题的地方。我的方案是一块3.7V 2000mAh锂电池通过一个MT3608升压模块升到5V给ESP32-S3和摄像头供电电机直接接电池3.7V通过MOSFET开关控制。这样做的原因是电机启动时电流冲击很大如果和主控共用一路电源会导致ESP32-S3复位。我实测过电机启动瞬间电流能到1.5A而ESP32-S3的工作电流只有200mA左右压降会导致主控重启。电池电压检测用两个100kΩ电阻分压接到GPIO 17。ESP32-S3的ADC参考电压是3.3V12位分辨率所以电压计算公式是V_bat ADC_value / 4095 * 3.3 * 2。我在代码里每秒钟读一次当电压低于3.4V时触发低电量报警低于3.2V时自动上浮并切断电机电源防止电池过放。3. 软件架构与核心代码实现3.1 Wi-Fi通信协议设计与视频流传输软件部分我分成三个任务Wi-Fi通信任务、视频采集任务、控制任务。Wi-Fi通信任务负责接收手机或电脑发来的控制指令同时把视频流推出去。视频流我用的是UDP协议每帧JPEG数据分成多个UDP包发送每个包最大1400字节避免IP分片包序号和帧序号写在包头里接收端根据帧序号重组。控制指令我用的是简单的文本协议格式是CMD:value\n比如THR:50\n表示油门50%RUD:-30\n表示方向舵左转30%。这种文本协议的好处是调试方便用串口助手就能发指令测试。接收端解析后直接映射到PWM占空比。视频采集任务用ESP-IDF的esp_camera库配置好OV5640后调用esp_camera_fb_get()获取一帧图像然后通过UDP发送。这里要注意的是esp_camera_fb_get()返回的是帧缓冲指针发送完成后必须调用esp_camera_fb_return()释放缓冲否则几次之后就没有可用缓冲了摄像头会卡死。// 视频采集与发送核心代码片段 camera_fb_t *fb esp_camera_fb_get(); if (fb) { // 发送帧头 uint8_t header[4] {0xAA, 0xBB, frame_seq 8, frame_seq 0xFF}; send_udp(header, 4); // 分片发送JPEG数据 int total_len fb-len; int offset 0; while (offset total_len) { int chunk (total_len - offset 1400) ? 1400 : (total_len - offset); send_udp(fb-buf offset, chunk); offset chunk; } esp_camera_fb_return(fb); frame_seq; }3.2 压载水舱的闭环控制逻辑压载水舱的控制我做了闭环用的是一个简单的状态机。潜艇上装了一个MS5837压力传感器通过I2C读取水深数据。状态机有三个状态上浮、下潜、悬停。当接收到下潜指令时状态机进入下潜状态打开电磁阀到外部水体启动水泵注水同时监测水深当达到目标深度时停止水泵关闭电磁阀进入悬停状态。悬停状态下如果水深变化超过10厘米自动微调水泵保持深度稳定。这个闭环控制的关键是压力传感器的校准。MS5837输出的是绝对压力需要减去水面大气压才能得到水深。我一般在每次上电时先读一次压力值作为基准然后后续读数减去这个基准再除以水的密度和重力加速度得到水深。公式是depth (pressure - surface_pressure) / (1000 * 9.8)其中压力单位是帕斯卡深度单位是米。提示MS5837的I2C地址是0x76和OV5640的SCCB地址不冲突可以挂在同一条I2C总线上。但要注意OV5640的SCCB时钟频率不能太高我一般设成100kHz而MS5837可以跑到400kHz。如果共用总线统一用100kHz比较稳妥。3.3 无线控制指令的解析与执行控制指令的解析我放在一个单独的任务里优先级比视频任务低因为控制指令的数据量很小不需要太高的实时性。指令格式是CMD:value\n我用strtok函数按冒号和换行符分割然后查表映射到对应的执行器。执行器映射表是这样的THR对应推进电机PWM范围-100到100负值表示反转RUD对应方向舵舵机范围-100到100ELV对应升降舵舵机范围-100到100BAL对应压载水舱范围-100到100负值表示排水上浮正值表示注水下潜。每个执行器都有独立的限幅和斜率限制防止指令突变导致电机堵转或舵机烧毁。斜率限制的实现方式是每次更新PWM值时不让它直接跳到目标值而是每次增加或减少一个固定步长比如每次变化不超过5%。这样即使操作者猛推摇杆执行器也是平滑响应对机械结构更友好。我实测下来这个斜率限制对于水下机器人特别重要因为水的阻力大突然加速会导致潜艇姿态剧烈变化甚至翻滚。4. 防水结构与装配实操4.1 舱体防水设计与密封处理防水是水下机器人最头疼的问题我前后做了五个版本才做到基本不漏水。最早用的是一个PVC管加橡胶塞的方案下水三分钟就进水了。后来改用亚克力管加O型圈密封效果好很多但亚克力管容易开裂。最终方案是用3D打印的ABS舱体壁厚2毫米接缝处用环氧树脂胶密封舱盖用硅胶O型圈加四个M3螺丝压紧。舱体的设计有几个关键点第一所有穿线孔必须用防水接头我用的是M5的尼龙防水接头内部灌满硅胶密封胶第二舱盖的O型圈槽要设计成梯形而不是矩形这样O型圈受压时能更好地填充间隙第三舱体内壁要涂一层三防漆防止冷凝水导致电路短路。我实测下来这个方案在3米水深下泡两个小时舱内湿度只有5%左右完全没问题。注意ABS材料吸水率比PVC高长期泡水会轻微膨胀。如果你要做长期水下作业建议用PETG或者尼龙材料打印舱体吸水率更低。另外3D打印的层间结合力不如注塑件打印时要把层高设小一点0.1毫米填充率设高一点80%以上增加强度。4.2 重心与浮心配平技巧潜艇在水下的姿态稳定性取决于重心和浮心的相对位置。重心必须低于浮心潜艇才能自动回正不会翻覆。我的做法是在舱体底部粘一块30克的铅块作为配重把重心压到浮心下方约1厘米处。浮心位置取决于潜艇的排水体积分布一般来说舱体中部偏上的位置是浮心。配平的过程是这样的先把潜艇放进水里观察它漂浮的姿态。如果船头翘起说明重心偏后需要把电池往前移如果船头下沉说明重心偏前电池往后移。调整到潜艇基本水平后再检查横滚稳定性用手把潜艇侧倾30度松手后如果它能自动回正说明重心够低如果回正很慢或者不回正就需要在底部加配重。我踩过的坑是配重加太多导致潜艇净浮力不足怎么排水都浮不起来。后来算了一下配重不能超过总浮力的10%否则浮力余量太小。我的潜艇总浮力约480克配重控制在40克以内留出至少30克的净浮力余量。4.3 天线布置与信号优化天线布置是决定通信距离的关键。我试过三种方案第一种是把天线完全放在舱内信号极差水面下10厘米就断连第二种是把天线穿过舱壁引出来但穿线孔密封不好漏水第三种是把天线固定在舱体顶部的防水天线座里天线座用环氧树脂粘在舱盖上馈线通过防水接头进入舱内。第三种方案效果最好通信距离能到50米以上。天线座的选择也有讲究。我用的是SMA母座加2.4GHz全向天线天线增益3dBi。如果你追求更远的距离可以换5dBi的棒状天线但体积会大一些。天线的极化方向也要注意潜艇上的天线是垂直极化手机或遥控器的天线也要垂直这样极化匹配信号最强。如果手机横屏操作天线变成水平极化信号会衰减10dB以上。提示2.4GHz信号在水面的反射很强会导致多径干扰。我实测发现把天线稍微倾斜15度左右可以减少水面反射的影响信号更稳定。另外Wi-Fi信道选1或11避开中间信道因为中间信道容易被其他设备干扰。5. 调试过程中的典型问题与排查5.1 视频卡顿与延迟问题的排查视频卡顿是最常见的问题原因可能有很多。我遇到过的几种情况第一种是Wi-Fi带宽不够UDP包丢失严重。排查方法是看接收端的丢包率如果超过10%就要降低视频分辨率或JPEG质量。第二种是ESP32-S3的内存不足帧缓冲分配失败。排查方法是看串口日志里有没有fb_get failed的报错如果有就要减少帧缓冲数量或降低分辨率。第三种是摄像头XCLK不稳定导致图像数据错乱。排查方法是用示波器量XCLK引脚看频率是否稳定在24MHz。我最终的配置是QVGA分辨率、JPEG质量0x30、帧率15帧、UDP包大小1400字节。这个配置下视频延迟在30到50毫秒之间丢包率低于5%对于FPV操控来说完全够用。如果你要传VGA延迟会增加到80到100毫秒操控手感会明显变差。5.2 压载水舱响应慢的优化压载水舱响应慢的问题我折腾了很久。最初用50毫升水舱加0.5升/分钟的水泵注满水要6秒排水也要6秒潜艇从水面到下潜3米需要十几秒操控体验很差。后来我换了1.5升/分钟的水泵注排水时间缩短到2秒响应快了很多。但新问题来了水泵电流从200mA增加到800mA电池续航从40分钟降到20分钟。权衡之后我采取了一个折中方案用1升/分钟的水泵注排水时间约3秒电流约500mA续航约30分钟。同时优化了控制逻辑在下潜和上浮时水泵全速运行在悬停微调时水泵用PWM降速运行减少电流消耗。这样既保证了响应速度又兼顾了续航。注意水泵的进水口一定要加滤网防止水中的杂质堵塞泵体。我最早没加滤网结果水里的泥沙把泵卡死了潜艇直接沉底。后来用100目的尼龙滤网包住进水口再也没有堵过。5.3 无线信号中断的应急处理无线信号中断是水下机器人最危险的情况因为潜艇可能失控沉底或漂走。我做了三重保护第一信号丢失超过2秒自动进入悬停状态保持当前深度第二信号丢失超过10秒自动排水上浮到水面第三信号丢失超过30秒自动切断电机电源只保留Wi-Fi信标等待重新连接。这个逻辑的实现是在Wi-Fi通信任务里加一个看门狗定时器每次收到有效指令就重置定时器。如果定时器超时就触发相应的应急动作。我实测下来这个机制救过好几次潜艇有一次手机没电了潜艇自动上浮到水面我划船过去捡回来的。5.4 常见问题速查表问题现象可能原因排查方法解决方案视频卡顿严重Wi-Fi带宽不足查看丢包率降低分辨率或JPEG质量摄像头不出图XCLK频率不对示波器量XCLK检查分频系数潜艇无法下潜水舱漏水或水泵故障检查水舱密封更换密封圈或水泵电机启动时主控复位电源干扰示波器量5V电源电机和主控分开供电通信距离短天线布置不当检查天线位置天线引出水面垂直极化潜艇姿态不稳重心偏高观察漂浮姿态底部加配重降低重心电池续航短水泵或电机功耗大测电流优化控制逻辑降速运行6. 实测数据与性能评估6.1 通信距离与延迟实测我在一个面积约200平方米的池塘里做了通信距离测试。测试条件是潜艇天线露出水面约5厘米手机在岸边高度约1.5米。实测结果是在无遮挡的情况下通信距离能到60米延迟在25到40毫秒之间在有树木遮挡的情况下通信距离降到30米左右延迟增加到50到80毫秒。如果潜艇下潜到天线完全没入水中通信距离骤降到5米以内基本不可用。这个数据说明天线露出水面是保证通信距离的关键。我在实际操控时一般让潜艇保持在水面下10厘米以内天线刚好露出水面这样既能看清水下情况又能保证通信稳定。如果要做深潜就需要考虑有线通信或者声呐通信方案了Wi-Fi在水下确实力不从心。6.2 下潜深度与浮沉响应时间压载水舱的实测数据水舱容积50毫升水泵流量1升/分钟注满水时间约3秒排空时间约3秒。潜艇从水面下潜到3米深度需要约8秒包括注水和下潜过程从3米上浮到水面需要约6秒。最大下潜深度我测试到5米再深的话水压会导致舱体轻微变形O型圈密封效果下降有渗水风险。浮沉响应时间主要受水泵流量和水舱容积影响。如果你要更快的响应可以增大水泵流量或减小水舱容积但前者增加功耗后者减少浮力调节范围。我的建议是水舱容积取总浮力的10%到15%水泵流量取1到1.5升/分钟这个组合在响应速度和功耗之间比较平衡。6.3 电池续航与功耗分析整机功耗实测ESP32-S3加摄像头约250mA水泵约500mA运行时电机约800mA全速运行时舵机约100mA每个。电池是3.7V 2000mAh实际可用容量约1800mAh。如果水泵和电机同时运行总电流约1.5A续航约1.2小时如果只是巡航电机半速、水泵间歇运行总电流约600mA续航约3小时。这个续航对于一般玩耍来说够用了但如果你要做长时间水下作业建议换更大容量的电池或者用两块电池并联。我试过用两块2000mAh电池并联续航翻倍但重量增加了80克需要重新配平。另外电池的放电曲线要注意3.7V锂电池在3.4V以下时电压下降很快所以低电量报警要设得早一点我一般设3.5V报警3.3V强制上浮。7. 后续扩展方向与个人经验7.1 可以增加的传感器与功能这个平台的可扩展性很强ESP32-S3还有不少空闲的GPIO和通信接口。我后续打算加几个传感器一个是TSL2591光照传感器用来测量水下光照强度辅助判断深度一个是GPS模块虽然水下没信号但潜艇上浮到水面时可以记录位置防止漂丢还有一个是9轴IMUMPU9250用来做姿态稳定控制让潜艇在悬停时自动保持水平。软件方面我打算加一个简单的PID控制器用IMU数据做姿态闭环用压力传感器数据做深度闭环。这样潜艇就能自动保持深度和姿态操作者只需要控制方向和速度操控难度会大大降低。另外我还想加一个SD卡模块用来记录水下视频和传感器数据方便事后分析。7.2 从遥控到自主控制的演进思路遥控潜艇玩久了自然会想让它自主运行。我的思路是分三步走第一步加装IMU和压力传感器实现深度和姿态的自动保持第二步加装前视声呐或红外测距实现避障第三步加装水下摄像头和图像识别模块实现目标跟踪。每一步都需要大量的调试和测试但ESP32-S3的计算能力足够支撑这些功能。不过要提醒一句水下自主控制比空中或地面难得多因为水的动态特性复杂传感器噪声大通信受限。我建议先从简单的定深悬停做起把PID参数调好再逐步增加功能。不要一上来就搞全自主很容易翻车。7.3 我踩过的坑与给你的建议最后分享几个我踩过的坑希望能帮你少走弯路。第一个坑是防水没做好第一次下水就烧了一块ESP32-S3后来所有电路板都涂了三防漆接缝处用硅胶密封再也没出过问题。第二个坑是电源干扰电机和主控共用电源导致主控频繁复位后来分开供电解决了。第三个坑是天线布置最早把天线放在舱内信号差得没法用后来引出水面才解决。第四个坑是配重过度潜艇浮不起来后来算清楚浮力余量才调好。如果你刚开始做这个项目我的建议是先用开发板在桌面上把Wi-Fi通信、视频采集、电机控制都跑通再装进舱体做防水测试最后下水调试。不要一上来就做整机分模块验证能省很多时间。另外多备几块ESP32-S3和摄像头模组调试过程中烧板子是很正常的事。这个项目我从零开始做了差不多三个月中间经历了无数次失败和返工但最终做出来的成品还是挺有成就感的。ESP32-S3这个芯片确实强大单芯片就能搞定Wi-Fi通信、视频采集和实时控制对于水下机器人这种空间和功耗都受限的场景来说是非常合适的选择。如果你也在做类似的项目希望这篇分享能给你一些参考和启发。