ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

复刻《星际迷航》三录仪:ESP32手持环境扫描仪DIY全攻略

复刻《星际迷航》三录仪:ESP32手持环境扫描仪DIY全攻略 1. 项目缘起与整体设计思路1.1 为什么选择复刻《星际迷航》中的三录仪《星际迷航》里的三录仪Tricorder大概是科幻史上最深入人心的手持设备之一。它能扫描环境、分析生命体征、探测能量场、记录数据几乎是一个万能传感器平台。我从小就是这部剧的粉丝一直想做一个能拿在手里、真正能用的版本。市面上的复刻品大多只是外观模型按个按钮亮几个灯就完事了没什么实际功能。我想要的是一台真正能采集数据、能显示波形、能存储记录的手持设备外观上尽量贴近原版但内核必须是现代电子技术。这个项目命名为 Tricoder-REV2是因为第一版做得太粗糙了。REV1 用的是洞洞板焊接飞线满天飞外壳是3D打印的粗糙件电池续航不到两小时屏幕在阳光下基本看不清。REV2 的目标很明确重新设计PCB、优化电源管理、换用高亮度显示屏、重新设计外壳结构让它从“能跑的原型”变成“可以日常携带的成品”。适合谁来参考这个项目如果你有基本的电子焊接经验会用Arduino或ESP32开发板了解I2C和SPI通信协议那这个项目完全可以在两到三周内完成。如果你是完全的新手也不用怕我会把每个环节拆得足够细包括元器件选型、焊接顺序、调试方法都讲清楚。这个项目涉及的知识面很广传感器融合、电源管理、嵌入式UI、结构设计做完之后你对整个嵌入式系统的理解会上一个台阶。1.2 核心功能定义与方案选型在动手之前我先列了一份功能清单然后逐项确定技术方案。这个过程很关键因为选型决定了后续所有工作的复杂度。环境扫描功能是核心。我选用了BME680传感器它能同时测量温度、湿度、气压和空气质量VOC。相比分开用DHT22加BMP280的方案BME680虽然贵一些但一颗芯片搞定四项数据I2C接口只占两个引脚PCB布局也简单很多。实测精度方面温度误差在±0.5°C以内气压误差±0.6hPa对于手持设备来说完全够用。生命体征探测这块我纠结了很久。最初想用MAX30102心率血氧模块但它需要手指紧贴传感器使用场景受限。后来改用MLX90614红外测温传感器可以非接触测量体表温度配合一个简单的红外接近传感器判断是否有人体靠近。虽然不能测心率和血氧但作为“生命探测”功能来说检测到前方有体温37°C左右的物体已经能达到科幻感的效果了。电磁场探测用了简单的电感线圈加运算放大器方案。一个100mH的电感配合LM358运放可以检测到附近电线、变压器产生的低频磁场。灵敏度通过一个10K电位器调节输出接到ESP32的ADC引脚。这个方案成本不到五块钱但效果出奇地好靠近手机充电器时读数明显跳动。主控选了ESP32-WROOM-32模块。理由有三第一双核240MHz处理传感器数据和驱动屏幕绰绰有余第二自带WiFi和蓝牙后续可以扩展数据上传功能第三Deep Sleep模式下功耗只有10微安左右对电池续航至关重要。相比Arduino NanoESP32的ADC精度稍差但12位分辨率对于这个项目来说够用了。显示用了1.3寸IPS彩屏ST7789驱动分辨率240x240SPI接口。之前REV1用的OLED在户外几乎看不见IPS屏亮度能到400尼特阳光下也能看清。而且IPS的可视角度大从侧面看也不偏色。电源管理是REV2改进最大的地方。用了TP4056充电模块加DW01保护芯片电池选了一块2000mAh的锂聚合物电池尺寸刚好能塞进外壳。加了一个物理开关控制总电源另外用ESP32的Deep Sleep功能实现软件开关机。实测下来正常使用屏幕常亮、传感器每秒采样一次能撑6小时左右如果开启省电模式屏幕30秒无操作自动熄灭、传感器降频到每5秒一次可以坚持将近20小时。外壳用Fusion 360设计PETG材料打印。PETG比PLA韧性好不容易摔裂而且耐温到80°C夏天放车里也不会变形。外壳分前后两半用M2螺丝固定内部有专门的卡槽固定PCB和电池避免晃动。2. 核心细节解析与实操要点2.1 电路设计中的关键决策PCB设计这块我踩了不少坑这里详细说一下。整个电路分成三块电源管理区、数字信号区、模拟信号区。电源管理区放在板子最左边包括TP4056充电电路、DW01保护电路、AMS1117-3.3稳压芯片。数字信号区在中间ESP32模块、屏幕接口、I2C传感器接口都在这里。模拟信号区在右边只有电磁场探测电路尽量远离数字信号减少干扰。注意ESP32的ADC2引脚在WiFi开启时无法使用所以电磁场探测的输出必须接到ADC1的引脚上比如GPIO32、GPIO33、GPIO34、GPIO35、GPIO36、GPIO39。我一开始接在GPIO25上结果WiFi一开读数就乱跳排查了半天才发现这个问题。电源部分有个细节值得说TP4056的充电电流通过一个电阻设定公式是 I 1200 / R。我用了1.2K的电阻充电电流就是1000mA。2000mAh的电池从空到满大约需要2.5小时。如果想充快点可以用0.8K电阻电流1.5A但发热会明显一些。我实测1A充电时TP4056表面温度在45°C左右可以接受。ESP32的供电是3.3V但它的峰值电流能到500mA尤其是在WiFi发射的瞬间。AMS1117最大输出1A压差1.1V用3.7V锂电池供电时输出3.3V没问题但效率只有不到70%多余的能量都变成热了。如果你想让续航更长可以换用MP1584这样的开关电源模块效率能到90%以上但电路会复杂一些需要加电感和续流二极管。我权衡之后还是用了AMS1117因为简单可靠而且外壳内有足够的空间散热。屏幕的背光LED需要单独的限流电阻。ST7789模块通常自带一个10欧姆的限流电阻但如果你买的是裸屏一定要自己算。背光LED的正向压降大约3.0V工作电流20mA电源3.3V那么限流电阻 R (3.3 - 3.0) / 0.02 15欧姆。我用了10欧姆电流稍大一些亮度更高LED寿命会短一点但影响不大。2.2 传感器校准与数据处理BME680的原始数据不能直接拿来用必须经过校准。温度读数受ESP32自身发热的影响因为传感器离主控太近。我的做法是在ESP32和BME680之间开了一条1mm宽的隔热槽PCB上挖空减少热传导。软件上再做一次补偿设备开机后先静置5分钟记录温度读数然后减去一个固定的偏移量。这个偏移量因设备而异需要自己标定。我的这台偏移量是1.8°C也就是说传感器读数比实际环境温度高1.8度。气压读数用来估算海拔高度公式是 h 44330 * (1 - (P / P0)^0.19)其中P0是海平面气压1013.25hPa。这个功能在户外徒步时挺有用的但要注意天气变化会影响气压进而影响高度读数。我一般会在出发前用已知海拔校准一次。空气质量VOC的读数需要预热。BME680内部有一个加热器每次测量前要把气体传感器加热到300°C左右这个过程大概需要20毫秒。刚开机时读数不准要等几分钟稳定下来。我在代码里加了一个标志位开机后前100次读数只显示“预热中”不显示具体数值。MLX90614红外测温的视场角是90度也就是说它测量的是一个圆锥形区域内的平均温度。测量距离和光斑大小的关系是光斑直径 2 * 距离 * tan(45°)。在10厘米距离上光斑直径约20厘米这个范围比较大容易把背景温度也测进去。我的经验是尽量靠近目标5厘米以内比较准。另外MLX90614出厂时已经校准过不需要自己调但要注意它的读数受环境温度影响内部有补偿算法一般不需要额外处理。电磁场探测电路需要调零。LM358的输入端有失调电压最大7mV放大100倍后就是0.7V的误差。我在运放的同相输入端加了一个10K电位器调节电位器让输出在无磁场时接近1.65VADC量程的一半。这样正负磁场都能检测到。调节方法很简单把设备拿到远离电线的地方慢慢转电位器直到屏幕上的磁场读数在0附近波动。2.3 外壳设计与结构优化外壳设计我改了五版才满意。第一版太厚握持感差第二版太薄电池放不进去第三版按钮位置不对单手操作别扭第四版散热不好ESP32过热降频第五版才把所有问题解决。具体尺寸是长150mm宽80mm厚25mm。这个尺寸刚好能一手握住拇指自然落在按钮区域。外壳前部有一个2mm厚的亚克力窗口保护屏幕用双面胶固定。后部有一个可拆卸的盖板用两颗M2螺丝固定方便更换电池。实操心得3D打印时外壳的前后两半要分别打印打印方向很重要。前壳的屏幕窗口朝上打印这样表面光滑后壳的平面朝下打印附着面积大不容易翘边。层高用0.2mm壁厚1.2mm三层填充率20%就够了。PETG的打印温度230°C热床80°C速度40mm/s太快了层间结合力不够。内部布局上PCB用四颗M2铜柱固定在后壳上铜柱高度5mm。电池放在PCB下方用双面胶泡棉固定防止晃动。电池和PCB之间垫一层0.5mm厚的绝缘纸防止引脚刺穿电池。屏幕排线从PCB上方绕过用一块3mm厚的泡棉压住避免排线松动。按钮用了三个6x6mm的轻触开关分别对应“上”、“下”、“确认”。按钮帽是3D打印的高度8mm直径6mm顶部有防滑纹路。按钮和外壳之间留了0.3mm的间隙按下去手感清脆不会卡滞。散热方面我在ESP32上方开了一排直径2mm的散热孔共8个。实测连续工作1小时后外壳表面温度在38°C左右比环境温度高10度可以接受。如果你在更热的环境下使用可以把散热孔开大一些或者加一个小型散热片。3. 实操过程与核心环节实现3.1 元器件采购与成本清单这个项目的元器件不算多但有几个关键件需要特别注意采购渠道。我把完整的清单和参考价格列出来方便你直接抄作业。元器件型号/规格数量参考单价备注主控模块ESP32-WROOM-32125元建议买带PCB天线的版本环境传感器BME680145元注意买正品山寨的精度差红外测温MLX90614160元BAA版本5V供电显示屏ST7789 1.3寸IPS130元240x240SPI接口充电模块TP4056带保护15元要买带DW01保护的版本稳压芯片AMS1117-3.311元SOT-223封装运放LM35811元DIP-8或SOP-8电感100mH13元工字电感直径10mm电池2000mAh锂聚合物125元尺寸要量好别买大了轻触开关6x6x5mm30.5元手感要试太硬的不行电位器10K11元单圈可调电阻电容若干-5元具体值见原理图PCB双面10x15cm130元嘉立创打样外壳PETG打印115元材料费螺丝铜柱M2若干5元铜柱5mm高总计大约250元左右。如果你手头已经有ESP32和屏幕成本能降到150元以内。PCB打样建议一次打5片因为焊接过程中可能会损坏多打几片备用。我第一批打了5片焊坏了两片主要是ESP32的引脚太密拖焊时连锡了。3.2 PCB焊接与调试步骤焊接顺序很重要一定要先焊矮的元件再焊高的元件否则高的元件会挡住矮的元件的焊盘。我的顺序是先焊电阻电容和稳压芯片再焊TP4056和DW01然后焊ESP32模块接着焊传感器接口和屏幕接口最后焊按钮和电感。ESP32模块的焊接是难点。它的引脚间距是1.27mm比标准DIP的2.54mm密一倍。我的方法是先用烙铁在焊盘上镀一层薄锡把模块放上去对准然后用烙铁头压住引脚侧面让锡熔化连接。不要用锡丝直接往引脚上怼那样很容易连锡。如果连锡了用吸锡线清理或者涂一点助焊剂再用烙铁拖开。注意ESP32模块底部有一个大的散热焊盘必须焊接到PCB的对应焊盘上否则散热不好。我的做法是在PCB焊盘上开一个2mm的孔焊接时从背面用烙铁加热锡会从孔里流到正面把模块底部的焊盘和PCB焊盘连在一起。这个步骤需要一点技巧多试几次就熟了。焊接完成后先不要装电池用稳压电源供电测试。把电压调到3.7V限流设到500mA。如果电流超过100mA说明有短路立刻断电检查。正常空载电流应该在20mA左右ESP32在运行但屏幕没亮。如果电流为零检查电源开关和稳压芯片。上电后先用万用表测ESP32的3.3V引脚应该是3.3V±0.1V。如果电压偏低可能是AMS1117坏了或者负载太大。然后测ESP32的EN引脚应该是3.3V高电平。如果EN是低电平ESP32不会启动检查EN引脚的上拉电阻通常10K是否焊好。屏幕测试把ST7789的驱动库装好运行一个简单的显示程序。如果屏幕不亮先检查背光引脚有没有电压。如果背光亮但没图像检查SPI接线SCL、SDA、DC、CS、RST。我遇到过一次屏幕花屏最后发现是SPI时钟太快了从40MHz降到20MHz就正常了。传感器测试用I2C扫描程序确认BME680和MLX90614的地址。BME680的地址是0x76或0x77MLX90614是0x5A。如果扫不到检查上拉电阻4.7K和接线。MLX90614是5V供电的但I2C电平是3.3V兼容的可以直接接ESP32。3.3 固件开发与UI设计固件用Arduino框架开发虽然ESP32也可以用ESP-IDF但Arduino的库更丰富开发速度快。整个固件分成几个模块传感器读取、数据处理、UI渲染、电源管理。传感器读取用了一个定时器每100毫秒触发一次。BME680的读取时间比较长一次完整的测量温度、湿度、气压、VOC需要大约200毫秒所以我把它放在单独的任务里用FreeRTOS的双核特性一个核跑传感器一个核跑UI。这样UI不会卡顿。UI设计上我用了三个页面主页面显示环境数据温度、湿度、气压、空气质量第二页显示生命探测红外温度、接近状态第三页显示电磁场强度波形图。用按钮切换页面长按确认键进入菜单可以调整屏幕亮度、设置省电模式、校准传感器。屏幕刷新率控制在30帧左右再高没必要还费电。我用了TFT_eSPI库它支持DMA传输刷新速度快CPU占用低。波形图用了一个环形缓冲区存最近100个采样点每次刷新时重绘整个波形。实测下来30帧的刷新率下ESP32的CPU占用大约40%还有余量做其他事情。电源管理是固件的重点。我实现了三级省电模式一级是屏幕变暗亮度从100降到30二级是屏幕关闭但传感器继续工作三级是Deep Sleep所有外设断电只有RTC在运行。按下电源键唤醒。Deep Sleep的唤醒时间大约200毫秒可以接受。实操心得ESP32的Deep Sleep模式下GPIO会保持最后的状态如果屏幕的CS引脚在睡眠时是低电平屏幕会一直亮着耗电。我的做法是在进入Deep Sleep前把所有GPIO都设为输入模式并关闭内部上拉。这样屏幕的CS变成高阻态背光电路断开功耗降到最低。实测Deep Sleep电流只有12微安2000mAh电池理论上能待机十几年当然实际受电池自放电影响几个月没问题。4. 常见问题与排查技巧实录4.1 硬件类问题速查现象可能原因排查方法解决方法上电后无反应电源开关没开/电池没电测电池电压充电或换电池ESP32反复重启供电不足/电流不够测3.3V电压换AMS1117或加电容屏幕白屏背光正常但无图像测SPI信号检查接线和时钟频率屏幕花屏SPI干扰/时钟太快降低SPI频率从40M降到20M传感器读数为零I2C没通用I2C扫描检查上拉电阻和地址温度读数偏高ESP32发热影响对比环境温度加隔热槽和软件补偿电磁场读数乱跳电源干扰示波器看波形加LC滤波和屏蔽按钮不灵敏接触不良/程序没消抖测按钮通断加10ms消抖充电指示灯不亮TP4056没工作测输入电压检查USB线和接口电池续航短漏电/屏幕太亮测待机电流检查Deep Sleep配置这个表格里的问题我几乎都遇到过。最折腾的是ESP32反复重启一开始以为是程序问题后来用示波器看3.3V波形发现WiFi发射时电压会瞬间掉到2.8V导致ESP32欠压复位。解决办法是在AMS1117的输出端并一个470uF的电解电容和一个100nF的陶瓷电容储能缓冲。加了之后电压波动在100mV以内再也没重启过。还有一个坑是MLX90614的读数偶尔会跳到80多度。排查后发现是I2C总线上的电容太大导致信号上升沿变缓数据出错。我把上拉电阻从4.7K换成2.2K问题解决。I2C的上拉电阻不是随便选的要根据总线电容和速度来算。标准模式100kHz下上升时间要小于1000ns总线电容400pF时上拉电阻最大 R 1000ns / (0.8473 * 400pF) ≈ 2.95K。所以2.2K是合适的4.7K偏大。4.2 软件类问题与调试技巧软件方面最大的坑是内存泄漏。ESP32有520KB SRAM听起来很多但WiFi协议栈和图形库占了不少。我一开始在UI刷新函数里动态分配内存画波形跑几个小时就死机。后来改成静态分配波形缓冲区在编译时就确定大小问题消失。注意Arduino的String类在ESP32上容易产生内存碎片尽量用char数组代替。我一开始用String拼接传感器数据跑一天后可用内存从200KB降到50KB。换成snprintf写入固定缓冲区后内存稳定在180KB以上。调试时善用ESP32的串口输出。我习惯在关键位置加Serial.print比如传感器读取前后、UI刷新前后、电源状态切换时。串口波特率用115200太快了容易丢数据。如果串口输出太多影响实时性可以用ESP32的硬件串口1把调试信息输出到GPIO17用USB转TTL模块单独看。还有一个技巧是用ESP32的看门狗。如果程序跑飞了看门狗会自动重启。我设置了10秒的超时在loop函数里定期喂狗。这样即使有偶发的死循环设备也能自己恢复不会一直卡死。4.3 结构类问题与改进方案外壳方面最常见的问题是螺丝孔滑丝。PETG材料比PLA软M2螺丝拧几次就滑了。我的解决办法是在螺丝孔里滴一滴502胶水等干了之后再拧胶水渗入塑料缝隙固化后硬度提高不少。或者直接用热熔胶把螺丝固定死反正电池仓不常开。屏幕窗口的亚克力片容易掉。双面胶在温度变化时会失去粘性。我改用3M的VHB胶带厚度0.5mm粘性强耐温到90°C。贴之前用酒精把亚克力片和外壳表面擦干净贴上去后用力压30秒24小时后达到最大强度。按钮手感不一致的问题也遇到过。三个按钮里有一个按下去很硬拆开发现是按钮帽和外壳孔壁摩擦。用砂纸把按钮帽侧面打磨掉0.1mm再涂一点硅脂手感就顺滑了。硅脂用那种CPU散热用的就行不要用导电的。散热方面夏天户外使用时外壳会有点烫。我在ESP32上方贴了一块15x15mm的铝散热片用导热胶固定。散热片高度5mm刚好在外壳内部不突出。加了散热片后连续工作1小时外壳温度从42°C降到36°C效果明显。5. 功能扩展与个人使用体会5.1 后续可以怎么玩这个平台的可扩展性很强。ESP32还有不少空闲的GPIO可以接更多传感器。我后来加了一个GPS模块用UART接口可以记录位置和海拔配合气压计做高度校准。还试过加一个麦克风模块做环境噪音监测但数据量太大ESP32处理起来有点吃力后来放弃了。软件方面我加了一个数据记录功能把传感器数据写到SD卡里CSV格式方便后续用Excel分析。SD卡模块用SPI接口和屏幕共用SPI总线用不同的CS引脚区分。注意SD卡和屏幕不能同时操作我在代码里加了互斥锁避免冲突。还有一个好玩的功能是蓝牙串口。ESP32自带蓝牙可以模拟一个串口设备手机连上后能实时看数据。我用了一个叫Serial Bluetooth Terminal的安卓应用配对后就能接收ESP32发来的传感器数据。这个功能在调试时特别有用不用插USB线就能看输出。如果你想让外观更接近原版可以用亚克力激光切割做外壳比3D打印的质感好很多。我试过用2mm厚的黑色亚克力激光切割后边缘用火抛光效果很赞。但亚克力的强度不如PETG摔了容易裂所以我还是用3D打印的做日常使用亚克力的当展示品。5.2 实际使用中的一些感受这台Tricoder-REV2我用了大半年出门徒步、逛电子市场、甚至去超市都带着。最实用的功能其实是环境监测尤其是去一个新地方时看看温度湿度气压心里有数。电磁场探测在逛电子市场时挺有意思靠近变压器或电机时读数明显变化能帮你找到隐藏的走线。电池续航方面我一般出门前充满正常使用一天下来还剩30%左右。如果开省电模式两天没问题。充电用普通的手机充电器就行TP4056支持5V输入电流1A两个多小时充满。个人体会这个项目最大的收获不是做出了一个设备而是把整个嵌入式开发的流程走了一遍。从需求分析、方案选型、电路设计、PCB打样、焊接调试、固件开发、结构设计到最终组装每个环节都有坑但每个坑填上之后都是经验。如果你也想做类似的项目我的建议是先从最小系统开始把ESP32和屏幕点亮再一个一个加传感器不要想着一次把所有功能都做上去。分步走每步都测试通过再继续这样出问题容易定位。最后分享一个小技巧PCB打样时可以在板子边缘加几个测试点把3.3V、GND、TX、RX引出来。调试时不用拆外壳就能接串口和电源省事很多。我还在板子上留了一个复位按钮的焊盘外壳上对应位置开了一个小孔用牙签就能戳到死机时不用拆机。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进