Arduino循迹避障小车:结合地面和接近传感器实现复杂路线
// 定义电机引脚
int PWM_left = 6; // 左电机PWM引脚
int left_dir = 7; // 左电机方向引脚
int PWM_right = 5; // 右电机PWM引脚
int right_dir = 2; // 右电机方向引脚
// 定义电机速度变量
int base_motor_speed = 10; // 电机基础速度
// 定义循迹相关变量
int count = 1; // 转弯计数器
int threshold = 940; // 地面传感器黑色阈值
// 定义沿墙相关变量
int red_led = 11; // 红色LED引脚
volatile int proximity[8]; // 存储接近传感器读数的数组
// 定义传感器引脚
unsigned char analogPin[20] = {A8, A9, A10, A11, A0, A1, A2, A3, A4, A5, A6, A7}; // 模拟引脚数组,包含地面和接近传感器
// 定义电机速度变量
int distance = 0; // 距离变量,单位毫米
int iCurLeftMotorForwardSpeed = 0, iCurRightMotorForwardSpeed = 0, iCurLeftMotorBackwardSpeed, iCurRightMotorBackwardSpeed = 0; // 当前电机速度
void setup() {
// 初始化串口
pinMode(red_led, OUTPUT); // 设置红色LED引脚为输出模式
Serial.begin(57600); // 初始化串口通信,波特率为57600
// 初始化电机
initMotor(); // 初始化电机引脚和模式
// 初始化接近传感器
initIRLED(); // 初始化接近传感器LED
}
void loop() {
// 循迹部分
if (readGroundSensorsIsBlack(1) && readGroundSensorsIsBlack(2)) { // 如果两个地面传感器都检测到黑线
MotorStop(); // 停止电机
delay(5000); // 等待5秒
if (count % 2 == 0) { // 根据转弯计数器决定左转或右转
rightTurn(12); // 右转
} else {
leftTurn(12); // 左转
}
count++; // 转弯计数器加1
delay(10); // 等待10毫秒
} else {
forWard(12); // 直行
delay(10); // 等待10毫秒
}
// 沿墙部分
if (readProximityDistance(0) < 15 && readProximityDistance(1) < 15 && readProximityDistance(2) < 15 && readProximityDistance(3) < 15) { // 如果四个接近传感器都检测到墙体
MotorStop(); // 停止电机
} else {
followWall(); // 沿墙运动
}
}
// 初始化电机引脚和模式
void initMotor() {
pinMode(PWM_right, OUTPUT); // 设置右电机PWM引脚为输出模式
pinMode(PWM_left, OUTPUT); // 设置左电机PWM引脚为输出模式
pinMode(right_dir, OUTPUT); // 设置右电机方向引脚为输出模式
pinMode(left_dir, OUTPUT); // 设置左电机方向引脚为输出模式
DDRJ |= 0x0F; // 设置PJ0-PJ3为输出模式
DDRK &= ~0x0F; // 设置PK0-PK3为输入模式
}
// 初始化接近传感器LED
void initIRLED() {
DDRA |= B11111111; // 设置PA0-PA7为输出模式
PORTA &= B00000000; // 关闭所有接近传感器LED
}
// 打开地面传感器LED
void groundLEDon(unsigned char lineIndex) {
PORTJ &= ~(1 << lineIndex); // 打开指定编号的地面传感器LED
}
// 关闭地面传感器LED
void groundLEDoff(unsigned char lineIndex) {
PORTJ |= 1 << lineIndex; // 关闭指定编号的地面传感器LED
}
// 读取地面传感器值
int readGroundSensor(unsigned char lineIndex) {
return analogRead(analogPin[lineIndex]); // 读取指定编号的地面传感器模拟值
}
// 判断地面传感器是否检测到黑线
bool readGroundSensorsIsBlack(unsigned char lineIndex) {
groundLEDon(lineIndex); // 打开指定编号的地面传感器LED
delay(1); // 等待1毫秒
int val = readGroundSensor(lineIndex); // 读取指定编号的地面传感器模拟值
groundLEDoff(lineIndex); // 关闭指定编号的地面传感器LED
Serial.print('Ground Sensor '); // 打印调试信息
Serial.print(lineIndex); // 打印调试信息
Serial.print(' : '); // 打印调试信息
Serial.println(val); // 打印调试信息
if (val > threshold) { // 如果模拟值大于阈值
return true; // 返回true,表示检测到黑线
} else {
return false; // 返回false,表示未检测到黑线
}
}
// 左转
void leftTurn(float duty) {
leftMotorForward(0); // 左电机停止
rightMotorForward(duty); // 右电机前进
}
// 右转
void rightTurn(float duty) {
leftMotorForward(duty); // 左电机前进
rightMotorForward(0); // 右电机停止
}
// 直行
void forWard(float duty) {
leftMotorForward(duty); // 左电机前进
rightMotorForward(duty); // 右电机前进
}
// 停止电机
void MotorStop() {
iCurLeftMotorForwardSpeed = 0; // 左电机前进速度设为0
iCurRightMotorForwardSpeed = 0; // 右电机前进速度设为0
iCurLeftMotorBackwardSpeed = 0; // 左电机后退速度设为0
iCurRightMotorBackwardSpeed = 0; // 右电机后退速度设为0
digitalWrite(right_dir, HIGH); // 设置右电机方向为高电平
digitalWrite(PWM_right, HIGH); // 设置右电机PWM为高电平
digitalWrite(left_dir, HIGH); // 设置左电机方向为高电平
digitalWrite(PWM_left, HIGH); // 设置左电机PWM为高电平
}
// 左电机前进
void leftMotorForward(float duty) {
int dutyInt = duty; // 将duty转换为整数类型
if (iCurLeftMotorForwardSpeed != dutyInt) { // 如果当前速度与目标速度不同
int dutyVal = map(dutyInt, 0, 100, 0, 255); // 将速度映射到PWM值
analogWrite(PWM_left, dutyVal); // 设置左电机PWM值
analogWrite(left_dir, 0); // 设置左电机方向为正向
iCurLeftMotorForwardSpeed = dutyInt; // 更新当前速度
}
}
// 右电机前进
void rightMotorForward(float duty) {
int dutyInt = duty; // 将duty转换为整数类型
if (iCurRightMotorForwardSpeed != dutyInt) { // 如果当前速度与目标速度不同
int dutyVal = map(dutyInt, 0, 100, 0, 255); // 将速度映射到PWM值
analogWrite(PWM_right, dutyVal); // 设置右电机PWM值
analogWrite(right_dir, 0); // 设置右电机方向为正向
iCurRightMotorForwardSpeed = dutyInt; // 更新当前速度
}
}
// 左电机后退
void leftMotorBackward(float duty) {
int dutyInt = duty; // 将duty转换为整数类型
if (iCurLeftMotorBackwardSpeed != dutyInt) { // 如果当前速度与目标速度不同
int dutyVal = map(dutyInt, 0, 100, 0, 200); // 将速度映射到PWM值
analogWrite(PWM_left, 0); // 设置左电机PWM值为0
analogWrite(left_dir, dutyVal); // 设置左电机方向为反向
iCurLeftMotorBackwardSpeed = dutyInt; // 更新当前速度
}
}
// 右电机后退
void rightMotorBackward(float duty) {
int dutyInt = duty; // 将duty转换为整数类型
if (iCurRightMotorBackwardSpeed != dutyInt) { // 如果当前速度与目标速度不同
int dutyVal = map(dutyInt, 0, 100, 0, 200); // 将速度映射到PWM值
analogWrite(PWM_right, 0); // 设置右电机PWM值为0
analogWrite(right_dir, dutyVal); // 设置右电机方向为反向
iCurRightMotorBackwardSpeed = dutyInt; // 更新当前速度
}
}
// 读取接近传感器距离值
int readProximityDistance(unsigned char proxIndex) {
int distance; // 距离变量
proxLEDon(proxIndex); // 打开指定编号的接近传感器LED
delay(1); // 等待1毫秒
proximity[proxIndex] = analogRead(analogPin[proxIndex]); // 读取指定编号的接近传感器模拟值
distance = 3.425 * pow(2.7182, 0.0026 * proximity[proxIndex]); // 将模拟值转换为距离值
proxLEDoff(proxIndex); // 关闭指定编号的接近传感器LED
return distance; // 返回距离值
}
// 打开接近传感器LED
void proxLEDon(unsigned char proxIndex) {
PORTA |= 1 << proxIndex; // 打开指定编号的接近传感器LED
}
// 关闭接近传感器LED
void proxLEDoff(unsigned char proxIndex) {
PORTA &= ~(1 << proxIndex); // 关闭指定编号的接近传感器LED
}
// 沿墙运动
void followWall() {
int distance1 = readProximityDistance(7); // 读取右侧接近传感器距离
int distance2 = readProximityDistance(5); // 读取左侧接近传感器距离
Serial.print('distance1:'); // 打印右侧距离
Serial.println(distance1); // 打印右侧距离
Serial.print('distance2:'); // 打印左侧距离
Serial.println(distance2); // 打印左侧距离
if ((distance1 >= 15 && distance1 < 20) && (distance2 >= 15 && distance2 < 20)) { // 如果距离在特定范围内
leftMotorForward(base_motor_speed + 2); // 左电机以特定速度前进
rightMotorForward(base_motor_speed); // 右电机以特定速度前进
} else if (distance1 >= 20 && distance2 < 20) { // 如果右侧距离较远,左侧距离较近
leftMotorForward(base_motor_speed); // 左电机以特定速度前进
rightMotorForward(base_motor_speed + 1); // 右电机以特定速度前进
} else if (distance1 >= 20 && distance2 >= 20) { // 如果两侧距离都较远
leftMotorForward(base_motor_speed); // 左电机以特定速度前进
rightMotorForward(base_motor_speed + 3); // 右电机以特定速度前进
} else if (distance1 < 15 && distance2 > 15) { // 如果右侧距离较近,左侧距离较远
leftMotorForward(base_motor_speed + 3); // 左电机以特定速度前进
rightMotorForward(base_motor_speed); // 右电机以特定速度前进
} else if (distance1 < 15 && distance2 < 15) { // 如果两侧距离都较近
leftMotorForward(base_motor_speed + 5); // 左电机以特定速度前进
rightMotorForward(base_motor_speed); // 右电机以特定速度前进
}
}
原文地址: https://www.cveoy.top/t/topic/jpTe 著作权归作者所有。请勿转载和采集!