基于Arduino与激光测距传感器的猫型清洁机器人DIY全攻略
2026/6/1 13:42:56 网站建设 项目流程

1. 项目概述与核心思路

最近在整理工作室,发现角落里堆了不少Arduino Nano、电机驱动模块和几个闲置的VL53L0X激光测距传感器。看着这些零件,我琢磨着能不能做个既好玩又有实际用处的小东西。扫地机器人太常见,做个方盒子在地上转来转去也没啥意思。正好手边有台3D打印机,于是灵光一闪:为什么不做一个有“生命感”的清洁机器人呢?比如,一只会自己满屋子跑、遇到障碍会“思考”并绕开、累了还会“休息”的猫型机器人。这个想法就成了“猫型机器人清洁器”项目的起点。

这个项目的核心目标,是打造一个能够自主在室内移动并进行简单拖地清洁的机器人平台。它看起来像一只猫,行为逻辑也模拟了猫的某些特性:比如用“胡须”(激光测距传感器)探测周围,灵活地转身,以及一个会摆动的“尾巴”。其技术核心在于环境感知与自主决策。我们通过一个激光测距传感器实时获取前方障碍物的距离信息,Arduino主板根据这些数据,结合一套简单的状态机与避障算法,来控制两个驱动轮电机和一个负责抬起/放下拖布的伺服电机,从而实现“前进-减速-转向-脱困”的完整行为链。

整个项目非常适合对机器人、嵌入式系统和3D建模打印感兴趣的爱好者。你不需要有深厚的电子工程背景,但需要一些动手焊接的耐心和读懂代码逻辑的能力。通过这个项目,你能亲手实践从传感器数据采集、电机PWM控制、到行为逻辑编程,再到机械结构设计与组装的完整创客流程。下面,我就把从零件堆到一只“电子猫”满地跑的全过程,包括我踩过的坑和总结的技巧,毫无保留地分享出来。

2. 硬件选型、电路设计与核心原理

硬件是整个机器人的骨骼与神经系统。选对零件、搭好电路,是项目成功的第一步。我的原则是在满足功能的前提下,尽量选择常见、易采购且文档丰富的模块,这样出了问题也容易排查。

2.1 核心控制器与感知模块

主控:Arduino Nano。选择它而不是UNO,主要是看中了其小巧的体型,能轻松塞进机器人“身体”里。Nano的GPIO数量、处理能力和内存对于本项目绰绰有余。需要注意的是,市面上有不同版本的Nano(如采用CH340或FT232串口芯片),在安装驱动时要区分清楚。

环境感知:VL53L0X激光测距传感器。这是本项目的“眼睛”。为什么选激光而不是超声波?因为激光测距精度高(毫米级)、方向性好、响应快,且不易受环境噪声干扰。VL53L0X通过I2C通信,体积小巧,测距范围约30-1000mm,完全满足室内避障需求。其原理是发射一束不可见的激光,测量光束反射回来的飞行时间(Time-of-Flight, ToF),从而计算出距离。这个传感器有个很实用的特性:可以通过软件改变I2C地址。这意味着你可以在一条I2C总线上挂载多个传感器,实现多方向测距(比如左、中、右),这也是后续算法优化的一个方向。

状态显示与交互:0.96英寸OLED显示屏(I2C接口)。它并非必需,但强烈建议加上。在调试阶段,你可以实时显示传感器读数、机器人当前状态(如“前进”、“左转”、“被困”)、电池电压等信息, invaluable。它和VL53L0X共用I2C总线,因为地址不同(OLED通常为0x3C或0x3D,VL53L0X默认0x29),所以不会冲突。

电机驱动:L298N或TB6612FNG双路电机驱动模块。我最初用的是经典的L298N,但它发热量较大。后来换成了TB6612FNG,效率更高,体积更小,且内置保护电路。两者都能通过PWM信号控制电机的速度和方向。本项目需要驱动两个减速电机作为机器人的左右轮。

执行器:

  1. 驱动电机:两个TT马达(带减速齿轮箱)。减速比的选择很重要,我用的是一套1:48的金属齿轮箱配套电机。减速比大,扭矩大,机器人“力气”足,能推动小拖布,但速度会慢一些。你需要根据你设计的机器人重量和想要的移动速度来权衡。
  2. 清洁机构:一个9g微型伺服电机(SG90)。它的作用是控制一个连杆机构,从而抬起或放下机器人底部的拖布。当机器人正常移动时,拖布放下;当它需要长时间停留或“被困”时,可以抬起拖布避免弄脏同一片区域。

启动与交互:电容触摸传感。为了保持外观简洁,我没有用实体按钮。而是用两个1MΩ的电阻配合Arduino的GPIO,实现了简单的电容触摸传感。手指触摸连接到GPIO的导线或铜箔,会轻微改变引脚的电容值,Arduino通过检测这个变化来触发启动或模式切换。这是一种低成本、有趣的交互方式。

声光反馈:有源压电蜂鸣器。连接到一个GPIO,用于播放启动音效、报警或(如原项目所说)待机时的“帝国进行曲”。编程时要注意,Arduino的tone()函数可以产生不同频率的声音,但播放复杂音乐需要精心编排频率和延时。

电源:7.4V 2S锂聚合物电池。电机驱动模块和伺服电机需要较高的电压(通常6-12V)才能获得良好性能,而Arduino Nano和传感器需要稳定的5V。因此,电池的7.4V输出直接给电机驱动模块供电,同时通过一个降压模块(或利用某些电机驱动板上的5V稳压输出)为控制部分提供5V电源。务必注意:伺服电机在动作时电流冲击较大,最好单独供电或确保电源有足够余量,否则可能导致Arduino复位。

2.2 电路连接详解与避坑指南

电路连接图是项目的“地图”,务必理清。下面是我的接法,并附上关键注意事项:

  1. I2C总线:将Arduino Nano的A4 (SDA)A5 (SCL)引脚,分别连接到VL53L0X传感器和OLED显示屏的对应引脚。同时,将它们的VCC接至Arduino的5V输出,GND接至公共地。注意:务必在I2C总线的SDA和SCL线上各加一个4.7kΩ的上拉电阻到5V。很多模块内置了上拉电阻,但如果通信不稳定,外加上拉电阻是首要排查点。

  2. 电机驱动连接(以TB6612FNG为例):

    • 电源:驱动模块的VM接电池正极(7.4V),GND接电池负极。VCC接5V为逻辑部分供电。
    • 控制信号:驱动模块需要每路电机两个控制信号(AIN1/AIN2和PWMA用于电机A;BIN1/BIN2和PWMB用于电机B)。
      • 左轮电机:我连接AIN1->D8,AIN2->D7,PWMA->D6
      • 右轮电机:连接BIN1->D12,BIN2->D11,PWMB->D10
      • STBY(待机)引脚接高电平(如5V)以启用驱动。
    • 电机输出:将左右电机的线分别接到驱动模块的AO1/AO2BO1/BO2
  3. 伺服电机:信号线(通常是橙色或白色)接D5。电源正极(红色)接一个独立的5V电源(或来自电池经降压的5V,但电流要足),负极(棕色或黑色)接公共地。重要:切勿直接从Arduino板载的5V引脚取电给伺服电机,瞬间电流可能导致板子重启。

  4. 电容触摸传感器:两个1MΩ电阻,一端分别接D14 (A0)D15 (A1),另一端接在一起并连接到公共地。同时,在D14和D15引脚上各焊接一小块铜箔或导线作为触摸点。程序里会将这些引脚设置为输入上拉模式,触摸时引脚被拉低,从而检测到变化。

  5. 压电蜂鸣器:正极接D3,负极接GND。D3是Arduino Nano的硬件PWM引脚之一,适合用tone()函数发声。

实操心得:电源与噪声处理电机是最大的噪声源。我在每个电机的两个引脚之间焊接了一个0.1μF的陶瓷电容,并在电机的电源输入处并联了一个100μF的电解电容。这能有效吸收电机换向时产生的尖峰电压和电气噪声,防止干扰微控制器和传感器,导致程序跑飞或传感器读数异常。这个步骤看似微小,但能极大提升系统稳定性,强烈建议不要省略。

3. 机械结构设计与3D打印要点

机器人的“身体”决定了它的稳定性、灵活性和外观。设计时需要考虑重心分布、传感器安装位置、电机固定方式以及内部走线空间。

3.1 3D模型设计与调整

原项目提供了几个STL文件(Cat_base.stl,Cat_body.stl,Cat_face.stl,Cat_rod.stl,Cat_sensor.stl)。我直接打印了这些部件,但在组装过程中发现了一些可以优化的地方。

  • 底盘(Cat_base):这是核心承重结构。它需要牢固地固定两个TT马达齿轮箱、万向轮(或脚轮)、电池仓以及主控板。原设计可能空间紧凑,我在用Fusion 360重新建模时,特意为电线预留了走线槽和束线孔,避免内部线材杂乱,被齿轮绞住。同时,在安装电机的位置增加了加强筋,防止高速移动时螺丝松脱或塑料开裂。
  • 传感器支架(Cat_sensor):用于固定VL53L0X传感器。设计时要确保传感器水平向前,并且前方没有结构遮挡其激光发射和接收窗口。我增加了可调节角度的设计(通过一个带弧槽的零件和螺丝固定),这样可以根据实际情况微调传感器的俯仰角,以探测不同高度的障碍物。
  • 连杆机构(Cat_rod):这是连接伺服电机和拖布的关键传动部件。它需要将伺服电机有限的旋转运动(通常0-180度)转换为拖布足够的升降行程。设计时需要进行简单的运动仿真,确保在伺服电机的整个运动范围内,拖布能完全抬起且不与底盘干涉。我使用了舵盘球头连杆的组合,这样比硬连接更灵活,能容忍一定的安装误差。
  • 外壳与装饰(Cat_body, Cat_face):这部分可以自由发挥,让机器人更像一只猫。注意留出OLED屏幕的显示窗口、蜂鸣器的出声孔以及触摸感应的接触区域。为了便于维修,我将身体设计成了可拆分的前后两部分,用螺丝或卡扣固定。

3.2 3D打印参数与后处理

  • 材料:推荐使用PLA+PETG。PLA容易打印但较脆,PETG韧性更好,更耐冲击,适合可能发生碰撞的机器人部件。
  • 层高与填充:结构件(如底盘、支架)使用0.2mm层高,25%-30%的网格填充,以保证强度。装饰性外壳可以用0.15mm层高,15%填充以节省时间和材料。
  • 支撑:对于有悬空结构的部分(如底盘下方的电机座),需要生成支撑。务必仔细设置支撑与模型的接触面,确保后期容易拆除且不损坏模型表面。
  • 后处理:打印完成后,仔细清除所有支撑材料。用M3或M2.5的自攻螺丝来组装部件,在需要频繁拆卸的部位(如检修盖),可以考虑嵌入黄铜螺纹嵌件,这样螺丝可以反复拧紧而不会滑丝,极大地提升了耐用性和体验。

4. 核心代码逻辑与避障算法解析

代码是机器人的“大脑”。其核心是一个基于有限状态机(FSM)的循环,不断读取传感器数据,根据预设规则改变机器人的行为状态。

4.1 程序框架与初始化

首先,需要引入所有必要的库:Wire.h用于I2C通信,VL53L0X.h用于激光测距,Adafruit_SSD1306.h用于OLED显示,Servo.h用于控制伺服电机。

#include <Wire.h> #include <VL53L0X.h> #include <Adafruit_SSD1306.h> #include <Servo.h> // 引脚定义 #define MOTOR_AIN1 8 #define MOTOR_AIN2 7 #define MOTOR_PWMA 6 // ... 其他引脚定义 // 对象声明 VL53L0X sensor; Adafruit_SSD1306 display(128, 64, &Wire, -1); Servo mopServo; // 全局变量 int distance = 0; enum RobotState { STANDBY, FORWARD, SLOW_DOWN, TURN_LEFT, TURN_RIGHT, BACK_AND_TURN }; RobotState currentState = STANDBY; unsigned long lastObstacleTime = 0; const long CLEANING_DURATION = 600000; // 清洁10分钟 void setup() { Serial.begin(115200); Wire.begin(); // 初始化传感器、显示屏、电机驱动引脚、伺服等 sensor.init(); sensor.setTimeout(500); // 电机驱动引脚设置为OUTPUT // 电容触摸引脚设置为INPUT_PULLUP // 伺服电机附着引脚 mopServo.attach(SERVO_PIN); mopServo.write(90); // 初始位置,拖布放下 // 播放启动音 playStartSound(); }

4.2 主循环与状态机实现

loop()函数是核心,它高速循环,执行以下步骤:

  1. 读取传感器:获取前方障碍物的距离(单位:毫米)。
  2. 检查触摸输入:判断是否被触摸以切换待机/工作模式。
  3. 状态决策:根据当前距离和状态,决定下一个状态。
  4. 执行动作:调用对应状态的函数,控制电机和伺服。
  5. 更新显示与计时:在OLED上显示信息,检查清洁是否超时。
void loop() { distance = sensor.readRangeSingleMillimeters(); // 读取距离 if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } checkTouch(); // 检查触摸,切换STANDBY和运行模式 if (currentState != STANDBY) { // 状态决策逻辑 if (distance > 500) { currentState = FORWARD; // 远处无障碍,全速前进 } else if (distance > 200 && distance <= 500) { currentState = SLOW_DOWN; // 中等距离,减速 } else if (distance > 50 && distance <= 200) { currentState = TURN_LEFT; // 很近,左转避障 } else { // 距离 <= 50mm,非常近,可能卡住 currentState = BACK_AND_TURN; } // 防止长时间困在原地 if (currentState == FORWARD || currentState == SLOW_DOWN) { lastObstacleTime = millis(); } else if (millis() - lastObstacleTime > 10000) { // 10秒没前进 currentState = BACK_AND_TURN; lastObstacleTime = millis(); } // 执行状态动作 switch (currentState) { case FORWARD: moveForward(255); break; // 全速 case SLOW_DOWN: moveForward(150); break; // 半速 case TURN_LEFT: turnLeft(200, 100); break; // 左轮后退,右轮前进 case TURN_RIGHT: turnRight(100, 200); break; case BACK_AND_TURN: moveBackwardThenTurn(200, 1500); break; // 后退1.5秒后随机转 case STANDBY: stopMotors(); break; } // 控制尾巴(伺服)摆动 - 增加“生命力” wagTail(); // 检查清洁时间 if (millis() - startCleaningTime > CLEANING_DURATION) { currentState = STANDBY; mopServo.write(70); // 抬起拖布 playStandbyMusic(); // 播放待机音乐 } } else { // 待机模式,只显示和播放音乐 playStandbyMusic(); } updateDisplay(distance, currentState); // 更新OLED显示 delay(50); // 主循环延迟,控制反应速度 }

4.3 关键函数与算法细节

  • moveForward(speed): 设置两个电机同向同速转动。速度值(0-255)对应PWM占空比。
  • turnLeft(leftSpeed, rightSpeed): 实现转向。让左轮速度小于右轮甚至反转,机器人就会向左转。这里的参数需要根据实际电机特性调整,可能需要进行电机校准,因为即使同一型号的电机,空载转速也有细微差异。
  • backAndTurn(): 脱困策略。先让两个电机反转一段时间(如1秒)后退,然后一个电机正转一个反转,实现原地旋转一个随机角度,再尝试前进。这能有效解决机器人卡在墙角或家具腿之间的困境。
  • wagTail(): 让伺服电机在90度基准位置附近来回缓慢摆动,模拟猫摇尾巴。注意伺服电机动作不宜太快太频繁,以免耗电过大。

算法优化心得:动态阈值与历史记忆最初的算法使用固定的距离阈值(如500mm, 200mm)。但在实际中,环境光变化、不同颜色的物体对激光反射率不同,会导致测量值有波动。我后来改进了算法,加入了动态阈值调整简单滤波。例如,连续读取5次距离值,取中位数,避免单次误读。还可以根据一段时间内的平均距离,微调减速和转向的阈值,让机器人的行为更平滑。 另外,我增加了一个简单的“记忆”功能:当连续多次在类似位置触发转向时,机器人会判断该区域可能过于复杂,主动执行一次BACK_AND_TURN进行大范围脱困,而不是在原地左右“挣扎”。

5. 组装、调试与问题排查实录

将硬件、结构和代码结合起来,并让机器人可靠地工作,这个阶段会遇到最多问题。

5.1 分步组装流程

  1. 底盘组装:先将两个TT马达用螺丝牢固安装在底盘两侧。安装万向轮。将电机驱动板、Arduino Nano用铜柱或尼龙柱固定在底盘上预留的位置。
  2. 电路连接:按照之前的电路图焊接或使用杜邦线连接所有模块。强烈建议先不要封闭外壳,保持所有线路可见,便于调试。给电池接上一个电源开关,方便随时断电。
  3. 上传代码与基础测试:连接USB线,上传最基本的测试代码(例如,让两个电机正反转各3秒,读取并串口打印传感器距离,让伺服运动到几个角度)。确保每个模块单独工作正常。
  4. 安装传感器与上层结构:将VL53L0X固定到传感器支架上,并安装到机器人前部。安装OLED屏幕。组装猫的身体外壳,注意留出线孔。
  5. 安装清洁机构:将伺服电机固定在底盘指定位置,连接连杆和拖布支架。调整伺服的中位角度,确保拖布能平稳放下和完全抬起。
  6. 总装与布线:将电池放入电池仓。仔细整理所有电线,用扎带或线槽固定,防止卷入车轮或齿轮。最后盖上装饰性的外壳。

5.2 系统调试与参数校准

组装完成后,需要进行系统级调试:

  1. 电机转向校准:编写一个测试程序,让两个电机都“前进”。观察机器人实际是直行、左偏还是右偏。如果偏航,可以通过软件交换一个电机的转向逻辑,或者微调两个电机的PWM基准值来补偿速度差异。
  2. 传感器精度测试:让机器人面对墙壁不同距离(例如100mm, 300mm, 500mm),通过串口监视器查看传感器读数是否稳定准确。如果跳动大,检查传感器是否固定牢固,前方有无灰尘或遮挡,并尝试在代码中增加软件滤波。
  3. 避障逻辑实地测试:在空旷地面放置纸箱或椅子作为障碍物。观察机器人在不同距离下的反应(全速、减速、转向)是否符合预期。重点调试BACK_AND_TURN的触发条件和动作幅度,这是避免机器人“卡死”的关键。
  4. 功耗与续航测试:满电状态下让机器人连续工作,记录直到电池低压或停止工作的时间。检查各模块(尤其是电机驱动和伺服)的发热情况。如果发热严重或续航太短,考虑优化代码(如减少伺服频繁动作、采用更高效的PWM频率)或更换容量更大的电池。

5.3 常见问题与解决方案速查表

问题现象可能原因排查步骤与解决方案
上电后无任何反应1. 电源开关未开或接触不良。
2. 电池电量耗尽。
3. Arduino未上电或损坏。
1. 检查开关,用万用表测量电池输出电压。
2. 给电池充电。
3. 单独用USB给Arduino供电测试。
电机不转或只单向转1. 电机驱动模块供电不足或未使能。
2. 控制引脚连接错误或虚焊。
3. 程序PWM值始终为0或逻辑错误。
1. 检查电机驱动模块的VM和GND输入电压,确认STBY引脚为高电平。
2. 用万用表或示波器检查控制引脚信号。
3. 编写简单电机测试程序,逐步排查。
激光传感器读数始终为0或超大值1. I2C通信失败。
2. 传感器前方有遮挡或强光直射。
3. 传感器本身损坏。
1. 检查I2C线路、上拉电阻,用扫描程序确认传感器地址(0x29)。
2. 清洁传感器窗口,避免在阳光直射下使用。
3. 更换传感器测试。
机器人行为混乱,乱撞1. 传感器数据读取不稳定或延迟大。
2. 避障算法阈值设置不合理。
3. 电机响应速度过快,导致超调。
1. 增加传感器读数滤波(如中值滤波、均值滤波)。
2. 根据实际环境(地板反光、家具颜色)重新校准距离阈值。
3. 在主循环中增加适当延迟(delay),或降低电机PWM变化速率。
伺服电机动作时Arduino重启伺服电机工作时电流过大,导致系统电压被拉低。绝对不要从Arduino板载5V取电给伺服!为伺服电机提供独立的5V电源(可从电池经降压模块获得),并与Arduino共地。
OLED显示屏不亮或花屏1. I2C地址不正确。
2. 供电不足。
3. 初始化代码错误。
1. 使用I2C扫描工具确认OLED地址(通常是0x3C)。
2. 检查连接,确保电源稳定。
3. 核对Adafruit_SSD1306库的初始化参数(屏幕尺寸、复位引脚号)。
电容触摸不灵敏1. 触摸点面积太小或接触不良。
2. 上拉电阻值不合适。
3. 程序检测阈值设置过高。
1. 增大触摸铜箔面积,确保手指能良好接触。
2. 尝试更换不同阻值的上拉电阻(如500kΩ-2MΩ)。
3. 在程序中降低触发所需的电平变化阈值或采用多次检测防抖。

6. 功能扩展与进阶玩法

基础功能实现后,这个平台还有很大的扩展空间,可以让你的“电子猫”变得更聪明。

1. 多传感器融合:

  • 增加侧面传感器:再添加1-2个VL53L0X传感器,分别指向左前和右前方。通过修改I2C地址(VL53L0X支持此功能),可以在一条总线上挂载多个。这样机器人就能感知侧方障碍,实现更流畅的沿墙走或贴边清洁。
  • 增加“触须”:在机器人两侧安装轻触开关或红外避障传感器,作为近距离碰撞检测的最后一道防线,防止激光传感器漏检透明或深色物体。

2. 算法升级:

  • 随机游走与区域覆盖:引入简单的随机数,让机器人在转向时加入随机角度,避免陷入固定的行走模式,提高清洁覆盖率。
  • 简单地图构建:如果使用更高级的主控(如ESP32),可以结合里程计(通过编码器电机估算行走距离和转角)和传感器数据,在OLED上绘制一个极简的、基于栅格的环境示意图。

3. 交互与联网:

  • 蓝牙/Wi-Fi控制:添加HC-05蓝牙模块或ESP-01s WiFi模块,通过手机APP或网页远程启动、停止机器人,或切换为手动遥控模式。
  • 状态上报:将电池电量、清洁时间、遇到的障碍次数等信息通过无线模块发送到手机,方便查看。

4. 清洁效果优化:

  • 振动拖布:在拖布支架上安装一个小型振动电机,在清洁时产生微震动,增强去污效果。
  • 可更换清洁头:设计快拆结构,方便更换为干擦布、湿拖布甚至小吸尘头。

这个项目从一堆散件到一只满屋跑的“小猫”,整个过程充满了动手的乐趣和解决问题的成就感。它不仅仅是一个清洁工具,更是一个涵盖了电子、编程、机械的综合性实践平台。我最深的体会是,在嵌入式项目中,稳定性往往比功能的复杂度更重要。那些看似不起眼的细节——电源滤波、机械结构的稳固、软件里的防抖滤波——往往是决定项目成败的关键。当你看到它第一次成功避开桌腿,摇着尾巴转向另一个方向时,那种感觉,棒极了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询