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

ESP32+HX711智能快递秤:蓝牙称重与Android App开发实战

ESP32+HX711智能快递秤:蓝牙称重与Android App开发实战 ★ FEATURED ARTICLE
1. 项目缘起与整体设计思路快递放在门口被顺手牵羊这事儿我自己就遇到过两回。一次是楼下邻居误拿另一次就再也没找回来。跟几个做智能家居的朋友聊起来发现大家都有类似痛点包裹送达时人不在家放门口不放心放快递柜又经常满格。市面上虽然有带锁的快递箱但价格动辄上千而且没法记录“谁在什么时候放了多重的包裹”这种关键信息。这个项目的出发点很直接用一块 ESP32 做主控搭配 HX711 称重模块和压力传感器做一个能识别“包裹是否放上来、放了多重”的智能秤台再通过蓝牙把数据推给手机 App。手机端用 Android Studio 开发一个轻量应用实时显示重量变化并记录时间戳。外壳部分用 3D 打印机自己打尺寸和结构完全按需定制。整套方案的成本控制在两百元以内核心逻辑就是重量突变即事件触发。为什么选 ESP32 而不是 Arduino Uno原因有三个。第一ESP32 自带蓝牙和 Wi-Fi省掉外接模块的麻烦和额外开销第二它的双核处理器在处理称重数据的同时还能跑蓝牙协议栈不会因为采样延迟导致数据丢包第三ESP32 的深度睡眠模式功耗极低用电池供电也能撑很久。HX711 是称重传感器专用的 24 位模数转换芯片内置放大器直接读应变片桥式传感器的微弱信号精度足够分辨几十克的差异。Android 端用 Java 或 Kotlin 写一个蓝牙 SPP 客户端接收 ESP32 发来的重量字符串解析后更新 UI 并存入本地数据库。整个系统的数据流是这样的压力传感器受到包裹重力产生微弱电压变化HX711 把这个模拟信号转换成数字量ESP32 通过 GPIO 读取 HX711 的输出经过校准计算得到实际重量值再通过蓝牙串口协议发送到手机。手机 App 收到数据后判断重量是否超过预设阈值如果超过就记录一条“包裹已放置”事件同时可以触发本地通知。如果重量从有到无则记录“包裹已取走”。这样一来即使人不在家也能知道包裹是什么时候到的、大概多重、什么时候被拿走的。这个项目适合谁呢如果你有基本的 Arduino 编程经验会用烙铁焊几个排针能照着教程安装 Android Studio 并跑通一个 Hello World那就可以动手做。不需要精通电路设计也不需要会写复杂的 Android 架构核心代码加起来不超过五百行。3D 打印部分如果没有打印机也可以找代打服务或者用亚克力板手工切割替代。2. 硬件选型与核心电路搭建2.1 ESP32 开发板的选择与引脚分配ESP32 的型号很多我手头用的是 ESP32-DevKitC V4核心是 ESP32-WROOM-32 模组。选它是因为引脚引出完整USB 转串口芯片是 CP2102在 Windows 和 macOS 上驱动都很好找。国内购买的话注意选带屏蔽罩的版本信号稳定性会好一些。开发环境我用的 Arduino IDE需要额外安装 ESP32 的开发板支持包。国内下载慢的问题可以通过添加国内镜像源解决在 Arduino IDE 的“附加开发板管理器网址”里填入国内镜像地址即可具体地址搜“esp32 arduino 国内镜像源”就能找到最新的。引脚分配上HX711 需要两个 GPIO一个用于数据输出DT一个用于时钟输入SCK。我选的是 GPIO16 和 GPIO17这两个引脚在 DevKitC 上位置方便接线而且不涉及启动时的特殊功能。注意不要用 GPIO0、GPIO2、GPIO12 这些在启动时会影响芯片模式的引脚否则可能出现烧录失败或者启动异常。蓝牙部分不需要额外引脚ESP32 内置的蓝牙协议栈直接使用。供电方面ESP32 开发板可以通过 Micro USB 或者 5V 引脚供电。HX711 模块和称重传感器需要 5V 供电但 HX711 的信号输出电平是 5V而 ESP32 的 GPIO 是 3.3V 容忍的。这里有个坑HX711 的 DT 引脚输出是 5V 电平直接接 ESP32 的 GPIO 长期运行可能损伤芯片。稳妥的做法是在 DT 和 ESP32 之间加一个电平转换模块或者用电阻分压。我实测用 1k 和 2k 电阻分压后信号读取正常连续跑了一周没有出现问题。2.2 HX711 与称重传感器的接线要点称重传感器我选的是 5kg 量程的铝合金悬臂梁式精度等级 C3满足包裹称重需求。传感器有四根线红、黑、白、绿。红线接 HX711 的 E黑线接 E-白线接 A-绿线接 A。不同厂家的线色可能不同拿到手先用万用表测一下桥臂电阻确认哪两根是激励、哪两根是信号。一般来说激励线之间的电阻是 1kΩ 左右信号线之间的电阻也是 1kΩ 左右激励和信号之间的电阻约 800Ω。HX711 模块和 ESP32 的连接VCC 接 5VGND 接 GNDDT 接 GPIO16SCK 接 GPIO17。这里注意 HX711 的 VCC 一定要接 5V接 3.3V 的话芯片工作不正常读数会乱跳。我一开始图省事接了 3.3V结果读数一直在漂移换了 5V 之后立刻稳定了。称重传感器的安装方式直接影响测量精度。悬臂梁传感器需要一端固定、一端悬空受力。我用 3D 打印了一个底座把传感器的一端用 M4 螺丝固定在底座上另一端悬空上面装一个承重平台。承重平台不能碰到其他任何东西否则会产生侧向力导致读数不准。这个细节很关键我第一版设计时平台边缘蹭到了外壳读数一直偏大后来把外壳开口扩大了两毫米才解决。2.3 3D 打印外壳的设计与打印参数外壳我用 Fusion 360 画的分上下两部分底座用来固定传感器和 ESP32上盖用来放包裹。底座内部留了走线槽HX711 模块和 ESP32 用尼龙柱固定。上盖和传感器之间用一个 M5 螺丝连接螺丝拧进传感器悬空端的螺纹孔里。整个外壳尺寸是 200mm x 150mm x 40mm足够放下一个标准快递盒。打印参数方面我用的是 PLA 材料层高 0.2mm填充率 20%打印温度 210°C热床温度 60°C。底座需要承受包裹重量所以填充率可以提高到 30%壁厚设为 1.2mm。上盖不需要承重20% 填充就够了。打印时间大概各需要四五个小时具体看打印机速度。如果手头没有 3D 打印机可以用亚克力板切割一个类似结构或者直接买一个现成的电子秤拆掉表头把传感器信号引出来接到 HX711。不过自己打印的好处是尺寸完全可控后续想改大改小都方便。3. 固件开发与重量校准实战3.1 Arduino 环境配置与 HX711 库的使用Arduino IDE 安装 ESP32 支持包的步骤打开“文件”-“首选项”在“附加开发板管理器网址”里填入国内镜像地址然后打开“工具”-“开发板”-“开发板管理器”搜索“esp32”安装最新版本。安装完成后在开发板列表里选择“ESP32 Dev Module”。如果下载速度慢可以在首选项里把“编译输出”设为详细观察具体卡在哪一步。HX711 库我用的是 bogde 的 HX711 Arduino Library在库管理器里直接搜索安装即可。这个库封装了读取原始值和校准的功能用起来很简单。初始化代码如下#include HX711.h HX711 scale; const int LOADCELL_DOUT_PIN 16; const int LOADCELL_SCK_PIN 17; void setup() { Serial.begin(115200); scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN); scale.set_scale(); // 先不设比例系数后面校准 scale.tare(); // 去皮清零 }读取重量时先调用scale.read_average(10)取十次平均减少噪声。然后除以比例系数得到实际重量。比例系数需要校准下面详细说。3.2 校准比例系数的计算与实操校准是称重项目里最关键的一步。HX711 输出的是原始 ADC 值需要除以一个比例系数才能变成克或千克。这个系数因传感器和安装方式而异必须实测。具体操作先放一个已知重量的物体比如一袋 500g 的盐。读取此时的原始值假设是 420000。然后拿掉物体读取空载原始值假设是 2000。那么比例系数 (420000 - 2000) / 500 836。这个系数就是每克对应的 ADC 变化量。在代码里用scale.set_scale(836)设置之后scale.get_units(10)返回的就是克数。但实际使用中我发现线性度在大量程时会有偏差。比如 500g 时校准好了放到 3kg 时读数偏小 2%。解决办法是用两个校准点先用 500g 校准再用 3kg 校准取平均系数。或者用多点校准在代码里做分段线性拟合。对于包裹称重来说精度要求不高±50g 都能接受所以单点校准足够了。注意校准前一定要先tare()去皮把空载时的原始值清零。如果传感器安装有预紧力空载原始值可能很大去皮后就没问题了。3.3 蓝牙串口通信的配置与数据格式ESP32 的蓝牙串口用BluetoothSerial库几行代码就能搞定#include BluetoothSerial.h BluetoothSerial SerialBT; void setup() { SerialBT.begin(SmartParcelScale); // 蓝牙设备名 } void loop() { float weight scale.get_units(10); SerialBT.println(weight); delay(200); }数据格式我用的就是纯文本每行一个浮点数单位是克。手机端按行读取解析成 float 即可。为什么不用 JSON因为解析开销大而且蓝牙串口带宽有限纯文本最省事。200ms 发一次既能实时反映重量变化又不会刷屏太快。蓝牙设备名设成“SmartParcelScale”方便在手机端识别。配对时不需要 PIN 码直接连接即可。注意 ESP32 的蓝牙和 Wi-Fi 共用射频如果同时开 Wi-Fi 和蓝牙可能会有干扰。这个项目只用蓝牙所以没这个问题。4. Android 端 App 开发与联调4.1 Android Studio 项目创建与蓝牙权限配置Android Studio 我用的 2023.1.1 版本创建项目时选“Empty Views Activity”语言选 Java。项目建好后在AndroidManifest.xml里添加蓝牙权限uses-permission android:nameandroid.permission.BLUETOOTH / uses-permission android:nameandroid.permission.BLUETOOTH_ADMIN / uses-permission android:nameandroid.permission.BLUETOOTH_CONNECT / uses-permission android:nameandroid.permission.BLUETOOTH_SCAN /Android 12 及以上需要BLUETOOTH_CONNECT和BLUETOOTH_SCAN权限并且要在运行时动态申请。我一开始只加了前两个在 Android 13 手机上一直连不上后来补上后两个才正常。界面布局很简单一个 TextView 显示当前重量一个 Button 用来连接设备一个 RecyclerView 显示历史记录。连接按钮点击后弹出已配对设备列表选中“SmartParcelScale”后建立 SPP 连接。4.2 蓝牙 SPP 连接与数据接收线程蓝牙 SPP 连接的核心代码BluetoothAdapter adapter BluetoothAdapter.getDefaultAdapter(); BluetoothDevice device adapter.getRemoteDevice(address); BluetoothSocket socket device.createRfcommSocketToServiceRecord( UUID.fromString(00001101-0000-1000-8000-00805F9B34FB)); socket.connect(); InputStream inputStream socket.getInputStream();接收数据要放在独立线程里不能在主线程做阻塞读取。我用一个Thread循环读取inputStream按换行符分割每读到一行就通过runOnUiThread更新 UI。这里有个细节read()方法返回 -1 表示连接断开要及时处理并提示用户重连。数据解析就是Float.parseFloat(line)然后判断重量是否超过阈值。我设的阈值是 50g超过就认为有包裹放上来了。记录逻辑是如果上一次重量小于阈值、这一次大于阈值就记一条“包裹已放置”反过来就记“包裹已取走”。时间戳用System.currentTimeMillis()。4.3 数据持久化与通知提醒历史记录我用 Room 数据库存建一个实体类ParcelEvent字段包括 id、重量、事件类型、时间戳。Room 的配置在 Android Studio 里很方便加三个依赖room-runtime、room-compiler、room-common。编译时用注解处理器生成代码。通知提醒用NotificationManager在重量超过阈值时发一条本地通知。Android 13 需要POST_NOTIFICATIONS权限记得在 Manifest 里声明并动态申请。通知内容就是“包裹已放置重量 XXX 克”。调试过程中遇到一个坑蓝牙连接在 App 切到后台后会被系统断开。解决办法是把接收线程放在Service里用前台服务保活。不过对于这个项目来说App 在前台运行就够了所以没做 Service。5. 常见问题排查与避坑经验5.1 称重读数不稳定或漂移这是最常见的问题原因通常有三个。第一HX711 供电不足检查 VCC 是否接了 5VGND 是否共地。第二传感器安装有侧向力检查承重平台是否碰到其他物体。第三电源噪声USB 供电时电脑的开关电源噪声会串进来可以加一个 100uF 的电解电容在 HX711 的 VCC 和 GND 之间。我遇到过一次读数每隔几秒跳一次后来发现是 ESP32 的蓝牙发送和 HX711 读取在同一时刻冲突了。解决办法是在读取 HX711 时暂停蓝牙发送或者把读取频率降低到 10Hz 以下。HX711 的默认输出速率是 10Hz 或 80Hz用 10Hz 模式更稳定。5.2 蓝牙连接失败或频繁断开Android 端连不上 ESP32 蓝牙先检查设备是否已配对。如果配对列表里没有“SmartParcelScale”先在系统设置里手动配对一次。如果配对后 App 里连不上检查 UUID 是否正确SPP 的标准 UUID 是00001101-0000-1000-8000-00805F9B34FB。频繁断开通常是信号干扰或距离太远。ESP32 的蓝牙 Class 2 有效距离约 10 米中间有墙的话会缩短。把手机和秤台放在同一房间基本不会断。另外ESP32 的蓝牙天线是板载 PCB 天线如果装在金属外壳里信号会很差所以外壳我用的是 PLA 塑料没有屏蔽问题。5.3 Android Studio 编译报错与依赖冲突Android Studio 新手最容易卡在 Gradle 同步失败。国内网络环境下把 Gradle 仓库换成国内镜像会快很多。在settings.gradle里把google()和mavenCentral()替换成国内镜像地址即可。具体地址搜“Android Studio 国内镜像”能找到最新的。另一个常见问题是minSdkVersion设得太低导致蓝牙 API 不可用。建议设成 21Android 5.0以上如果要支持 Android 12 的新蓝牙权限targetSdkVersion要设成 31 以上。我一开始targetSdkVersion设的 30在 Android 13 手机上跑的时候权限申请一直失败改成 33 后正常了。5.4 3D 打印件强度不足或变形PLA 打印的承重件在长期受力下会发生蠕变也就是慢慢变形。如果包裹比较重建议用 PETG 或 ABS 材料强度更好。另外打印时把承重方向的层线设置成垂直于受力方向可以显著提高强度。比如底座受力是垂直向下的打印时让层线水平走不要竖着打。还有一个细节螺丝孔要留公差。我第一版螺丝孔按 4.0mm 画的结果 M4 螺丝拧不进去因为 PLA 打印出来孔会缩小约 0.2mm。后来改成 4.3mm 就刚好。如果不想反复试可以在切片软件里设置“孔洞补偿”一般设 0.1-0.2mm 就行。6. 系统联调与实测数据记录6.1 端到端联调步骤联调按这个顺序来不容易乱第一步单独测试 ESP32 和 HX711用串口监视器看重量读数是否正常。第二步打开手机蓝牙配对“SmartParcelScale”用任意蓝牙串口 App 测试数据接收。第三步运行自己写的 Android App确认能收到数据并正确解析。第四步放上不同重量的物体观察 App 显示值和实际值是否一致。第五步测试事件记录逻辑放上、拿走看数据库里是否生成对应记录。我实测下来500g 以内的误差在 ±5g1kg 到 3kg 的误差在 ±20g5kg 满量程误差约 ±50g。这个精度对于判断“有没有包裹”完全够用甚至能大致判断包裹里是文件还是重物。6.2 功耗测试与供电方案用 USB 供电时ESP32 加 HX711 的电流约 80mA蓝牙发送时峰值到 120mA。如果用电池供电2000mAh 的锂电池大概能撑 20 小时。如果要延长续航可以用 ESP32 的深度睡眠模式每隔几秒唤醒一次读取重量读完立刻睡。不过深度睡眠时蓝牙会断开需要重新连接所以不适合实时性要求高的场景。我最终的方案是插 USB 电源长期供电放在门口鞋柜上。线从鞋柜后面走基本看不见。如果门口没有插座可以用充电宝供电10000mAh 的充电宝能撑三四天。6.3 实际使用场景与改进方向用了两个月下来最大的感受是重量阈值不能设太低。我一开始设的 20g结果风吹动门帘碰到秤台都会触发记录。后来改成 100g误报就少多了。另外如果快递员把包裹斜靠在秤台边缘重量读数会偏小可能低于阈值。解决办法是把秤台面积做大一点让包裹必须完全放在上面才能稳定。后续改进我想加一个功能用 ESP32 的 Wi-Fi 连到家庭网络把数据同步到本地服务器这样手机不在家也能查记录。不过这就涉及到网络配置和安全问题复杂度会高不少。目前蓝牙方案的好处是简单、私密、不依赖外网适合对隐私比较在意的用户。还有一个想法是用多个传感器做阵列判断包裹的重心位置这样能区分“包裹”和“其他重物”。不过成本会翻倍而且算法复杂很多暂时没做。7. 关键参数速查与物料清单7.1 核心物料清单与参考价格物料型号/规格数量参考价格ESP32 开发板ESP32-DevKitC V4135 元称重传感器5kg 悬臂梁125 元HX711 模块24 位 ADC18 元电平转换双向电平模块15 元3D 打印耗材PLA 1.75mm约 100g15 元螺丝螺母M4/M5 套装若干10 元Micro USB 线数据线15 元合计约 103 元如果加上 USB 电源适配器总成本约 120 元。比市面上的智能快递箱便宜很多而且功能完全自定义。7.2 关键参数速查表参数推荐值说明HX711 供电5V3.3V 会导致读数不稳采样速率10Hz80Hz 模式噪声大蓝牙发送间隔200ms太快会丢包重量阈值100g低于此值不触发记录校准点500g 和 3kg两点校准线性度更好打印填充率底座 30%上盖 20%兼顾强度和耗材螺丝孔公差0.3mm补偿打印收缩7.3 固件与 App 的关键代码片段索引ESP32 端核心就是三个部分HX711 初始化与读取、蓝牙初始化与发送、主循环逻辑。Android 端核心是蓝牙连接线程、数据解析、Room 数据库操作。代码都不长加起来不到 500 行。我把关键片段都放在上面了照着拼起来就能跑。如果你在复现过程中遇到问题优先检查三个地方HX711 的供电是不是 5V、蓝牙 UUID 是不是标准 SPP UUID、Android 权限是不是都申请了。这三个地方对了基本就能跑通。剩下的就是校准和调试精度耐心调几次就能达到可用状态。
阅读完成 · 觉得有帮助?
咨询建站