《Arduino 手册(思路与案例)》栏目介绍:
在电子制作与智能控制的应用领域,本栏目涵盖了丰富的内容,包括但不限于以下主题:Arduino BLDC、Arduino CNC、Arduino E-Ink、Arduino ESP32 SPP、Arduino FreeRTOS、Arduino FOC、Arduino GRBL、Arduino HTTP、Arduino HUB75、Arduino IoT Cloud、Arduino JSON、Arduino LCD、Arduino OLED、Arduino LVGL、Arduino PID、Arduino TFT,以及Arduino智能家居、智慧交通、月球基地、智慧校园和智慧农业等多个方面与领域。不仅探讨了这些技术的基础知识和应用领域,还提供了众多具体的参考案例,帮助读者更好地理解和运用Arduino平台进行创新项目。目前,本栏目已有近4000篇相关博客,旨在为广大电子爱好者和开发者提供全面的学习资源与实践指导。通过这些丰富的案例和思路,读者可以获取灵感,推动自己的创作与开发进程。
https://blog.csdn.net/weixin_41659040/category_12422453.html
Arduino BLDC 之 红外巡线 + 动态避障复合系统
一、主要特点
红外巡线功能:
系统使用红外传感器检测地面上的线路,通过简单的算法,机器人能够沿着预设路径稳定行驶,实现自动巡线。
动态避障能力:
集成多种传感器(如超声波传感器、激光雷达等),实时检测周围环境,识别障碍物并自动调整运动轨迹,确保机器人在动态环境中的安全性。
复合控制策略:
结合红外巡线和动态避障两种功能,系统能够在巡线的同时有效避开障碍物,提升导航的智能性和灵活性。
实时反馈与调整:
系统能够实时接收传感器反馈,快速调整运动策略,确保机器人在复杂环境中保持稳定和高效。
易于编程与扩展:
基于 Arduino 平台的设计使得系统易于编程和扩展,用户可以根据需求添加更多传感器或功能模块,增强系统的功能。
二、应用场景
智能物流:
在仓库和物流中心,红外巡线 + 动态避障系统可以用于自动搬运小车,优化物品运输和分拣流程,提高工作效率。
家庭服务机器人:
在智能家居中,该系统可用于清扫机器人,实现自主巡回清扫,同时避开家具等障碍物,提升用户体验。
教育与科研:
在机器人教育和科研项目中,红外巡线 + 动态避障系统是学习控制理论和机器人技术的理想平台,适用于实验和项目开发。
工业自动化:
在生产线中,机器人可通过此系统实现自动搬运、装配等任务,适应复杂的工作环境。
无人驾驶小车:
在无人驾驶技术中,该系统可用于开发小型自动驾驶车辆,实现智能巡航与避障。
三、注意事项
传感器选择与配置:
选择高精度的红外传感器和避障传感器,确保其在不同光照和环境条件下的稳定性和可靠性。
算法优化:
针对巡线和避障的算法需要进行优化,以确保系统在复杂环境中能够快速反应,避免路径偏差或碰撞。
环境建模:
在设计时考虑环境的复杂性,确保系统能够准确识别巡线和障碍物,避免误判。
电源管理:
合理管理电源,确保系统在长时间运行中的稳定性和续航能力,特别是在移动设备中。
安全性设计:
在控制系统中设置合理的安全限制,确保机器人在运行过程中的安全性,避免对人员和设备造成伤害。
1、基础红外巡线
#include <Servo.h>
Servo motorLeft; // 左侧电机
Servo motorRight; // 右侧电机
const int leftSensor = A0; // 左侧红外传感器
const int rightSensor = A1; // 右侧红外传感器
void setup() {
Serial.begin(9600);
motorLeft.attach(9);
motorRight.attach(10);
}
void loop() {
int leftValue = analogRead(leftSensor);
int rightValue = analogRead(rightSensor);
// 判断传感器的状态
if (leftValue < 500 && rightValue < 500) {
// 在线上,前进
motorLeft.write(180);
motorRight.write(180);
} else if (leftValue < 500) {
// 左侧在线,右转
motorLeft.write(180);
motorRight.write(90);
} else if (rightValue < 500) {
// 右侧在线,左转
motorLeft.write(90);
motorRight.write(180);
} else {
// 停止
motorLeft.write(90);
motorRight.write(90);
}
delay(100); // 每100毫秒更新一次
}
2、动态避障控制
#include <Servo.h>
Servo motorLeft;
Servo motorRight;
const int frontSensor = A0; // 前方超声波传感器
const int leftSensor = A1; // 左侧红外传感器
const int rightSensor = A2; // 右侧红外传感器
void setup() {
Serial.begin(9600);
motorLeft.attach(9);
motorRight.attach(10);
}
void loop() {
int frontValue = analogRead(frontSensor);
int leftValue = analogRead(leftSensor);
int rightValue = analogRead(rightSensor);
if (frontValue < 500) {
// 前方有障碍物,后退并转向
motorLeft.write(0);
motorRight.write(0);
delay(500);
motorLeft.write(0);
motorRight.write(180); // 向右转
delay(500);
} else {
// 没有障碍物,进行巡线控制
if (leftValue < 500 && rightValue < 500) {
motorLeft.write(180);
motorRight.write(180);
} else if (leftValue < 500) {
motorLeft.write(180);
motorRight.write(90);
} else if (rightValue < 500) {
motorLeft.write(90);
motorRight.write(180);
} else {
motorLeft.write(90);
motorRight.write(90);
}
}
delay(100);
}
3、红外巡线与动态避障复合控制
#include <Servo.h>
Servo motorLeft;
Servo motorRight;
const int frontSensor = A0; // 前方超声波传感器
const int leftSensor = A1; // 左侧红外传感器
const int rightSensor = A2; // 右侧红外传感器
void setup() {
Serial.begin(9600);
motorLeft.attach(9);
motorRight.attach(10);
}
void loop() {
int frontValue = analogRead(frontSensor);
int leftValue = analogRead(leftSensor);
int rightValue = analogRead(rightSensor);
if (frontValue < 500) {
// 前方有障碍物,后退并转向
motorLeft.write(0);
motorRight.write(0);
delay(500);
motorLeft.write(0);
motorRight.write(180); // 向右转
delay(500);
} else {
// 没有障碍物,进行巡线控制
if (leftValue < 500 && rightValue < 500) {
motorLeft.write(180);
motorRight.write(180);
} else if (leftValue < 500) {
motorLeft.write(180);
motorRight.write(90);
} else if (rightValue < 500) {
motorLeft.write(90);
motorRight.write(180);
} else {
motorLeft.write(90);
motorRight.write(90);
}
}
delay(100);
}
要点解读
红外巡线功能:
第一个示例实现了基础的红外巡线功能。通过读取左侧和右侧的红外传感器值,控制电机的转动,实现沿着黑线的巡行。传感器值小于500表示检测到黑线。
动态避障功能:
第二个示例实现了动态避障的功能。当前方传感器检测到障碍物时,机器人会后退并转向以避免碰撞。然后继续进行巡线控制。
复合控制系统:
第三个示例将红外巡线与动态避障功能结合在一起。该系统能够在巡线的同时,实时避开前方的障碍物,增强了机器人的智能性和灵活性。
传感器输入:
所有示例均使用红外传感器和超声波传感器(假设为模拟输入)来检测环境。红外传感器用于巡线,超声波传感器用于避障。
电机控制:
使用 Servo 库控制 BLDC 电机。根据传感器的反馈,调整电机的角度以实现前进、后退和转向。
延迟控制:
通过 delay() 函数控制动作之间的时间间隔,确保每个动作都能充分执行,避免过快引起的控制失效。
可扩展性:
这些示例提供了基础框架,可以根据需求扩展功能。例如,可以引入更多的传感器(如激光雷达)进行更精确的环境感知,或实现更复杂的控制算法(如 PID 控制)来提高系统的稳定性和响应速度。
4、基础红外巡线+超声波避障(单任务处理)
功能:通过红外传感器巡线,检测到障碍物时暂停巡线并避障。
#include <NewPing.h> // 超声波库
#include <PID_v1.h> // 用于巡线平滑控制
// 硬件连接
#define IR_LEFT A0 // 左侧红外传感器
#define IR_RIGHT A1 // 右侧红外传感器
#define TRIG_PIN 12 // 超声波Trig
#define ECHO_PIN 11 // 超声波Echo
#define MOTOR_PWM1 5 // BLDC驱动PWM1
#define MOTOR_PWM2 6 // BLDC驱动PWM2
#define MAX_DISTANCE 200 // 超声波最大检测距离(cm)
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);
double Setpoint = 0.0; // 巡线目标位置(传感器中间值)
double Input, Output;
double Kp = 2.0, Ki = 0.5, Kd = 1.0;
PID linePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
void setup() {
Serial.begin(115200);
pinMode(MOTOR_PWM1, OUTPUT);
pinMode(MOTOR_PWM2, OUTPUT);
linePID.SetMode(AUTOMATIC);
linePID.SetOutputLimits(-255, 255);
// 红外传感器校准(根据实际读数调整)
Setpoint = (analogRead(IR_LEFT) + analogRead(IR_RIGHT)) / 2.0;
}
void loop() {
// 1. 超声波避障检测
int distance = sonar.ping_cm();
if (distance > 0 && distance < 30) { // 检测到障碍物
avoidObstacle();
return; // 跳过巡线逻辑
}
// 2. 红外巡线控制
int leftVal = analogRead(IR_LEFT);
int rightVal = analogRead(IR_RIGHT);
Input = leftVal - rightVal; // 差值表示偏离程度
linePID.Compute();
// 3. 电机控制(差速转向)
if (Output > 0) {
// 向右转(左侧电机加速)
analogWrite(MOTOR_PWM1, 150 + Output);
analogWrite(MOTOR_PWM2, 150 - Output);
} else {
// 向左转(右侧电机加速)
analogWrite(MOTOR_PWM1, 150 + Output);
analogWrite(MOTOR_PWM2, 150 - Output);
}
}
void avoidObstacle() {
// 简单避障逻辑:后退->右转->前进
Serial.println("Avoiding obstacle!");
// 后退
analogWrite(MOTOR_PWM1, -180);
analogWrite(MOTOR_PWM2, -180);
delay(300);
// 右转
analogWrite(MOTOR_PWM1, 200);
analogWrite(MOTOR_PWM2, -200);
delay(200);
// 恢复巡线
analogWrite(MOTOR_PWM1, 0);
analogWrite(MOTOR_PWM2, 0);
}
要点解读:
单任务处理:避障为最高优先级,检测到障碍物时暂停巡线。
红外传感器校准:需根据实际地面反射率调整Setpoint。
差速转向:通过左右电机速度差实现转向,PID输出直接控制差速幅度。
超声波滤波:可对距离值做中值滤波,避免误判。
5、多传感器融合避障(优先级动态切换)
#include <NewPing.h>
#include <QTRSensors.h> // 多路红外传感器库
// 硬件定义
#define NUM_SENSORS 4 // 4路红外传感器
#define IR_PINS {A0, A1, A2, A3} // 传感器引脚数组
#define TRIG_PIN 12
#define ECHO_PIN 11
#define MOTOR_PWM1 5
#define MOTOR_PWM2 6
// 多路红外传感器
QTRSensors qtr;
unsigned int sensorValues[NUM_SENSORS];
NewPing sonar(TRIG_PIN, ECHO_PIN, 200);
// 状态机定义
enum State { LINE_FOLLOW, OBSTACLE_AVOID, STOP };
State currentState = LINE_FOLLOW;
unsigned long avoidStartTime = 0;
void setup() {
Serial.begin(115200);
qtr.setTypeAnalog();
qtr.setSensorPins((const uint8_t[])IR_PINS, NUM_SENSORS);
pinMode(MOTOR_PWM1, OUTPUT);
pinMode(MOTOR_PWM2, OUTPUT);
}
void loop() {
static int lastPosition = 0;
// 1. 状态机切换
switch (currentState) {
case LINE_FOLLOW:
// 红外巡线
lastPosition = qtr.readLineBlack(sensorValues);
int error = lastPosition - 1500; // 1500为中间值(4传感器)
// 简单比例控制
int speedLeft = 120 + error * 0.1;
int speedRight = 120 - error * 0.1;
setMotorSpeed(speedLeft, speedRight);
// 超声波检测障碍物
int distance = sonar.ping_cm();
if (distance > 0 && distance < 25) {
currentState = OBSTACLE_AVOID;
avoidStartTime = millis();
}
break;
case OBSTACLE_AVOID:
// 避障动作(持续1秒)
setMotorSpeed(-100, -100); // 后退
delay(300);
setMotorSpeed(150, -150); // 右转
delay(200);
// 返回巡线状态
if (millis() - avoidStartTime > 1000) {
currentState = LINE_FOLLOW;
}
break;
case STOP:
setMotorSpeed(0, 0);
break;
}
}
void setMotorSpeed(int left, int right) {
// BLDC驱动代码(需根据实际驱动模块调整)
if (left >= 0) {
analogWrite(MOTOR_PWM1, left);
} else {
// 反向控制逻辑(需硬件支持)
}
// 同理处理right电机
}
要点解读:
状态机设计:通过enum明确区分巡线和避障状态。
多路红外传感器:使用QTRSensors库提高巡线精度,支持多传感器融合。
动态避障:避障动作完成后自动返回巡线状态。
时间控制:通过millis()实现避障动作的时序控制。
6、复杂环境自适应(巡线+避障+记忆路径)
功能:在巡线过程中动态避障,并记录障碍物位置实现路径记忆。
#include <NewPing.h>
#include <QTRSensors.h>
#include <EEPROM.h> // 用于存储障碍物位置
// 硬件定义
#define NUM_SENSORS 6
#define IR_PINS {A0, A1, A2, A3, A4, A5}
#define TRIG_PIN 12
#define ECHO_PIN 11
#define MOTOR_PWM1 5
#define MOTOR_PWM2 6
#define BUZZER 7
// 全局变量
QTRSensors qtr;
unsigned int sensorValues[NUM_SENSORS];
NewPing sonar(TRIG_PIN, ECHO_PIN, 200);
bool obstacleDetected = false;
int obstacleMemory[10][2]; // 存储障碍物坐标(简化版)
int obstacleCount = 0;
void setup() {
Serial.begin(115200);
qtr.setTypeAnalog();
qtr.setSensorPins((const uint8_t[])IR_PINS, NUM_SENSORS);
pinMode(MOTOR_PWM1, OUTPUT);
pinMode(MOTOR_PWM2, OUTPUT);
pinMode(BUZZER, OUTPUT);
// 从EEPROM加载障碍物记忆(示例)
// EEPROM.get(0, obstacleMemory);
}
void loop() {
// 1. 巡线控制(PID简化版)
int position = qtr.readLineBlack(sensorValues);
int error = position - 2500; // 中间值(6传感器)
int baseSpeed = 100;
int leftSpeed = baseSpeed + error * 0.05;
int rightSpeed = baseSpeed - error * 0.05;
// 2. 超声波避障检测
int distance = sonar.ping_cm();
if (distance > 0 && distance < 30 && !obstacleDetected) {
obstacleDetected = true;
recordObstacle(position, distance); // 记录障碍物位置
avoidObstacle();
} else if (distance >= 40) {
obstacleDetected = false;
}
// 3. 电机控制
if (obstacleDetected) {
setMotorSpeed(0, 0); // 避障时暂停巡线
} else {
setMotorSpeed(leftSpeed, rightSpeed);
}
}
void recordObstacle(int linePos, int dist) {
if (obstacleCount < 10) {
obstacleMemory[obstacleCount][0] = linePos; // 巡线位置
obstacleMemory[obstacleCount][1] = dist; // 障碍物距离
obstacleCount++;
// 蜂鸣器提示
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
}
}
void avoidObstacle() {
// 高级避障逻辑(示例:根据记忆绕行)
setMotorSpeed(-80, -80); // 后退
delay(200);
// 尝试从右侧绕行
setMotorSpeed(100, -100);
delay(300);
// 前进一段距离
setMotorSpeed(120, 120);
delay(400);
}
void setMotorSpeed(int left, int right) {
// 实际BLDC驱动代码(需适配驱动模块)
analogWrite(MOTOR_PWM1, constrain(left, 0, 255));
analogWrite(MOTOR_PWM2, constrain(right, 0, 255));
}
要点解读:
路径记忆:使用数组或EEPROM存储障碍物位置,为后续优化路径提供基础。
多传感器冗余:6路红外传感器提高复杂线路识别能力。
避障策略升级:根据障碍物位置动态选择绕行方向(如优先右侧)。
用户反馈:通过蜂鸣器提示障碍物记录事件。
注意,以上案例只是为了拓展思路,仅供参考。它们可能有错误、不适用或者无法编译。您的硬件平台、使用场景和Arduino版本可能影响使用方法的选择。实际编程时,您要根据自己的硬件配置、使用场景和具体需求进行调整,并多次实际测试。您还要正确连接硬件,了解所用传感器和设备的规范和特性。涉及硬件操作的代码,您要在使用前确认引脚和电平等参数的正确性和安全性。