构建水果质量检测器:IoT-For-Beginners 制造项目实战——边缘 AI 分类、多设备协同与云端服务整合
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
本文围绕 IoT-For-Beginners 课程「4-manufacturing(制造)」项目的最终实战任务展开:以关联文档 assignment.md 定义的「水果质量检测器」原型为核心,完整拆解其四项评估标准(云服务配置、接近触发与命令下发、边缘图像分类、LED 告警控制),并结合仓库中各硬件平台的距离传感器示例代码,给出可直接复现的端到端实现路径。读完本文,你将掌握如何把前 24 课学到的传感器读取、IoT Hub 通信、Azure Functions 无服务器逻辑与边缘 AI 推理拼装成一条完整的「感知—决策—执行」工业流水线。
一、任务背景:把「手工挑果」变成自动化流水线
该任务模拟一个真实制造场景:处理厂的传送带上由人工逐个检查水果并挑出未成熟果实,厂方希望用自动化系统替代人工。任务要求你利用此前所有课程积累的代码,搭建一个原型级水果质量检测器,实现三个核心能力:
- 接近触发:当传送带上的水果靠近到预设距离时,由接近传感器触发检测流程;
- 边缘 AI 分类:摄像头拍照后,由运行在边缘设备上的 AI 模型对水果成熟度进行分类,并将结果存入云端存储;
- 执行器反馈:根据分类结果,通过云端命令控制 LED 点亮,提醒工作人员移除未成熟水果。
任务文档明确强调:这应当能够完全由你在各前置课程(训练水果检测器、设备端调用 Custom Vision、在边缘运行检测器等)中写过的代码拼装而成,仓库中4-manufacturing/lessons/下的前三个课时目录正是这些代码的来源。
二、总体架构:Things → Insights → Actions
课程 README.md 给出的参考架构可以概括为三段式数据流:
- Things(设备侧):带接近传感器的设备检测水果到达并发消息上云;摄像头设备拍照后交给边缘图像分类器;负责 LED 告警的设备接收命令。
- Insights(洞察侧):云端的无服务器应用(Azure Functions)消费 IoT Hub 消息、做出「是否触发拍照」「果实是否未熟」等决策;Azure Storage 保存分类结果供后续统计分析(如未熟果占比)。
- Actions(执行侧):IoT Hub 向摄像头设备下发拍照/分类命令,向 LED 设备下发点亮命令。
原型阶段全部逻辑跑在一台设备上(使用微控制器时,图像分类器需放在一台独立的边缘设备上),其组件间消息流如下图所示:
三、评估标准逐项拆解
任务文档给出了四档评估表(Exemplary / Adequate / Needs Improvement),这是完成本任务时最直接的验收清单:
| 标准 | 优秀(Exemplary) | 合格(Adequate) | 待改进(Needs Improvement) |
|---|---|---|---|
| 配置全部云服务 | 成功配置 IoT Hub、Azure Functions 应用与 Azure 存储 | 仅配置了 IoT Hub,未配置 Functions 或存储 | 任何 IoT 云服务均未配置成功 |
| 监控接近距离、低于预设距离时上报 IoT Hub,并通过命令触发摄像头 | 能测距、在物体足够近时向 IoT Hub 发消息,并成功接收触发摄像头的命令 | 测距并上报成功,但摄像头未收到命令 | 测距、上报或命令触发均失败 |
| 拍照、分类并把结果发给 IoT Hub | 拍照后使用边缘设备分类,并将结果发送到 IoT Hub | 能分类但未经由边缘设备,或结果未上报 | 无法完成图像分类 |
| 根据分类结果用命令控制 LED 开关 | 当水果未成熟时能通过命令点亮 LED | 命令能发到设备但 LED 不受控 | 无法下发 LED 控制命令 |
下面按标准逐项说明实现要点。
标准 1:配置 IoT Hub、Azure Functions 与 Azure 存储
这一项要求三条云端链路全部打通:设备遥测的入口(IoT Hub)、消息消费与决策逻辑(Functions)、分类结果的持久化(Storage)。三者分别在前置课时中搭建过,本任务的核心是把它们串到同一个 Hub 下,并为不同的设备身份(距离传感器、摄像头、LED 设备)分别管理连接字符串。
标准 2:接近触发与摄像头命令下发
接近传感器硬件。课程选用 Seeed Grove 的 Time of Flight 距离传感器,核心是 VL53L0X 激光测距模块,量程 10mm~2000mm,超过 1000mm 的读数会报告为 8109mm,接口为 I²C。其原理是发射激光(或红外)电磁波并检测反射回来的时间,用飞行时间反算距离——这也是它被称为 Time of Flight(飞行时间)传感器的原因。
Raspberry Pi 实现。仓库中 pi 平台示例 只有 11 行,展示的是最小可运行读距循环:
import time from grove.i2c import Bus from rpi_vl53l0x.vl53l0x import VL53L0X distance_sensor = VL53L0X(bus = Bus().bus) distance_sensor.begin() while True: distance_sensor.wait_ready() print(f'Distance = {distance_sensor.get_distance()} mm') time.sleep(1)要点:通过 Grove Base HAT 的 I²C 总线接入传感器(依赖grove库的Bus和rpi-vl53l0x包,安装命令pip install rpi-vl53l0x);wait_ready()阻塞等待一次测距完成,get_distance()返回毫米值。课程 pi-proximity.md 中给出预期的控制台输出形如Distance = 29 mm每秒一行。
Wio Terminal(微控制器)实现。同一硬件在 Wio Terminal 示例 中用 C++ 完成:
#include "Seeed_vl53l0x.h" Seeed_vl53l0x VL53L0X; void setup() { Serial.begin(9600); delay(1000); VL53L0X.VL53L0X_common_init(); VL53L0X.VL53L0X_high_accuracy_ranging_init(); } void loop() { VL53L0X_RangingMeasurementData_t RangingMeasurementData; memset(&RangingMeasurementData, 0, sizeof(VL53L0X_RangingMeasurementData_t)); VL53L0X.PerformSingleRangingMeasurement(&RangingMeasurementData); Serial.print("Distance = "); Serial.print(RangingMeasurementData.RangeMilliMeter); Serial.println(" mm"); delay(1000); }对应的 platformio.ini 使用atmelsam平台、seeed_wio_terminal板型,依赖seeed-studio/Grove Ranging sensor - VL53L0X @ ^1.1.1库。注意微控制器只能跑单个应用,因此后续多设备逻辑要合并在一个 sketch 内(见「多设备模拟」一节)。
虚拟设备实现。没有硬件时可用 CounterFit 模拟器,虚拟设备示例 用counterfit-shims-rpi-vl53l0x垫片包替代真实驱动:
from counterfit_connection import CounterFitConnection CounterFitConnection.init('127.0.0.1', 5000) from counterfit_shims_rpi_vl53l0x.vl53l0x import VL53L0X distance_sensor = VL53L0X() distance_sensor.begin() while True: distance_sensor.wait_ready() print(f'Distance = {distance_sensor.get_distance()} mm') time.sleep(1)在 CounterFit Web 应用中创建 Distance 类型传感器时,I²C 地址需设为0x29(物理 VL53L0X 的固定地址)。virtual-device-proximity.md 还建议在模拟器中开启随机值模式,模拟传送带上果实的远近变化。
触发决策的位置是课程专门讨论的架构权衡:是设备端判断「距离 < 阈值」后才上报一条触发消息,还是把连续测距值全部上报、由云端(IoT Hub/Functions)判断?两种都可行,但代价不同——上报全部测距会增加 IoT Hub 费用与带宽(工厂里上百万设备时尤其明显),也可能拖慢设备;而在设备端决策则需要通过云端配置(如设备孪生)来在线调整阈值,避免把触发距离硬编码进固件。
达到触发条件后,Functions 消费消息并向摄像头设备发送 C2D(云ToDevice)命令,例如「takePhoto」,摄像头设备收到命令后执行拍照与分类。
标准 3:拍照、边缘分类并上报结果
摄像头设备收到命令后拍照,把图像交给运行在边缘设备上的 Custom Vision 模型(此前课时已训练并发布过香蕉/水果成熟度检测模型)完成推理。评估标准特别区分了「使用边缘设备分类」(优秀)与「仅在云端或 PC 上分类」(合格但非优秀),这正呼应课程「边缘计算减少回传带宽与延迟」的主线。推理完成后,将包含类别与置信度的分类结果作为遥测消息发回 IoT Hub,由 Functions 消费并写入 Azure Storage 存档,用于事后统计未熟果占比。
标准 4:按分类结果下发 LED 控制命令
当分类结果判定水果未成熟时,Functions 向 LED 设备下发命令(如turnOn/turnOff),设备端在命令回调中驱动继电器或 GPIO 点亮 LED,向工人发出移除未熟果的提示。验收的完整闭环是:未熟果 → 边缘分类 → 结果上报 → Functions 决策 → 命令下发 → LED 点亮;任何一环断裂都会落入评估表的较低档。
四、先定义消息结构,再写代码
课程强调:多组件通信的系统必须先约定每条消息的 JSON 结构,再动手写应用。以温度为例,字段该叫temperature还是temp?
{ "temperature": 20.7 }vs.
{ "temp": 20.7 }两种写法本身都合法,但收发两端不一致就是线上事故——文档引用了火星气候轨道器因单位换算失误坠毁的经典案例提醒:不仅字段名,单位也必须在全链路保持一致(°C 还是 °F,毫米还是米)。本任务涉及的四种消息分别是:距离测量上报、拍照命令下发、分类结果上报、LED 命令下发,建议为每一类都先写出 schema 草案再实现。
五、在一块开发板上模拟多台 IoT 设备
原型要求「接近传感器设备」「摄像头设备」「LED 设备」三个身份,而开发者手上只有一套硬件。课程给出两套模拟策略:
- 单板计算机(Raspberry Pi / 虚拟设备):可同时运行多个进程,直接把每台 IoT 设备实现成独立 Python 文件,在多个终端里并行运行(本课时距离传感器就单独放在
distance_sensor.py而非app.py中,正是此意)。注意部分硬件被多个进程并发访问时可能冲突。 - 微控制器(Wio Terminal):无法多进程,必须把所有设备逻辑合并进单个应用。课程建议:每个 IoT 设备一个类(如
DistanceSensor、ClassifierCamera、LEDController),各自暴露setup/loop方法供主函数调用;命令处理集中在一处再分发到对应类;主loop用统一的最小延迟(如 1 秒)配合计数器实现不同设备不同周期(每 10 秒 vs 每 1 秒)的调度。
六、从原型走向生产
任务文档同时说明了原型与生产系统的差距,这也是评估答辩时的加分谈资:
- 加固硬件:生产环境用能抗工厂噪音、高温、振动与机械应力的工业级部件;
- 内部直连:部分组件之间改为设备间直接通信,避免每次决策都绕行云端,仅将需要留存的数据上云;也可用网关设备把部分 IoT 服务下沉到边缘;
- 可配置化:触发距离、检测对象等参数通过云端配置(如设备孪生)下发,而非写死在固件中,适应不同产线与不同水果;
- 自动剔除:用机械装置自动移除未熟果,替代 LED 人工提示。
七、完成后的清理
这是制造项目的最后一课,任务文档特别提示:先完成作业,再按仓库根目录的 clean-up.md 指引删除 IoT Hub、Functions 与 Storage 等云资源,避免持续产生费用。
八、延伸阅读
- 本课时主文档(架构、消息设计、多设备模拟的完整讨论):4-manufacturing/lessons/4-trigger-fruit-detector/README.md
- 分平台接近传感器实操:Raspberry Pi、Wio Terminal、虚拟设备
- 原始任务(英文):4-manufacturing/lessons/4-trigger-fruit-detector/assignment.md
- 前置技能来源:训练检测器(
4-manufacturing/lessons/1-train-fruit-detector/)、设备端调用检测器(4-manufacturing/lessons/2-check-fruit-from-device/)、边缘运行检测器(4-manufacturing/lessons/3-run-fruit-detector-edge/)
【免费下载链接】IoT-For-Beginners12 Weeks, 24 Lessons, IoT for All!项目地址: https://gitcode.com/GitHub_Trending/io/IoT-For-Beginners
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考