1. 项目概述:从扩展板到可编程小车
最近在工作室整理物料,翻出了一套闲置许久的树莓派小车套件,核心是一块基于树莓派GPIO的电机驱动扩展板。这玩意儿买来吃灰好几年了,一直想找个机会让它动起来,但又不想写太复杂的底层驱动代码。正好,之前在一个极客社区里看到有人提过bitlash-coder这个工具,号称能用一种简化的脚本语言快速控制硬件,特别适合做原型验证和教育场景。这不就是为我这种“懒人”准备的吗?于是,一个周末的下午,我决定把这个小车拼起来,并试试用 bitlash-coder 来驾驭它。
这个项目的目标很明确:零基础组装一台树莓派智能小车,并为其安装配置 bitlash-coder 开发环境,最终通过编写简单的脚本让小车实现基本运动控制。它非常适合刚接触树莓派和硬件编程的朋友,或者像我一样想快速验证一个硬件想法而无需深入嵌入式C语言开发的爱好者。整个过程你会接触到硬件组装、Linux基础操作、开发环境搭建和脚本编写,算是一个小而全的入门实践。
2. 硬件准备与小车拼装实录
动手之前,得先把“车”造出来。我手头的套件比较基础,主要包含以下几样东西:
- 树莓派主板:我用的是树莓派4B,性能足够,GPIO引脚兼容性好。树莓派3B+或更新的树莓派5当然也可以,注意一下电源适配器的电流要够(建议5V/3A)。
- 电机驱动扩展板:这是核心部件。它直接插在树莓派的GPIO排针上,板上通常集成了电机驱动芯片(如L298N、TB6612FNG)、电源管理模块和一些额外的接口(如舵机接口、传感器接口)。我的这块板子驱动两个直流电机,正好对应小车的左右轮。
- 底盘套件:包括亚克力或金属底盘、两个直流减速电机、轮子、万向轮(或从动轮)、一堆螺丝螺母和铜柱。
- 电源:给树莓派和电机供电。这里有个关键点:电机工作时电流较大,如果和树莓派共用同一个USB电源,可能会因电流冲击导致树莓派重启。稳妥的做法是,扩展板有独立的外接电源接口(如接线端子),用一块7.4V的锂电池或合适的直流电源单独给电机供电。树莓派则继续使用它自己的5V USB-C电源。
- 其他:杜邦线(公对公、母对母)、螺丝刀、可能需要的电池盒和开关。
2.1 底盘与电机安装
拼装过程其实像搭乐高,但有几个细节决定了小车跑得直不直、稳不稳。
首先,将两个直流电机用配套的螺丝固定在底盘两侧的电机座上。这里要注意电机的出轴方向,确保两个轮子都朝前。固定时螺丝不要拧得太紧,以免压坏电机外壳,但也不能太松导致电机晃动。
接着安装轮子。直流减速电机的轴通常是D型轴,轮子内侧有对应的D型孔,对准用力按进去即可。如果很紧,可以轻轻敲击轮毂外侧(垫块木头保护)。装好后用手转动轮子,应该顺畅无卡滞。
最后安装万向轮。我用的套件是单个万向球轮,安装在底盘前部或后部的中心位置,作为从动轮支撑和转向。确保安装牢固,高度调整到使底盘基本水平。
2.2 扩展板与树莓派连接
这是硬件连接中最需要细心的一步。
- 断电操作:确保树莓派和任何外接电源都处于完全断电状态。
- 对准引脚:将电机驱动扩展板小心地对准树莓派的40针GPIO排针。务必确认方向正确!通常扩展板会标有“PIN1”或有一个缺口标记,对应树莓派GPIO排针上也有一个缺口(PIN1通常是靠近SD卡槽那一侧,有方形焊盘的那个引脚)。对准后垂直、平稳地按下,直到扩展板完全 seated。
- 连接电机:扩展板上会有标记为
M1A/M1B、M2A/M2B或OUT1/OUT2、OUT3/OUT4的端子。用杜邦线将左侧电机的两根线连接到一组输出(例如M1A和M1B),右侧电机连接到另一组输出(例如M2A和M2B)。电机线序接反了只会导致轮子反转,后期在软件里可以调整,所以不用太担心。 - 连接电源:
- 树莓派电源:使用原装或可靠的5V/3A USB-C电源适配器,直接插入树莓派的USB-C口。
- 电机电源:将外接电池(如7.4V锂电池)的正负极接到扩展板标有
VM或电机电源的端子上。务必注意正负极!接反可能会损坏驱动芯片。扩展板上通常还有一个跳线帽,用于选择是否将电机电源(VM)与树莓派逻辑电源(VCC)连通。对于独立供电的情况,这个跳线帽必须拔掉!否则高压会灌入树莓派,后果严重。
- 初步检查:连接完成后,先不要上电机电源。只给树莓派上电,观察扩展板上的指示灯(如果有)是否正常(例如树莓派供电指示灯亮)。然后用手轻轻转动轮子,应该能感觉到一定的阻力(电机驱动芯片内部电路的原因),这是正常的。
注意:整个拼装过程,最怕的就是电源接错和短路。在首次通电前,花两分钟检查所有接线:树莓派电源独立、电机电源极性正确、电机电源与逻辑电源隔离跳线已移除。这能避免绝大部分“冒烟”悲剧。
3. 树莓派系统准备与bitlash-coder安装
硬件就绪,接下来是软件环境。我们需要一个运行在树莓派上的操作系统,以及bitlash-coder本身。
3.1 树莓派系统烧录与基础配置
我选择官方的Raspberry Pi OS (Legacy) with desktop,基于Debian,兼容性好,桌面环境方便初次操作。
- 下载与烧录:从树莓派官网下载Raspberry Pi Imager工具。插入一张至少16GB的MicroSD卡,在Imager中选择操作系统(Raspberry Pi OS 32-bit),选择存储卡,然后点击“烧录”。烧录完成后,Imager会提示你“设置”,这是一个非常方便的功能。
- 预配置:在烧录完成后的设置窗口中,你可以预先:
- 设置主机名(如
raspberrypi-car)。 - 开启SSH服务,并设置密码。这样组装好后可以直接用网线连接电脑,通过SSH远程操作,无需接显示器键盘。
- 配置Wi-Fi国家和网络(如果需要无线连接)。
- 设置地区、时区。
- 设置一个用户名和密码(建议不用默认的
pi用户,安全起见)。 完成设置后,安全弹出SD卡。
- 设置主机名(如
- 首次启动与网络连接:将SD卡插入树莓派,连接网线到路由器,然后上电。等待几分钟让系统启动。在你的电脑上,可以使用
ping raspberrypi-car.local(如果你改了主机名)或者通过路由器管理界面查看树莓派获取到的IP地址。然后使用SSH客户端(如Windows的PuTTY或PowerShell SSH, macOS/Linux的终端)连接:ssh your_username@raspberrypi-car.local。 - 基础更新与工具安装:登录后,首先更新系统并安装一些常用工具。
sudo apt update sudo apt upgrade -y sudo apt install -y git python3-pip vim
3.2 bitlash-coder 安装详解
bitlash-coder 是一个开源项目,我们需要从代码仓库克隆并安装。
克隆仓库:
cd ~ git clone https://github.com/bitlash/bitlash-coder.git cd bitlash-coder如果网络不畅,可以尝试使用镜像源,或者先在其他地方下载好再传到树莓派上。
安装依赖:bitlash-coder 主要是一个Python项目,它通过RPi.GPIO或gpiozero库来控制GPIO。安装必要的Python包。
pip3 install -r requirements.txt通常
requirements.txt里会包含RPi.GPIO。如果文件不存在或安装失败,可以手动安装:pip3 install RPi.GPIO权限问题处理:在树莓派上,非root用户直接操作GPIO可能需要权限。最方便的方法是将当前用户加入
gpio组。sudo usermod -a -G gpio $USER执行后,需要注销并重新登录SSH会话,或者重启树莓派,才能使组权限生效。你可以用
groups命令检查gpio组是否已在当前用户的组列表中。初步测试安装:进入bitlash-coder目录,通常有一个主脚本,比如
bitlash.py或coder.py。我们可以先运行一个简单的交互模式看看。python3 bitlash.py如果看到欢迎信息或一个
>>提示符,说明核心环境没问题。按Ctrl+C退出。
4. bitlash-coder核心功能与小车控制脚本编写
bitlash-coder的核心思想是提供一个解释器,让你用一种类似BASIC的简单脚本语言(bitlash)来实时控制硬件。我们不需要编译,写一行命令,回车就能看到效果,非常适合交互式学习和快速测试。
4.1 bitlash语言基础与硬件控制函数
首先,我们需要了解如何用bitlash命令控制我们的扩展板。这需要知道扩展板的电机控制引脚对应树莓派GPIO的哪个物理引脚。
查引脚对应关系:树莓派GPIO有物理引脚编号(Board编号)和BCM编号两种体系。扩展板的丝印或说明书通常会标明它使用的引脚定义。例如,我的板子M1A、M1B、M2A、M2B分别对应BCM编号的17、18、22、23。你必须根据自己扩展板的文档来确定这个映射!如果找不到文档,一个笨办法是:用万用表蜂鸣档,在扩展板断电时,测量电机输出端子与树莓派GPIO排针哪个引脚是导通的。
假设我的映射是:
- 左电机前进/后退:BCM 17 (IN1), BCM 18 (IN2)
- 右电机前进/后退:BCM 22 (IN3), BCM 23 (IN4)
在bitlash-coder中,通常已经封装好了电机控制的函数。我们需要查看项目文档或示例代码来找到对应的函数名。常见的形式可能是motor(pin1, pin2, speed)或者有专门的car_forward(),car_turn()等函数。
为了通用性,我们假设需要直接控制GPIO高低电平来实现H桥控制(这是最底层的方式,所有驱动板都适用)。对于L298N这类驱动芯片,控制逻辑是:
- 让电机正转:IN1=高(1), IN2=低(0)
- 让电机反转:IN1=低(0), IN2=高(1)
- 让电机刹车/停止:IN1=高(1), IN2=高(1) 或 IN1=低(0), IN2=低(0)
在bitlash交互环境中,我们可以先测试控制一个电机。启动bitlash:
python3 bitlash.py在>>提示符下,输入bitlash命令。假设控制函数是digitalWrite(pin, value)。
>> pinMode(17, OUTPUT) // 设置BCM 17为输出模式 >> pinMode(18, OUTPUT) >> digitalWrite(17, 1) // IN1 = HIGH >> digitalWrite(18, 0) // IN2 = LOW此时,连接在M1A和M1B上的左轮电机应该开始朝一个方向转动。如果轮子反转,交换digitalWrite(17,1)和digitalWrite(18,0)的顺序即可。
4.2 编写小车运动控制脚本
在交互模式下一行行输入太麻烦。bitlash支持执行脚本文件。我们在bitlash-coder目录下创建一个控制脚本,比如car_control.bts。
// car_control.bts - 树莓派小车基础控制脚本 // 引脚定义 (根据你的扩展板修改!) var LEFT_FWD = 17; // BCM 17 var LEFT_BCK = 18; // BCM 18 var RIGHT_FWD = 22; // BCM 22 var RIGHT_BCK = 23; // BCM 23 // 初始化所有电机控制引脚为输出模式 function initPins() { pinMode(LEFT_FWD, OUTPUT); pinMode(LEFT_BCK, OUTPUT); pinMode(RIGHT_FWD, OUTPUT); pinMode(RIGHT_BCK, OUTPUT); stop(); // 初始状态停止 } // 停止所有电机 function stop() { digitalWrite(LEFT_FWD, 0); digitalWrite(LEFT_BCK, 0); digitalWrite(RIGHT_FWD, 0); digitalWrite(RIGHT_BCK, 0); delay(100); // 短暂延时,确保信号稳定 } // 前进:左轮正转,右轮正转 function forward() { digitalWrite(LEFT_FWD, 1); digitalWrite(LEFT_BCK, 0); digitalWrite(RIGHT_FWD, 1); digitalWrite(RIGHT_BCK, 0); } // 后退:左轮反转,右轮反转 function backward() { digitalWrite(LEFT_FWD, 0); digitalWrite(LEFT_BCK, 1); digitalWrite(RIGHT_FWD, 0); digitalWrite(RIGHT_BCK, 1); } // 左转:左轮后退(或停止),右轮前进 function turnLeft() { digitalWrite(LEFT_FWD, 0); digitalWrite(LEFT_BCK, 0); // 这里用停止,转弯更柔和。也可设为1实现原地旋转。 digitalWrite(RIGHT_FWD, 1); digitalWrite(RIGHT_BCK, 0); } // 右转:右轮后退(或停止),左轮前进 function turnRight() { digitalWrite(LEFT_FWD, 1); digitalWrite(LEFT_BCK, 0); digitalWrite(RIGHT_FWD, 0); digitalWrite(RIGHT_BCK, 0); // 这里用停止 } // 主程序:一个简单的自动行进演示 function main() { initPins(); print("小车启动!"); forward(); delay(2000); // 前进2秒 turnRight(); delay(1000); // 右转1秒 forward(); delay(2000); // 再前进2秒 turnLeft(); delay(1000); // 左转1秒 backward(); delay(1500); // 后退1.5秒 stop(); print("演示结束!"); } // 运行主程序 main();保存文件后,在bitlash交互环境中用load命令执行它:
>> load("car_control.bts")或者,更直接地在终端命令行运行:
python3 bitlash.py car_control.bts你应该能看到小车按照脚本的指令:前进、右转、前进、左转、后退,最后停止。
4.3 加入速度控制(PWM)
上面的脚本电机只有“开”和“关”两种状态,速度是固定的。要想控制小车速度,需要使用PWM(脉冲宽度调制)。树莓派的GPIO可以通过软件或硬件产生PWM信号。
bitlash-coder可能支持pwmWrite(pin, dutycycle)这样的函数,其中dutycycle范围是0(常闭)到255(常开)或0到100。我们需要查看其文档或源码确认。
如果支持,我们可以改进forward等函数,加入速度参数。同时,电机驱动板必须支持PWM输入(通常驱动芯片的ENA、ENB引脚就是接PWM的)。如果你的扩展板将ENA/ENB直接接高电平(使能),那么就需要改接线,将树莓派的PWM引脚(如BCM 12, 13)连接到ENA/ENB。
这是一个支持PWM的改进版forward函数示例(假设PWM引脚BCM 12接左电机使能ENA, BCM 13接右电机使能ENB):
var LEFT_PWM = 12; var RIGHT_PWM = 13; var LEFT_FWD = 17; var LEFT_BCK = 18; var RIGHT_FWD = 22; var RIGHT_BCK = 23; function forward(speed) { // speed: 0-255 // 设置方向 digitalWrite(LEFT_FWD, 1); digitalWrite(LEFT_BCK, 0); digitalWrite(RIGHT_FWD, 1); digitalWrite(RIGHT_BCK, 0); // 设置速度 pwmWrite(LEFT_PWM, speed); pwmWrite(RIGHT_PWM, speed); }在调用时就可以用forward(150)来以中等速度前进了。
5. 交互式控制与调试技巧
脚本自动化很好,但调试时我们更需要交互式实时控制。bitlash的交互模式本身就支持这一点。你可以写一个简单的“遥控”脚本,或者直接在交互命令行里定义函数。
一个更高级的玩法是利用bitlash的网络服务器功能(如果它支持),或者结合Python的socket或flask库,做一个简单的网页遥控界面。这里分享一个快速测试用的交互模式心得:
在bitlash交互环境中,你可以先加载你的引脚定义和基础函数文件,然后直接调用它们。
>> load("car_defs.bts") // 这个文件只包含var定义和initPins、stop等基础函数 >> initPins() >> forward() // 小车开始前进 >> // 让它跑一会儿... >> stop() // 小车停止 >> turnLeft() >> delay(500) >> stop()这种即时反馈对于调试电机接线、调整转弯比例(左右轮速度差)非常有用。
调试常见问题:
电机不转:
- 检查电源:电机电源开关开了吗?电池有电吗?万用表量一下电机端子电压是否正常。
- 检查接线:电机线是否插紧?是否接在了正确的端子上?
- 检查跳线帽:电机电源(VM)和逻辑电源(VCC)之间的跳线帽是否已移除?
- 检查软件:GPIO引脚号对吗?用户是否在
gpio组?可以用命令sudo raspi-gpio get来查看引脚当前状态。
只有一个电机转:
- 检查不转的那个电机的两根控制线是否都正确连接到扩展板。
- 在bitlash中单独测试控制这个电机的两个GPIO引脚,用
digitalWrite看是否能输出高电平。
小车跑偏:
- 这是最常见的问题。两个电机的实际转速不可能完全一致。解决方法是软件校准:在
forward函数中,给左右轮设置不同的PWM值。例如,如果小车总是向右偏,就稍微调低右轮PWM值或调高左轮PWM值。
function forward(speed) { var leftSpeed = speed; var rightSpeed = speed * 0.95; // 右轮打95折 pwmWrite(LEFT_PWM, leftSpeed); pwmWrite(RIGHT_PWM, rightSpeed); // ...方向控制代码 }- 你需要通过多次实地测试来找到合适的补偿系数。
- 这是最常见的问题。两个电机的实际转速不可能完全一致。解决方法是软件校准:在
bitlash命令未找到或执行错误:
- 仔细检查bitlash的语法。它可能和标准C或JavaScript有些不同,比如注释用
//,变量用var,但函数定义可能用function或def。以项目自带的示例脚本为准。 - 确保你运行bitlash解释器的路径下,有你所引用的脚本文件。
- 仔细检查bitlash的语法。它可能和标准C或JavaScript有些不同,比如注释用
6. 项目扩展与进阶思路
让小车基本动起来只是第一步。基于bitlash-coder的快速原型能力,你可以轻松扩展更多功能:
避障小车:添加一个HC-SR04超声波模块到扩展板的空闲GPIO上。在bitlash中编写函数
getDistance()来读取距离,然后在主循环中不断检测,如果距离小于10厘米,就调用stop()然后backward()或turnRight()。巡线小车:使用几个红外反射传感器,安装在底盘前方。bitlash脚本不断读取这几个传感器的值(高电平或低电平),根据“左中右”哪个传感器看到黑线,来决定是
forward()、turnLeft()还是turnRight()。蓝牙/Wi-Fi遥控:在树莓派上安装
pybluez库或使用Socket编程。写一个简单的Python服务器接收手机或电脑发来的指令(‘F‘, ’B‘, ’L‘, ’R‘, ’S‘),然后这个Python脚本调用bitlash-coder的API或者直接通过系统命令os.system('python3 bitlash_cmd.py forward')来间接控制小车。数据记录与可视化:让小车在运行时,将传感器数据(如距离、电机PWM值)和时间戳写入一个文本文件。跑完后,把文件传到电脑上,用Python的Matplotlib画个运行轨迹图或速度曲线,分析小车的性能。
我个人在折腾这个小车项目中最深的体会是:硬件项目,三分在软件,七分在调试。接线是否牢固、电源是否纯净、轮子是否打滑、地面是否平整,这些物理因素对结果的影响往往比代码里的一个参数大得多。bitlash-coder这类工具的价值,就在于它极大降低了软件部分的门槛,让你能把更多精力放在解决这些实际的物理和调试问题上,快速获得“动起来”的正反馈,这对于保持学习兴趣和创造力至关重要。下次如果你想让小车翻个跟头或者跳个舞,试着改改脚本里的延时和动作序列吧,乐趣就在其中。