用树莓派+BrickPi复活乐高机器人,Scratch编程实现无人配送车
1. 项目概述与核心价值
如果你和我一样,在创客教育或STEAM领域摸爬滚打了十几年,手头攒着一堆“古董级”的乐高机器人套件,既舍不得扔,又苦于官方编程环境老旧、硬件更新成本高昂,那么今天分享的这个项目,或许能给你打开一扇新的大门。我们不再依赖乐高官方的“智能砖”,而是用一块树莓派(Raspberry Pi)和一个名为BrickPi的扩展板,让那些老旧的乐高马达和传感器重新焕发生机,并用孩子们在学校里就熟悉的Scratch图形化编程来驱动它们。这个项目的最终产物,是一个被我戏称为“Covid-19无人配送车”的乐高卡车模型,它能利用超声波传感器自动避障、探测悬崖,并通过按键实现遥控,模拟无接触配送场景。
这个方案的核心价值在于“降本增效”与“平滑过渡”。对于经费有限的学校、家庭创客空间或教育机构而言,乐高Mindstorms NXT甚至更早的RCX套件依然是宝贵的资产。BrickPi方案让我们无需斥巨资购买最新的EV3或SPIKE Prime套件,就能让这些旧设备接入现代的单板计算机生态。更重要的是,Scratch编程语言的引入,极大地降低了机器人编程的门槛。学生可以从积木式的拖拽编程开始,直观地理解“事件驱动”、“循环控制”和“传感器反馈”等核心计算思维概念,而无需一开始就面对Python或C++的语法壁垒。从技术角度看,这本质上是构建了一个基于树莓派的嵌入式控制系统,通过GPIO和定制固件(BrickPi提供)与乐高传感器、电机通信,实现了从图形化指令到物理动作的完整闭环。它不仅仅是一个玩具车的改造,更是一个完整的、可扩展的机器人开发平台原型。
2. 硬件选型与搭建思路解析
2.1 核心硬件:为什么是树莓派+BrickPi?
在这个项目中,硬件选型是基石。我选择树莓派3B+或更高型号作为主控,而非乐高原装“智能砖”,主要基于三点考量:开放性、性能和生态。树莓派是一台完整的微型Linux电脑,其计算能力、存储空间和网络连接能力远超封闭的乐高控制器。这意味着我们可以运行更复杂的程序,处理更多传感器数据,甚至未来可以轻松集成摄像头进行图像识别,或通过Wi-Fi实现云端控制。而BrickPi扩展板,则扮演了至关重要的“翻译官”角色。乐高的传感器和电机使用特定的数字协议与NXT/EV3“智能砖”通信,树莓派的通用GPIO无法直接识别。BrickPi板载了专用的微控制器和电路,完美实现了协议转换,让树莓派能够像原生乐高主机一样,通过Python库或我们使用的Scratch编程环境,直接控制乐高设备。
关于具体型号,我强烈建议使用BrickPi3而非旧版。BrickPi3针对树莓派3/4的40针GPIO接口设计,供电更稳定,并且官方提供的软件支持和系统镜像也更完善。至于树莓派本身,至少选择3B+型号,它提供了稳定的有线网络和更强的CPU,能保证Scratch编程界面和后台服务流畅运行。如果预算允许,树莓派4将是更佳选择,其多核处理能力能为未来功能扩展留足余地。
2.2 传感器与执行器配置逻辑
原版乐高“智能卡车”设计使用了光传感器作为前方探测。但在实际教育场景中,尤其是模拟无人配送,我将其替换为两个超声波传感器。这是一个基于安全性和教学意义的决策。一个传感器朝前(S2),用于检测行进路径上的障碍物,实现自动刹车或转向避障。另一个传感器朝下(S1),安装在前保险杠下方,用于探测“悬崖”(如楼梯边缘、桌面边缘)。当检测到前方地面突然消失时,车辆应紧急停止并后退。这种配置模拟了真实无人车中的“前向避障”和“防跌落”功能,能更生动地向学生展示多传感器信息融合的决策逻辑。
电机配置遵循了经典的差速转向模型。我们使用一个大型电机(MA)驱动后轮,负责提供前进/后退的动力。另一个中型电机(MD)通过一个齿条机构控制前轮转向,实现左转和右转。这种分离控制的方式,在编程上比乐高常见的“双电机差速转向”更直观,尤其适合初学Scratch的学生理解“动力”与“方向”是两个独立的控制维度。
注意:供电方案的选择。BrickPi需要一个独立的8节AA电池盒为其和树莓派供电。在编程调试阶段,我强烈推荐使用9V直流电源适配器(务必确认电压为9V,极性正确)。这能避免频繁更换电池的麻烦和电压下降导致树莓派意外重启,丢失程序。仅在最终移动测试时切换回电池盒。
2.3 结构改造与机械适配要点
将BrickPi和树莓派组合体安装到乐高车体上,是搭建过程中最具挑战性的环节之一。原设计是为扁平的NXT“智能砖”预留的空间,而BrickPi+树莓派的堆叠高度明显增加。我的解决方案是放弃原装外壳,利用乐高梁和销直接构建一个承载平台。
关键技巧在于使用短的灰色摩擦销(如图中所示)而非长的黑色科技销来连接BrickPi底部的安装孔和乐高梁。短销提供了更好的灵活性和容错度,更容易对准孔位。我用了四个“L”形直角连接件和四个短销,在车体中部搭建了一个稳固的基座。同时,必须仔细规划线缆走向。乐高马达和传感器的线缆又粗又硬,极易卷入齿轮或车轮。我的做法是使用额外的乐高梁和轴,在车斗(后部)区域创建一个线缆管理通道,将所有线缆有序地固定、抬起,确保其远离所有运动部件。这个小细节能避免90%的运行时故障。
3. 软件环境部署与Scratch编程基础
3.1 系统镜像刷写与初始配置
软件环境的准备是项目成功的第一步,也是最容易出错的一步。绝对不能使用树莓派官方的Raspbian或NOOBS镜像。我们必须使用Dexter Industries(BrickPi制造商)专门为机器人定制的“BrickPi Robotics Image”。这个镜像预装了所有必要的驱动、Scratch编程扩展以及BrickPi的守护进程。
操作流程如下:首先,从Dexter Industries官网下载最新的BrickPi3系统镜像。使用Etcher或Raspberry Pi Imager工具将其写入一张至少16GB的MicroSD卡。将SD卡插入树莓派,连接HDMI显示器、USB键盘鼠标,最后接通电源。首次启动会进行系统初始化,时间可能稍长。初始化完成后,你会在桌面看到一个名为“BrickPi3”的文件夹,里面包含了Scratch示例程序和文档。此时,务必先安装散热片!树莓派CPU和BrickPi的芯片在封闭空间内容易过热。使用矮款的散热片(高度约0.5英寸和0.25英寸各一),分别贴在树莓派CPU和BrickPi的主芯片上。如果使用过高散热片,会导致外壳无法合拢或挤压电路。
3.2 Scratch for Robots:图形化编程环境解析
系统预装的Scratch是经过深度定制的“Scratch for Robots”版本。它与普通Scratch的最大区别在于,在“事件”、“控制”积木块旁边,多出了一个“机器人”类别。这个类别里包含了控制电机(设置速度、方向)、读取传感器(超声波、触碰、颜色等)以及管理机器人连接的核心积木。
理解这些积木的工作机制至关重要。它们并非直接控制硬件,而是通过“广播”消息与后台一个名为“scratch_gpio_handler.py”的Python服务进行通信。该服务作为中间件,接收Scratch发出的指令(如“motor A forward at speed 100”),通过BrickPi的Python库将其转换为硬件命令。同样,它也���BrickPi轮询传感器数据,并更新到Scratch的变量中。这种架构意味着,在Scratch中,对电机和传感器的所有操作都是异步和非阻塞的。例如,当你让电机转动时,Scratch脚本会继续执行后面的积木,而不会等待电机转动完成。这需要我们用“事件”和“广播”来构建程序流。
3.3 模块化编程思想与变量管理
在开始编写复杂的无人车程序前,建立模块化编程的习惯能事半功倍。我的策略是:为每一个功能子系统创建独立的测试脚本。这不仅能快速定位硬件连接错误,也是教授学生系统调试方法的绝佳范例。
首先,创建用于测试的变量。在Scratch的“数据”模块中,点击“建立一个变量”。对于电机测试,我创建了motor_letter(A/B/C/D),motor_name(用于显示),motor_speed。对于传感器,创建Ultrasonic_Distance和Ultrasonic_Distance_2。在后续的主程序中,我们还会创建控制变量如drive_speed,turn_speed,backing_up等。合理命名变量(使用下划线分隔,含义明确)是写出可读、可维护代码的基础,即使是在图形化编程中也是如此。
4. 核心功能模块的独立实现与测试
4.1 电机驱动测试:从单电机到双电机协同
第一个测试脚本是“motor_test.sb”。它的逻辑很简单:通过询问框让用户输入要测试的电机端口号(A, B, C, D),然后让该电机以一定速度正转3秒,停止1秒,再反转3秒。
关键积木块解析:
广播 [setup]和广播 [start]:这两个命令必须放在程序开头,用于初始化BrickPi的通信。将 [motor_speed] 设为 (100):设置电机速度,范围通常是-100到100,负值代表反转。广播 [motor A speed motor_speed]:这是控制电机的核心命令。它向后台服务发送消息,指定端口A的电机以motor_speed的速度运行。广播 [update]:这个命令必须放在一个循环里(例如“重复执行”)。它告诉后台服务去读取最新的传感器数据,并更新电机状态。如果没有这个持续的“update”,电机只会执行一次命令后就停止。广播 [motor A speed 0]:停止电机的标准方法。我习惯单独创建一个“当接收到 [stop_all]”的脚本,里面将所有电机速度设为0,作为紧急停止按钮。
在单电机测试通过后,创建“motor_pair_test.sb”,测试驱动电机(MA)和转向电机(MD)的协同工作。例如,编写一个脚本,让MA持续前进,同时用MD左右摆动前轮。这个测试能验证两个电机是否独立可控,机械结构是否顺畅,有无齿轮卡顿。
4.2 超声波传感器校准与数据读取
超声波传感器测试脚本“ultrasonic_test.sb”稍微复杂一些。传感器需要正确的初始化和持续的轮询。
操作步骤:
- 同样以
广播 [setup]和广播 [start]开始。 - 使用
广播 [attach sensor S1 as US (cm)]命令,将端口S1的传感器配置为超声波测距模式(单位厘米)。这里有一个至关重要的坑:在第一次运行程序前,Scratch的传感器下拉菜单里可能没有“S1 US cm”这个选项。你需要先按照大致正确的逻辑写好程序(哪怕选一个别的传感器类型),运行一次。当程序执行到“attach sensor”命令时,BrickPi后台服务会尝试识别该端口的硬件。运行停止后,你再回到积木块,下拉菜单里就会出现正确的选项了。然后修正它,再次运行。 - 在一个“重复执行”循环里,放置
广播 [update]和将 [Ultrasonic_Distance] 设为 (传感器 [S1 US cm] 的值)。这样,变量Ultrasonic_Distance就会实时显示前方障碍物的距离。 - 为了可视化,可以加上
说 (连接 (S1距离:) 和 (Ultrasonic_Distance)),让Scratch小猫把距离读出来。
测试时,用手在传感器前移动,观察读数变化是否平滑。朝下的传感器(S1)应在地面正常时显示一个较小的固定值(比如5-10cm),当移动到桌子边缘时,数值会剧增或变为一个很大的数(表示超出量程)。这是实现“防跌落”功能的基础。
4.3 触碰传感器(按键)的响应编程
触碰传感器在这里被用作卡车的“后保险杠”。编程逻辑与超声波类似,但更简单,因为它返回的是一个布尔值(0或1,代表按下或松开)。
在“bumper_test.sb”中:
- 使用
广播 [attach sensor S3 as touch]将端口S3的传感器配置为触碰模式。 - 在循环中,通过
(传感器 [S3 touch] 的值)来读取状态。 - 使用“如果...那么”积木进行判断:
如果 (传感器 [S3 touch] 的值) = [1] 那么,让小猫说“右后保险杠被撞到!”。
这个测试确保物理按键安装牢固,且线缆连接正确。你可以用手按压按键,观察小猫的反馈是否即时、准确。
5. 无人配送车完整逻辑集成与编程
5.1 主程序框架与初始化模块
在完成所有独立测试后,我们开始集成主程序“BrickPi_Covid-19_Delivery_Truck.sb”。一个好的开始是建立清晰的主程序框架和初始化模块。
首先,创建所有需要的变量:drive_speed(前进速度),turn_speed(转向速度),backup_speed(后退速度),drive_motor_MA,turn_motor_MD(这两个实际上在广播命令中直接使用端口号,但变量化有利于管理),downward_ultrasonic_S1,forward_ultrasonic_S2,right_rear_bumper_S3,left_rear_bumper_S4(这些传感器值变量),以及一个非常重要的状态变量backing_up(是否正在后退,0为否,1为是)。
初始化脚本(当绿旗被点击)应依次执行:
广播 [setup]和广播 [start]。- 依次附加所有传感器:两个超声波,两个触碰。
- 将
drive_speed,turn_speed,backup_speed设置为合适的初始值(例如50, 30, -40)。 - 将
backing_up设为0。 - 启动一个“重复执行”循环,里面只放一个
广播 [update]。这个循环是整个程序的“心跳”,确保传感器数据持续更新,电机命令持续生效。它应该一直运行,直到程序结束。
5.2 键盘遥控与运动控制逻辑
我们使用键盘的上下左右箭头作为遥控器。这里充分体现了Scratch事件驱动的优势。
前进逻辑(上箭头键):
当 [上箭头 v] 键被按下 广播 [Go Forward]当接收到 [Go Forward v] 如果 <(backing_up) = [1]> 那么 将 [backing_up] 设为 [0] 广播 [motor MA speed drive_speed] //恢复前进 否则 将 [drive_speed] 改变 (10) //加速 广播 [motor MA speed drive_speed] 结束这里有一个状态判断:如果卡车正在后退(backing_up=1),按下前进键意味着取消后退状态,恢复正常前进;否则就是加速。
后退逻辑(下箭头键):后退速度backup_speed通常设置为一个固定的负值(如-40)。当按下下箭头时,设置backing_up=1,并让驱动电机以backup_speed运行。同时,启动一个针对后退状态的监控循环,不断检查两个后保险杠传感器。一旦任何一个被触发,就立即广播 [Go Forward],让卡车停止后退并转为前进,脱离碰撞物。
转向逻辑(左/右箭头键):转向电机MD控制前轮角度。我们采用瞬时触发模式:
当 [左箭头 v] 键��按下 广播 [motor MD speed turn_speed] //假设左转为正速度 等待 (0.2) 秒 //让轮子转动一个角度 广播 [motor MD speed 0] //停止转向电机,轮子保持当前角度右箭头键同理,只是速度设为turn_speed的负值。这种“点动”转向方式,比持续���住转向更易控制,也更符合真实车辆的转向感觉。转向后,卡车会沿弧线行驶。需要回正时,向相反方向点按一下即可。
5.3 自动避障与防跌落安全逻辑
这是项目的核心智能部分,完全由传感器驱动,无需人工干预。我们需要在主循环(或并行的一个独立循环)中实现。
前方避障逻辑:在一个“重复执行”循环中,持续读取forward_ultrasonic_S2的值。
如果 <(forward_ultrasonic_S2) < [15]> 那么 //如果前方15厘米内有障碍 广播 [motor MA speed 0] //紧急停止 播放声音 [警报声 v] //可选,声光报警 等待 (1) 秒 广播 [motor MD speed turn_speed] //尝试左转 等待 (0.5) 秒 广播 [motor MD speed 0] 广播 [motor MA speed drive_speed] //尝试前进 结束这个逻辑很简单:检测到障碍就停车,等待一秒(模拟“思考”),然后尝试转向一个固定角度,再继续前进。你可以将其扩展为更复杂的“随机转向”或“转向直到路径畅通”的算法。
防跌落逻辑(朝下超声波传感器):在另一个“重复执行”循环中,持续读取downward_ultrasonic_S1的值。这个传感器安装在前方,指向地面。
如果 <(downward_ultrasonic_S1) > [20]> 那么 //如果地面距离突然大于20厘米(假设正常地面距离<10cm) 将 [backing_up] 设为 [1] //设置状态为“正在后退” 广播 [motor MA speed backup_speed] //紧急后退 等待 (1) 秒 //后退1秒 广播 [motor MA speed 0] 将 [backing_up] 设为 [0] //退出后退状态 说 [发现边缘!已后退!] 持续 (2) 秒 结束这里的关键是阈值的设定。你需要在实际场地上测量卡车正常行驶时,朝下传感器到地面的距离,然后设定一个比该距离大不少的安全阈值(例如2倍)。一旦测距值超过阈值,立即判定为前方有悬崖,触发紧急后退。
6. 系统调试、优化与项目扩展思考
6.1 常见故障排查与调试技巧
在实际操作中,你会遇到各种各样的问题。以下是我总结的排查清单:
| 问题现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 树莓派无法启动,或启动后黑屏 | 1. SD卡镜像烧录错误 2. 电源功率不足 3. HDMI线或显示器问题 | 1. 重新使用Etcher烧录官方镜像,确保验证通过。 2. 使用标称5V/2.5A以上的优质电源,并直接连接树莓派(不经过BrickPi)。 3. 尝试更换HDMI线和显示器接口。 |
| Scratch中找不到机器人积木块 | 未使用BrickPi专用系统镜像 | 确认刷写的是“BrickPi Robotics Image”,而非普通Raspbian。 |
| 电机/传感器无反应 | 1. 端口连接错误 2. 程序未发送 广播 [update]3. BrickPi服务未启动 4. 电池电量不足 | 1. 对照接线图,检查电机/传感器是否插在BrickPi正确的端口(MA, MD, S1-S4)。 2. 确保主循环中有 广播 [update]在持续执行。3. 重启树莓派,或通过终端命令 sudo systemctl status brickpi3检查服务状态。4. 更换全新电池或使用9V电源适配器。 |
| 超声波传感器读数不稳定或为0 | 1. 传感器前方有吸音材料 2. 物体表面不反射超声波(如绒毛) 3. 传感器安装不牢,震动 4. 多个超声波互相干扰 | 1. 在开阔、硬质表面(如木地板、桌面)测试。 2. 对准平整的硬质物体。 3. 用乐高零件将其牢牢固定。 4. 两个超声波传感器不要面对面放置,错开角度。 |
| 卡车行驶跑偏 | 1. 两个驱动轮摩擦力不同 2. 地面不平 3. 电机本身存在微小差异 | 1. 检查轮胎是否安装到位,清理轮胎上的灰尘。 2. 在平整光滑的表面上测试。 3. 在程序中为两个驱动轮(如果是双电机驱动)设置细微的速度补偿值。 |
| Scratch程序运行卡顿 | 1. 树莓派CPU过热降频 2. 同时运行了过多程序 3. 程序中有死循环或过于复杂的运算 | 1. 确保安装了散热片,环境通风。 2. 关闭不必要的浏览器标签和其他应用。 3. 优化Scratch脚本,避免在“重复执行”中嵌套过多“等待”或复杂运算。使用“广播”来分解逻辑。 |
6.2 性能优化与可靠性提升
经过基础功能实现后,可以从以下几个方面优化你的无人车:
- 速度与转向的PID平滑控制(进阶):目前的转向是“开环”控制,即给定一个固定时间和速度让轮子转动。可以引入简单的比例控制:让转向电机持续运行,直到一个颜色传感器或陀螺仪(如果未来加装)检测到车身已转到目标角度。这需要更复杂的编程,可以在学生掌握基础后作为进阶挑战。
- 电源管理优化:长时间运行,电池消耗很快。可以考虑使用大容量的USB充电宝(输出5V/2A以上)通过树莓派的USB口供电,同时用另一个电池盒单独为BrickPi和电机供电。这能显著延长运行时间。务必注意共地问题,稳妥起见还是使用BrickPi的原生电池盒供电方案。
- 无线控制与脱机运行:项目最后一步是拔掉HDMI线和USB键盘鼠标,换上一个无线迷你键盘触摸板。你还可以更进一步,为树莓派配置Wi-Fi,启用VNC或SSH。这样你就可以用另一台电脑远程登录树莓派的桌面,无线修改和调试Scratch程序,实现真正的“无人”遥控。
- 增加状态反馈:利用树莓派的音频输出,可以为不同事件(如遇到障碍、电量低)配置不同的提示音。甚至可以利用Scratch的“说”功能,结合语音合成软件(如espeak),让卡车用语音报告状态,增加项目的趣味性和交互性。
6.3 项目扩展与教学应用场景
这个“无人配送车”项目是一个绝佳的教学平台原型,可以衍生出无数STEAM课程:
- 算法升级:将简单的“遇到障碍就停然后随机转”的避障逻辑,升级为“沿墙走”算法或“A*寻路”算法的简化版。这可以引入计算机科学中的搜索和规划概念。
- 多传感器融合:增加颜色传感器,让卡车沿着地面上的黑色胶带轨道行驶(巡线车)。增加陀螺仪传感器,实现更精确的角度转向控制。这涉及到传感器数据的滤波与融合。
- 物联网集成:利用树莓派的网络功能,编写一个简单的Python Flask web服务器。学生可以通过手机浏览器访问一个控制页面,点击按钮来控制卡车前进后退,并实时查看摄像头画面(需加装Pi Camera)和传感器数据。这引入了网络通信和Web开发的基础概念。
- 模拟真实场景:设计一个微型社区地图,包含“住宅”(二维码贴纸)、“配送中心”和“道路”。卡车需要巡线到达“住宅”,通过摄像头识别二维码(代表门牌号),放下货物(通过一个舵机控制的释放机构),然后返回。这是一个综合性的项目挑战。
从我个人的教学经验来看,这个项目的魅力在于其极高的“可及性”和“可扩展性”。学生从搭建乐高车体开始,接触到机械结构;连接电路时,理解了输入(传感器)与输出(电机)的概念;用Scratch编程时,实践了事件、循环、条件判断和变量等核心编程思想;最后看到自己编写的逻辑转化为物理世界的动作时,那种成就感是无可替代的。它完美地诠释了“做中学”的理念,将抽象的代码与具象的物理运动紧密联系在一起,这正是创客教育和STEAM教育的精髓所在。
