资讯动态

从零打造Arduino蓝牙智能小车:避障、循迹与手机APP控制全攻略

发布时间:2026/9/1 6:42:24 来源:尧图企业网站定制
在实际嵌入式开发和学习中Arduino因其开源、易上手的特点成为许多初学者进入硬件编程世界的首选。而将Arduino与传感器、电机驱动模块结合制作一辆能够自主避障、循迹并能通过手机蓝牙遥控的智能小车则是一个集成了电子、编程、通信和机械的综合实践项目。这个项目不仅能让你理解数字信号、模拟信号、PWM调速、串口通信等核心概念还能亲手搭建一个看得见、摸得着的智能系统。本文旨在为零基础的爱好者提供一份从零开始的完整教程。我们将从硬件清单和电路连接讲起逐步完成Arduino程序Sketch的编写并深入讲解如何利用常见的手机APP开发工具如App Inventor 2制作一个专属的蓝牙控制APP。整个过程将覆盖避障传感器、红外循迹模块、HC-05/06蓝牙模块、L298N电机驱动板等关键部件的使用并解释每一步背后的原理和常见陷阱。完成本教程后你将拥有一辆能够通过手机APP遥控、自动避障、自动循黑线行驶的多功能智能小车并对嵌入式系统开发有一个扎实的入门理解。1. 硬件准备与电路连接在开始编程之前正确的硬件选型和电路搭建是项目成功的基础。这一部分将详细列出所需组件并解释它们的作用及连接方法。1.1 核心组件清单与功能说明下表列出了制作一辆基础多功能蓝牙小车所需的核心硬件。对于初学者建议购买现成的智能小车套件其中通常包含了车架、电机和轮子。组件名称数量主要功能关键参数/备注Arduino UNO R31主控板运行控制程序核心处理器ATmega328P输入电压7-12VL298N电机驱动模块1驱动直流电机控制其正反转和速度可驱动2路直流电机或1路步进电机需外部供电TT减速直流电机2或4提供小车动力通常与车轮配套工作电压3-6V注意减速比小车底盘及轮子1套承载所有电子元件包括底盘、电机固定架、轮子、万向轮等HC-05或HC-06蓝牙模块1实现Arduino与手机APP的无线串口通信HC-05可主从一体HC-06仅从机常用波特率9600超声波测距模块 (HC-SR04)1实现避障功能测量前方障碍物距离测距范围2cm-400cm精度3mm红外循迹传感器3或5实现循迹功能检测地面黑线数字输出检测到黑线输出高电平或低电平可调18650锂电池及电池盒1套为整个系统供电两节串联约7.4V可为驱动板和Arduino供电杜邦线公对公、公对母若干连接各模块建议准备多种长度和接口类型面包板可选1便于电路连接和测试对于复杂接线有帮助1.2 电路连接详解与原理连接电路时务必在断电状态下操作。整个系统的供电逻辑是锂电池为L298N驱动板供电L298N上的5V输出可以为Arduino和传感器供电从而简化布线。1.2.1 电机与L298N驱动板连接将两个直流电机分别连接到L298N的OUT1、OUT2电机A和OUT3、OUT4电机B。电机的正反转由这两个输出口的电平组合控制。1.2.2 L298N与Arduino及电源连接电源将锂电池正极VCC接L298N的12V输入负极GND接L298N的GND。控制信号将L298N的ENA、IN1、IN2、IN3、IN4、ENB分别连接到Arduino的数字引脚。ENA/B用于PWM调速IN1/2和IN3/4用于控制转向。示例连接ENA - D5,IN1 - D6,IN2 - D7,IN3 - D8,IN4 - D9,ENB - D10。供电将L298N板载的5V输出引脚连接到Arduino的VIN或5V引脚具体取决于板载稳压芯片是否启用并将两者的GND相连。注意如果使用外部7-12V电源直接给Arduino供电则无需此连接但必须确保Arduino与L298N的GND共地。1.2.3 超声波模块连接HC-SR04有四个引脚VCC、GND、Trig、Echo。VCC- Arduino5VGND- ArduinoGNDTrig- Arduino 数字引脚 (如D2)Echo- Arduino 数字引脚 (如D3)1.2.4 红外循迹传感器连接以三路传感器为例每个传感器有三个引脚VCC、GND、OUT。VCC- Arduino5VGND- ArduinoGNDOUT- 分别接至Arduino的三个数字引脚 (如D11,D12,D13)。传感器上通常有电位器可调节检测灵敏度。1.2.5 蓝牙模块连接HC-05/06有四个引脚VCC、GND、TXD、RXD。VCC- Arduino5V(或3.3V需查阅模块规格)GND- ArduinoGNDTXD- ArduinoRX(D0)RXD- ArduinoTX(D1)注意Arduino的TX(D1)和RX(D0)引脚在烧录程序时被IDE占用。因此在连接蓝牙模块后烧录程序可能需要暂时拔掉蓝牙模块的TXD和RXD线否则可能导致上传失败。这是一个非常常见的坑点。2. Arduino程序开发核心逻辑与函数封装硬件连接完成后我们需要为Arduino编写控制程序Sketch。程序将分为几个功能模块电机驱动、蓝牙指令解析、超声波避障、红外循迹。采用模块化编程思想先封装基础函数再组合成高级功能。2.1 基础引脚定义与电机驱动函数首先在程序开头定义所有硬件连接的引脚并封装最基础的电机动作函数。// 引脚定义 // 电机A左侧电机控制引脚 const int ENA 5; const int IN1 6; const int IN2 7; // 电机B右侧电机控制引脚 const int ENB 10; const int IN3 8; const int IN4 9; // 超声波引脚 const int trigPin 2; const int echoPin 3; // 三路红外循迹传感器引脚 (假设OUTPUT模式检测到黑线输出HIGH) const int leftSensor 11; const int centerSensor 12; const int rightSensor 13; // 电机驱动函数 void motorInit() { // 将所有控制电机的引脚设置为输出模式 pinMode(ENA, OUTPUT); pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); // 初始状态停止电机 stopMotor(); } // 控制单个电机转动speed为PWM值(0-255)dir为方向(1正转-1反转0刹车) void setMotor(int in1, int in2, int en, int speed, int dir) { digitalWrite(in1, dir 1 ? HIGH : LOW); digitalWrite(in2, dir -1 ? HIGH : LOW); if (dir 0) { // 刹车模式两个输入引脚同为HIGH或LOW digitalWrite(in1, HIGH); digitalWrite(in2, HIGH); } analogWrite(en, speed); } // 封装小车动作前进、后退、左转、右转、停止 void carForward(int speed) { setMotor(IN1, IN2, ENA, speed, 1); setMotor(IN3, IN4, ENB, speed, 1); } void carBackward(int speed) { setMotor(IN1, IN2, ENA, speed, -1); setMotor(IN3, IN4, ENB, speed, -1); } void carTurnLeft(int speed) { // 左轮后退右轮前进实现原地左转 setMotor(IN1, IN2, ENA, speed, -1); setMotor(IN3, IN4, ENB, speed, 1); } void carTurnRight(int speed) { // 左轮前进右轮后退实现原地右转 setMotor(IN1, IN2, ENA, speed, 1); setMotor(IN3, IN4, ENB, speed, -1); } void stopMotor() { setMotor(IN1, IN2, ENA, 0, 0); setMotor(IN3, IN4, ENB, 0, 0); }关键解释analogWrite(pin, value)函数用于输出PWM信号value范围0-255值越大电机转速越快。L298N的逻辑控制IN1HIGH, IN2LOW电机正转IN1LOW, IN2HIGH反转两者同为HIGH或LOW为刹车。将小车动作封装成函数极大提高了主程序的可读性和可维护性。2.2 超声波测距与避障逻辑超声波模块通过发送和接收声波来计算距离。我们需要一个函数来获取当前距离并基于此实现自动避障逻辑。// 超声波测距函数 float getDistance() { // 发送一个10us的高电平脉冲触发测距 digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // 读取回声高电平持续时间单位微秒 long duration pulseIn(echoPin, HIGH); // 计算距离声速340m/s除以2因为是往返距离 float distance duration * 0.034 / 2; return distance; } // 自动避障函数 void autoAvoidance(int safeDistance, int moveSpeed) { float dist getDistance(); if (dist safeDistance) { // 前方安全前进 carForward(moveSpeed); } else { // 检测到障碍物停止然后右转或左转 stopMotor(); delay(200); carTurnRight(moveSpeed); delay(300); // 转弯持续时间可调整 stopMotor(); } }关键解释pulseIn(pin, HIGH)函数会等待指定引脚变为高电平并计时直到其变为低电平返回高电平持续的微秒数。这是测量超声波返回时间的关键。safeDistance是安全阈值例如20厘米。当测得的距离小于此值时触发避障动作。避障策略可以更复杂例如先后退再转向或者根据左右两侧距离选择转向方向。上述示例是一个简单的“前进-遇障-右转”策略。2.3 红外循迹逻辑循迹传感器检测地面反射光黑线吸收光线传感器输出高电平或低电平取决于模块。我们通过判断三个传感器的状态组合来决定小车的转向。// 读取循迹传感器状态 void readLineSensors(int left, int ¢er, int right) { left digitalRead(leftSensor); center digitalRead(centerSensor); right digitalRead(rightSensor); } // 自动循迹函数 void autoLineFollowing(int baseSpeed) { int leftVal, centerVal, rightVal; readLineSensors(leftVal, centerVal, rightVal); // 假设传感器检测到黑线时返回 HIGH if (centerVal HIGH) { // 中间传感器在黑线上直行 carForward(baseSpeed); } else if (leftVal HIGH) { // 只有左边检测到黑线向左微调右轮快左轮慢或反转 setMotor(IN1, IN2, ENA, baseSpeed * 0.3, 1); // 左轮慢速 setMotor(IN3, IN4, ENB, baseSpeed, 1); // 右轮全速 } else if (rightVal HIGH) { // 只有右边检测到黑线向右微调 setMotor(IN1, IN2, ENA, baseSpeed, 1); setMotor(IN3, IN4, ENB, baseSpeed * 0.3, 1); } else { // 都没检测到黑线可能出界停止或原地旋转寻找黑线 stopMotor(); // 可以加入寻线逻辑例如原地左转直到检测到黑线 carTurnLeft(baseSpeed * 0.5); delay(100); } }关键解释循迹算法的核心是“PID控制”的简化版这里使用的是简单的“开关控制”。更平滑的循迹可以使用PID算法计算电机速度差。baseSpeed * 0.3这样的系数用于差速转向使一侧轮子变慢来实现转弯比直接让一个轮子反转更平滑。传感器实际输出电平可能相反检测到黑线输出LOW需要根据模块说明书或实际测试调整if判断条件。2.4 蓝牙指令解析与模式切换我们将通过手机APP发送单个字符来控制小车。同时程序需要支持在不同模式如手动遥控模式、自动避障模式、自动循迹模式间切换。// 全局变量与模式定义 #define MODE_MANUAL 0 #define MODE_AVOIDANCE 1 #define MODE_LINE_FOLLOW 2 int currentMode MODE_MANUAL; // 初始为手动模式 int carSpeed 150; // 默认速度范围0-255 void setup() { Serial.begin(9600); // 初始化串口用于蓝牙通信 motorInit(); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(leftSensor, INPUT); pinMode(centerSensor, INPUT); pinMode(rightSensor, INPUT); stopMotor(); } void loop() { // 1. 检查并解析蓝牙指令 if (Serial.available() 0) { char command Serial.read(); handleBluetoothCommand(command); } // 2. 根据当前模式执行相应任务 switch (currentMode) { case MODE_MANUAL: // 手动模式下loop()中不执行自动操作仅响应蓝牙指令 // 动作已在 handleBluetoothCommand 中执行 break; case MODE_AVOIDANCE: autoAvoidance(20, carSpeed); // 安全距离20cm break; case MODE_LINE_FOLLOW: autoLineFollowing(carSpeed); break; } delay(50); // 短暂延时稳定循环 } // 蓝牙指令处理函数 void handleBluetoothCommand(char cmd) { switch (cmd) { // 手动控制指令 case F: carForward(carSpeed); break; case B: carBackward(carSpeed); break; case L: carTurnLeft(carSpeed); break; case R: carTurnRight(carSpeed); break; case S: stopMotor(); break; // 速度调节 case 1: carSpeed 100; break; case 2: carSpeed 150; break; case 3: carSpeed 200; break; // 模式切换指令 case A: currentMode MODE_AVOIDANCE; stopMotor(); break; case L: currentMode MODE_LINE_FOLLOW; stopMotor(); break; case M: currentMode MODE_MANUAL; stopMotor(); break; default: break; // 忽略未知指令 } }关键解释Serial.available()检查串口缓冲区是否有数据Serial.read()读取一个字节。我们定义了一套简单的协议F(前进)、B(后退)、L(左转)、R(右转)、S(停止)。模式切换用A(避障)、L(循迹)、M(手动)。在loop()中程序不断检查蓝牙指令并更新模式。根据currentMode的值决定是执行手动指令还是自动运行避障/循迹逻辑。3. 手机蓝牙控制APP制作基于App Inventor 2有了Arduino端的程序我们需要一个手机APP来发送控制指令。对于零基础开发者MIT App Inventor 2是一个绝佳的图形化开发工具。本节将引导你创建一个具备方向控制、模式切换、速度调节按钮的简易APP。3.1 App Inventor 2 项目设置与界面设计访问与登录访问 App Inventor 官网 使用谷歌账号登录。新建项目点击“Start new project”输入项目名称如ArduinoCarController。界面设计从“Palette”中拖拽组件到“Viewer”屏幕。布局使用HorizontalArrangement水平布局和VerticalArrangement垂直布局来组织按钮。按钮添加多个Button分别命名为BtnForward、BtnBackward、BtnLeft、BtnRight、BtnStop。修改它们的文本属性为“↑”、“↓”、“←”、“→”、“停”。模式选择添加一个ListPicker组件将其文本改为“选择模式”用于切换手动、避障、循迹模式。速度选择添加一个Slider组件范围0-255用于调节速度并关联一个Label显示当前速度值。蓝牙组件在“Palette”的“Connectivity”抽屉中拖拽一个BluetoothClient组件到界面。这个组件在屏幕上不可见但负责所有蓝牙通信逻辑。连接按钮添加一个Button用于连接蓝牙设备一个Label显示连接状态。设计好的界面布局应清晰分区顶部是蓝牙连接区中间是方向控制区下方是模式和速度控制区。3.2 逻辑块编程实现蓝牙连接与指令发送App Inventor的核心是“Blocks”编程通过拼接图形化代码块来实现逻辑。3.2.1 初始化与蓝牙连接当屏幕初始化(Screen1.Initialize)时可以设置一些默认值。当“连接蓝牙”按钮被点击时调用BluetoothClient1.Connect方法并通过ListPicker显示已配对的设备列表供用户选择。连接成功后更新状态标签。3.2.2 发送控制指令每个方向控制按钮被点击时都需要通过BluetoothClient1.SendText方法发送对应的字符指令。例如BtnForward.Click事件发送文本“F”BtnStop.Click事件发送文本“S”关键点为了避免持续按住按钮发送大量指令造成串口拥堵可以考虑使用“按下”和“松开”事件。但为简化本例使用点击事件点击发送动作指令再次点击停止发送S或依赖停止按钮。3.2.3 模式与速度控制ListPicker的AfterPicking事件中根据用户选择项发送对应的模式指令“M”,“A”,“L”。Slider的PositionChanged事件中将滑块位置0-100映射到速度值0-255并发送速度指令。但我们的Arduino程序只定义了1、2、3三档速度。为了更精细的控制可以修改Arduino程序使其能接收0-255的数值并在APP端发送类似“V128”的指令V代表速度128是值。以下是发送速度指令的修改思路在Arduino端// 在 handleBluetoothCommand 函数中增加对速度指令的解析 if (cmd V) { // 假设APP发送的是 V128\n // 需要读取后续的字符串并转换为整数 // 这里简化处理实际需要更完整的串口字符串解析 delay(10); // 等待数据接收 String speedStr Serial.readStringUntil(\n); int newSpeed speedStr.toInt(); if (newSpeed 0 newSpeed 255) { carSpeed newSpeed; } }3.3 APP测试与打包安装实时测试使用“AI Companion”APP在手机上扫描项目二维码可以实时测试APP与硬件的交互。连接蓝牙确保手机已与HC-05/06模块配对默认配对密码常为1234或0000。在APP中点击连接按钮从列表中选择你的蓝牙模块名称类似HC-05。功能测试逐一测试方向控制、模式切换、速度调节功能观察小车反应。打包APK在App Inventor中选择“Build” - “App (save .apk to my computer)” 可以生成安卓安装包分享到手机安装。4. 系统集成、调试与常见问题排查将硬件、Arduino程序、手机APP三者整合并稳定运行是整个项目的关键。这一阶段会遇到各种问题需要系统性地排查。4.1 上电与基础功能测试流程遵循以下步骤可以有条不紊地验证系统供电检查连接电池观察L298N、Arduino、各传感器模块的电源指示灯是否正常亮起。烧录程序用USB线连接Arduino和电脑在Arduino IDE中选择正确板卡Arduino Uno和端口上传完整的Sketch。上传前务必暂时断开蓝牙模块的TX/RX线。连接蓝牙上传成功后断电重新接好蓝牙模块的TX/RX线再上电。打开手机蓝牙设置搜索并配对模块。电机测试打开串口监视器波特率9600手动发送F、B、L、R、S等字符观察小车是否能正确响应前进、后退、转向、停止。如果电机不转检查L298N的使能跳线帽是否接上或程序中的ENA/ENB是否使用了PWM引脚。传感器测试超声波在串口监视器中打印getDistance()的返回值用手在模块前移动观察距离值变化是否合理。红外循迹打印三个传感器的digitalRead值分别放在白色和黑色表面上观察输出是否变化。APP连接测试打开手机APP连接蓝牙测试按钮功能是否与串口发送指令效果一致。4.2 常见问题与解决方案下表汇总了开发过程中可能遇到的典型问题及其排查思路。问题现象可能原因排查步骤与解决方案Arduino程序上传失败1. 端口被占用如蓝牙连接2. 板卡类型选择错误3. USB线或驱动问题1. 拔掉蓝牙模块的TX(接ArduinoRX)线再上传。2. 确认IDE中板卡选择为“Arduino Uno”。3. 尝试更换USB口或数据线安装CH340驱动。蓝牙模块无法配对或连接1. 模块未进入配对模式2. 密码错误3. 电压不足1. 确保模块指示灯快闪配对模式。HC-05可按住按键上电进入AT模式设置参数。2. 尝试常用密码1234或0000。3. 确保模块供电稳定5V或3.3V。APP发送指令小车无反应1. 蓝牙未真正连接2. 串口波特率不匹配3. 指令格式错误1. 检查APP连接状态标签确认已连接指定设备。2. 确认Arduino程序Serial.begin(9600)与蓝牙模块波特率一致默认9600。3. 用串口监视器发送相同指令对比测试。检查APP发送的是否是单个字符且无多余空格或换行除非程序做了处理。电机只震动不转动1. 供电不足2. PWM频率问题极少见3. 电机线接触不良1.最常见原因。检查电池电量是否充足L298N的12V输入电压是否足够。电机空载启动电流大可能导致电压骤降。2. 确保ENA/ENB连接的是Arduino的PWM引脚带~标识。3. 重新插拔电机接线。超声波测距值固定或不准确1. 引脚连接错误2. 测量周期太短3. 前方有吸音材料1. 确认Trig和Echo没有接反。2. 两次测距之间需有足够间隔60ms避免上次触发干扰。3. 超声波对柔软、多孔表面反射效果差。循迹小车左右摇摆或跑偏1. 传感器安装高度不一致2. 电机速度差异3. 控制算法过于敏感1. 调整传感器距地面高度使其一致通常为0.5-1.5cm。2. 即使PWM值相同两个电机实际转速也可能不同。可微调左右电机的PWM值进行补偿。3. 尝试在autoLineFollowing函数中增加转向后的短暂直行延时或引入简单的PID控制。同时开启多个自动模式冲突程序逻辑设计缺陷确保像示例代码一样使用currentMode全局变量和switch语句在loop()中一次只执行一种自动模式逻辑。手动指令可以随时中断自动模式。4.3 项目优化与扩展方向当基础功能实现后可以考虑以下优化和扩展让小车更智能、更稳定电源管理优化为Arduino和传感器单独供电如使用一块7.4V电池经降压模块给Arduino供5V与电机驱动电源分离避免电机干扰导致单片机重启。增加电源开关和电量指示LED。控制算法升级循迹实现标准的PID控制算法使小车循线更平滑、更快速。避障引入更复杂的策略如“左转-前进测距-右转-前进测距-选择更宽方向”。融合实现“巡线过程中遇到障碍物自动停车或绕行”的融合功能。功能扩展增加传感器添加光线传感器实现追光添加温湿度传感器进行环境监测并通过蓝牙将数据发回APP显示。增加执行器安装舵机和超声波云台实现扫描式避障。改进APP在APP中增加实时显示传感器数据如距离、光线值的功能实现摇杆控制代替按钮保存常用指令序列。代码结构优化使用面向对象思想将Motor、Ultrasonic、LineFollower封装成类。使用状态机State Machine更清晰地管理小车的工作模式。增加详细的调试日志输出可通过串口监视器查看系统状态。这个项目最大的价值不在于复现一辆完美的小车而在于通过解决从硬件连接到软件调试、从底层驱动到上层应用交互的全链路问题建立起对嵌入式系统开发的直观认识。每一个遇到的错误和排查过程都是宝贵的经验。建议在完成基础版本后选择一两个扩展方向深入尝试你将收获远超项目本身的工程能力。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价