基于HuskyLens与掌控板打造本地AI视觉自助收银机原型
1. 项目缘起:当AI视觉遇上开源硬件,我们能做什么?
最近在折腾一个挺有意思的项目,用HuskyLens AI视觉传感器和掌控板,做了一个自助超市收银机的原型。这听起来可能有点“玩具”的感觉,但实际做下来,你会发现它触及了现代零售、物联网和嵌入式AI几个领域的交叉点。HuskyLens这个传感器,本质上是一个集成了简单AI算法的摄像头模组,能直接输出识别结果,比如人脸、物体、颜色、标签、巡线,省去了我们在微控制器上跑复杂模型的麻烦。掌控板则是一个基于ESP32的开源硬件,集成了屏幕、按键、麦克风、Wi-Fi/蓝牙,非常适合做交互原型。
那么,把这两者结合起来做一个“收银机”,核心逻辑是什么?其实就是用HuskyLens去识别商品(比如通过颜色、物体或二维码标签),然后掌控板负责处理识别结果、计算价格、显示账单,并模拟支付流程。整个过程,我们不需要连接云端服务器,所有计算都在本地完成,响应快,也保护了隐私。这个项目非常适合想了解AIoT(人工智能物联网)入门、嵌入式系统交互设计,或者单纯想做个有趣小项目的朋友。无论你是学生、创客,还是对智能硬件感兴趣的开发者,都能从这个项目中获得从硬件连接到逻辑编程的完整体验。
2. 核心硬件选型与连接:为什么是HuskyLens和掌控板?
在做任何项目之前,硬件选型是第一步,也是最关键的一步。选对了,事半功倍;选错了,可能连第一步都迈不出去。我选择HuskyLens和掌控板这个组合,是基于几个非常实际的考量。
2.1 HuskyLens:将AI视觉能力“傻瓜化”
HuskyLens最大的优势在于“开箱即用”。传统的AI视觉方案,你需要一个摄像头模组(如OV2640),然后在微控制器(如ESP32-CAM)上部署TensorFlow Lite Micro之类的框架,自己准备数据集、训练模型、优化、部署。这个过程门槛高,周期长,对算力也有要求。HuskyLens则把这些都封装好了。它内置了Kendryte K210 AI芯片,预置了多种算法。你只需要在它的小屏幕上,通过按键选择识别模式(比如“物体识别”),然后让它“学习”一两个你要识别的物体样本,它就能在后续的摄像头画面中实时框出并告诉你这是什么。
对于我们的超市收银机项目,这意味着:
- 快速原型:我们不需要自己训练商品识别模型。可以用“颜色识别”模式区分不同颜色的水果(红苹果、绿苹果、黄香蕉),或者用“物体识别”模式学习几个具体的商品包装盒。
- 降低复杂度:HuskyLens通过UART(串口)或I2C接口输出结构化的识别结果,比如
ID:1, x:120, y:80(ID代表学习时的样本编号,x,y是中心坐标)。掌控板只需要解析这些简单的数据,而不需要处理原始的图像流。 - 功耗与体积:相比带摄像头的开发板,HuskyLens集成度高,供电简单(5V),体积也相对紧凑。
注意:HuskyLens的识别能力是有限的。它适合识别特征明显、背景相对简单的物体。对于成百上千种高度相似的商品(比如不同口味的同品牌薯片),它的准确率会下降。但在我们的原型和教学场景中,这完全够用。
2.2 掌控板:一体化的交互与计算核心
为什么不用更常见的Arduino Uno或ESP32开发板?因为掌控板在“交互”上做了高度集成。
- 内置显示屏:一块1.3英寸的OLED屏幕,无需额外接线和驱动,直接可以显示商品名称、价格、总价等信息,这是收银机的核心输出设备。
- 丰富的输入设备:板载了多个触摸按键(金手指)和物理按键(A/B),我们可以轻松地设计“确认”、“取消”、“结账”等交互逻辑。
- 无线能力:集成ESP32,自带Wi-Fi和蓝牙。虽然我们这个基础版本是离线收银,但未来扩展线上支付、库存同步等功能非常方便。
- 编程友好:完美支持Mind+(基于Scratch3.0)和Python(MicroPython)编程。对于初学者,图形化编程可以快速搭建逻辑;对于进阶者,Python能实现更复杂的控制。
2.3 硬件连接:一张图搞定供电与通信
连接非常简单,核心是建立HuskyLens与掌控板之间的串口通信。
所需材料清单:
- HuskyLens AI视觉传感器 x1
- 掌控板(2.0版本) x1
- Type-C数据线(为掌控板供电和编程) x1
- 杜邦线(母对母) x4
接线步骤:
- 给HuskyLens供电:HuskyLens需要5V电压。掌控板上的
3V3引脚是3.3V,不能直接使用。我们需要使用掌控板上的VCC引脚(输出5V)和GND引脚。 - 建立串口通信:我们使用软串口(Software Serial)来通信,以避免占用掌控板下载程序用的硬串口。通常选择两个通用的GPIO引脚。
- 具体连接方案:
| 掌控板引脚 | HuskyLens引脚 | 线色(建议) | 作用 |
|---|---|---|---|
| 3V3 | 3V3 | 灰色 | 错误接法!勿用!HuskyLens需要5V。 |
| VCC (5V) | VCC (5V) | 红色 | 正确!为HuskyLens提供5V电源。 |
| GND | GND | 黑色或棕色 | 共地,确保电压基准一致。 |
| P13(GPIO13) | RX | 黄色 | 掌控板的TX(发送端)接HuskyLens的RX(接收端)。 |
| P14(GPIO14) | TX | 白色 | 掌控板的RX(接收端)接HuskyLens的TX(发送端)。 |
提示:TX接RX,RX接TX,这是串口通信的标准接法,目的是让一方的发送端对准另一方的接收端。接反了无法通信。
连接完成后,用Type-C线将掌控板连接到电脑。此时,HuskyLens应该会亮起红灯,屏幕点亮。
3. 软件环境搭建与HuskyLens基础配置
硬件连好了,接下来是让它们“活”起来的软件部分。这里我强烈推荐使用**Mind+**这款国产图形化编程软件,它对掌控板和HuskyLens的支持非常友好,省去了配置开发环境、安装库文件等一系列繁琐步骤。
3.1 Mind+软件安装与设备连接
- 下载与安装:前往Mind+官网下载对应操作系统的版本并安装。
- 切换模式:打开Mind+,点击左上角,切换到“实时模式”(区别于上传模式的离线运行,实时模式可以边编程边看到效果,非常适合调试)。
- 连接掌控板:
- 用Type-C线连接掌控板和电脑。
- 在Mind+右下角点击“连接设备”,在端口列表中,选择识别到的掌控板端口(如
COM3或/dev/cu.usbserial-XXXX)。 - 点击连接,成功后右下角会显示“掌控板”已连接。
- 加载扩展:这是关键一步。我们需要告诉Mind+,这个项目要用到HuskyLens。
- 点击左下角的“扩展”,在“主控板”分类下找到并添加“掌控板”。
- 然后在“传感器”分类下找到“HuskyLens AI摄像头”,点击添加。添加成功后,左侧积木区会出现HuskyLens相关的指令块。
3.2 HuskyLens的首次配置与“学习”商品
在编程之前,我们需要先在HuskyLens设备本身上进行一些设置,让它准备好识别我们的“商品”。
选择识别算法:按HuskyLens侧面的“功能键”(FUNC),屏幕上会列出所有算法:人脸识别、物体追踪、物体识别、巡线、颜色识别、标签识别等。
- 方案A(颜色识别):如果我们用不同颜色的积木块代表不同商品(红=苹果,绿=梨,蓝=饮料),就选择“颜色识别”。这是最简单快速的方案。
- 方案B(物体识别):如果我们用真实的、外形有区别的小物件(比如一盒牛奶、一包饼干),就选择“物体识别”。这个模式需要“学习”样本。
- 方案C(标签识别):如果我们打印一些二维码或AprilTag贴纸贴到商品上,就选择“标签识别”。这最接近真实超市的条形码方案。
这里以物体识别为例进行后续说明。
学习第一个商品样本:
- 将HuskyLens对准第一个商品(比如一盒牛奶),确保它在屏幕中央的白色方框内。
- 长按“学习键”(LEARN)约2秒,直到屏幕上的白色方框变成蓝色框,并显示“再按一次确认,长按退出”。此时HuskyLens已经抓取了一帧图像作为样本。
- 再短按一次“学习键”,屏幕上会显示“ID:1”。这意味着这个商品被学习为1号样本。你可以按“功能键”来切换显示ID编号。
学习更多商品:重复步骤2,学习其他商品(比如饼干、巧克力)。每次学习,HuskyLens会自动分配递增的ID(2, 3...)。
保存模型(可选但重要):HuskyLens断电后,学习的物体会丢失。为了下次不用重新学,可以长按“功能键”进入设置菜单,找到“保存模型”并确认。这样模型就保存在了传感器内部。
完成这些后,当你把学习过的商品再次放到镜头前,HuskyLens应该能自动框出它,并显示对应的ID。这就为我们的收银程序提供了最基础的输入信号。
4. 核心逻辑编程:从识别到结算的完整流程
有了硬件连接和传感器配置,最核心的部分来了——编程。我们将使用Mind+的图形化积木来搭建整个收银机的逻辑。虽然看起来像搭积木,但其背后的逻辑与用Python或C++编写是完全相通的。我会详细解释每一块积木的作用和背后的编程思想。
4.1 程序初始化与HuskyLens通信建立
任何程序都需要一个起点。在Mind+中,我们通常用“当绿色旗帜被点击”作为主程序的开始。
- 初始化串口:首先,我们必须初始化与HuskyLens通信的软串口。
- 拖入
串口初始化积木,设置TX引脚为13,RX引脚为14,波特率设置为9600。这个波特率需要与HuskyLens的出厂设置一致(通常是9600)。 - 为什么是9600?波特率是通信速度。更高的波特率(如115200)传输更快,但可能不稳定。9600是低速但非常稳定的通用选择,对于传输简单的识别结果数据(几个字节)绰绰有余。
- 拖入
- 初始化HuskyLens协议:拖入
HuskyLens初始化积木。这个积木内部会向HuskyLens发送一些初始化指令,确保两者使用同一种“语言”(协议)通信。 - 清空屏幕与变量:拖入
清空屏幕积木,让OLED屏幕从空白开始。然后,创建几个变量来存储关键数据:商品ID:临时存储当前识别到的商品编号。商品名称:根据ID映射出的名称。商品单价:根据ID映射出的价格。购物清单:一个列表(数组),用于存储每次识别后加入的商品名称。总价:一个数字变量,累加每次加入商品的价格。
实操心得:在“当绿色旗帜被点击”下面进行所有的初始化操作是一个好习惯。这确保了每次重新运行程序,都是从干净的状态开始,避免了上次运行残留的数据干扰本次逻辑。
4.2 构建商品信息数据库
在真实收银系统中,商品名称和价格是从后台数据库查询的。在我们的原型里,需要自己建立一个简单的映射关系。最直接的方法就是用“如果...那么...”积木来实现查询。
我们可以创建一个自定义的“函数”(在Mind+里叫“自制积木”),命名为“查询商品信息”,它接收一个“商品ID”作为输入,然后设置对应的“商品名称”和“商品单价”。
在这个函数里,我们会这样写逻辑:
如果 商品ID = 1 那么 商品名称 = “牛奶” 商品单价 = 5.5 否则如果 商品ID = 2 那么 商品名称 = “饼干” 商品单价 = 3.0 否则如果 商品ID = 3 那么 商品名称 = “巧克力” 商品单价 = 8.0 否则 商品名称 = “未知商品” 商品单价 = 0这样,当主程序拿到一个ID,调用这个函数,就能立刻知道它是什么、卖多少钱。
4.3 主循环:识别、处理、显示的永动机
收银机需要一直工作,等待商品被放到镜头前。这需要一个“永远循环”的结构。
- 获取识别结果:在循环内,首先拖入
向HuskyLens请求数据积木,协议选择“物体识别”。这条指令会让掌控板通过串口向HuskyLens索要最新的识别数据。 - 解析数据:接着使用
HuskyLens是否有读到数据?积木进行判断。如果为“是”,说明HuskyLens当前“看到”了它认识的东西。- 如果读到数据,就用
HuskyLens读取物体识别数据,ID积木,将识别到的物体ID存入商品ID变量。 - 然后,立即调用我们刚才创建的“查询商品信息”函数。
- 如果读到数据,就用
- 防重复触发机制(关键!):这里有一个巨大的坑。HuskyLens的识别是连续的,一个商品放在镜头前,程序每循环一次(可能每秒几十次)都会读到同一个ID,导致瞬间在购物清单里添加几十件同样的商品,总价爆炸。
- 解决方案:引入一个状态变量,比如
上次识别ID。在成功识别并处理一个商品后,将当前商品ID存入上次识别ID。然后在循环开头,判断如果HuskyLens是否有读到数据?为是,并且读到的商品ID不等于上次识别ID,才进行后续的“加入购物车”操作。处理完后,立即更新上次识别ID。当商品拿开,HuskyLens读不到数据了,就将上次识别ID重置为0或-1,等待下一个商品。 - 这个逻辑模拟了真实收银机的“扫码枪”行为:扫一次,响一声,添加一件。而不是把商品放在扫码口不动,它就一直在那“哔哔哔”地添加。
- 解决方案:引入一个状态变量,比如
- 加入购物车与计算:当确认是一次新的有效识别后:
- 将
商品名称追加到购物清单列表中。 - 将
商品单价累加到总价变量上。
- 将
- 更新屏幕显示:在OLED屏幕上清晰地显示信息。可以分区域显示:
- 第一行:显示最新加入的商品,如
+牛奶 5.5元。 - 中间区域:滚动显示
购物清单列表的内容。 - 底部:固定显示
总计:XX.XX元。 - 使用
OLED显示字符串积木,并注意用转行积木控制显示位置。
- 第一行:显示最新加入的商品,如
4.4 交互功能:结账与清零
一个完整的收银机不能只加不减,还需要结账和开始新订单的功能。
- 绑定按键事件:我们可以用掌控板的A键作为“结账”键,B键作为“清零/新订单”键。
- 结账逻辑:当A键被按下时,程序可以:
- 在屏幕上显示“请支付 XX.XX元”的醒目提示。
- 播放一段“嘀嘀”的提示音(使用掌控板的蜂鸣器)。
- 可以模拟一个3秒倒计时,然后显示“支付成功,谢谢惠顾!”。
- 注意:结账后不应自动清零,因为可能需要打印小票(我们这里模拟)。实际按需决定是否在结账后自动清零。
- 清零逻辑:当B键被按下时,程序需要:
- 清空
购物清单列表。 - 将
总价变量设为0。 - 清空屏幕,并显示“等待扫码...”的初始界面。
- 同时,也要重置
上次识别ID等状态变量,为新订单做好准备。
- 清空
踩坑实录:按键检测的“消抖”。机械按键在按下时,信号并不是干净的从0到1,而是会在几毫秒内产生快速的抖动,导致程序误判为多次按下。在Mind+中,可以使用“当按键A被按下”事件积木,它内部通常做了消抖处理。但如果自己用循环检测引脚电平,就必须在代码中加入延时(如
等待50毫秒)再判断一次,以确保是有效的按键动作。
5. 功能优化与扩展思考
一个能跑通的基础版本已经完成了。但要让这个项目更像样、更有学习价值,我们还需要进行一些优化和思考扩展的可能性。
5.1 提升识别鲁棒性与用户体验
- 多物体同时识别:HuskyLens支持一帧画面里识别多个物体。我们可以修改程序,不再只读取第一个物体的ID,而是用一个循环,通过
HuskyLens物体识别数据,下一个?积木来遍历当前画面中的所有已识别物体。这样,即使你同时把牛奶和饼干放在镜头前,也能一次性都加入购物车,体验更流畅。 - 增加视觉与听觉反馈:识别成功时,除了屏幕显示,还可以让掌控板的RGB灯闪烁绿色;识别到未知商品时,闪烁红色并发出“嘀嘀”报警声。这能让人机交互更加直观。
- 屏幕显示优化:当购物清单很长时,OLED屏幕一屏显示不下。需要实现滚动显示功能。可以设定一个固定显示行数(如4行),当列表超过4个商品时,让列表的起始显示索引逐渐增加,实现自动向上滚动,就像超市收银机屏幕那样。
5.2 向“真实”收银系统迈进
我们的原型是离线的,所有商品价格都硬编码在程序里。如何让它更接近真实系统?
- 引入条码/二维码识别:这是最直接的升级。使用HuskyLens的“标签识别”模式,学习几个二维码(可以用手机生成,内容就是商品ID,如“001”)。商品上贴上对应的二维码。程序识别到二维码后,解析出ID,后续流程不变。这更符合真实超市场景。
- 搭建简单的网络数据库:利用掌控板的Wi-Fi功能。
- 在同一个局域网内,用电脑或树莓派搭建一个最简单的HTTP服务器,上面放一个
prices.json文件,内容如{"001": {"name": "牛奶", "price": 5.5}, "002": {...}}。 - 当掌控板识别到商品ID后,不是去本地函数查询,而是通过Wi-Fi发起一个HTTP GET请求,例如
http://192.168.1.100/prices.json,获取到整个价格表,或者更精细地只请求该ID对应的信息。 - 这样,修改价格只需要改服务器上的文件,无需重新给掌控板烧录程序。
- 在同一个局域网内,用电脑或树莓派搭建一个最简单的HTTP服务器,上面放一个
- 模拟支付流程:可以结合掌控板的蓝牙功能,模拟与手机APP的通信。当点击“结账”时,掌控板通过蓝牙向手机发送总金额,手机APP弹出模拟支付界面,确认后,手机再通过蓝牙向掌控板发送“支付成功”指令,掌控板再显示成功信息。这就构成了一个完整的闭环体验。
5.3 项目复盘与核心收获
做完这个项目,再回头看,它不仅仅是一个“玩具”。它完整地串联了以下几个关键技术点:
- 嵌入式感知:如何通过串口与智能传感器通信,获取物理世界的信息。
- 状态机逻辑:如何设计程序逻辑来处理“等待->识别->添加->等待下一个”的循环,特别是防重复触发这种关键状态控制。
- 人机交互:如何在资源受限(小屏幕、少量按键)的嵌入式设备上设计清晰、友好的用户界面和流程。
- 系统思维:如何将硬件(传感器、主控板)、软件(识别算法、业务逻辑)、交互(显示、按键)整合成一个可工作的系统原型。
对于初学者来说,成功复现这个项目,你已经跨过了AIoT应用开发的第一道门槛。你会发现,很多复杂的商业应用(如智能货柜、自动分拣),其核心原型阶段的思路与此是相通的:感知->处理->执行->交互。
我个人在调试过程中,最大的教训就是状态管理。最初没有防重复触发机制,程序简直一团糟。这也让我深刻体会到,在事件驱动的嵌入式编程中,理清所有可能的状态和它们之间的转换条件,比写具体的功能代码更重要。画一个简单的状态转换图,往往能事半功倍。
最后,这个项目的所有代码和连接方式都是开源的、可复用的。你可以轻易地修改商品数据库、改变交互方式,甚至更换传感器(比如用RFID读卡器来识别商品),来创造属于你自己的“智能收银”或“物品管理”系统。动手去试,在解决问题的过程中学习,这才是创客精神的精髓。