// 定义电机引脚
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);   // 右电机以特定速度前进
  }
}
Arduino循迹避障小车:结合地面和接近传感器实现复杂路线

原文地址: https://www.cveoy.top/t/topic/jpTe 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录