循迹小车的代码程序有很多种实现方式,根据不同的传感器、控制器和通信模块等硬件组件的不同,代码实现也会有所区别。下面给出一种基于STM32芯片和红外传感器的智能循迹小车的代码程序,供参考:

#include "stm32f1xx_hal.h"

/* 定义红外传感器引脚 */
#define IR_LEFT_Pin GPIO_PIN_0
#define IR_LEFT_GPIO_Port GPIOA
#define IR_CENTER_Pin GPIO_PIN_1
#define IR_CENTER_GPIO_Port GPIOA
#define IR_RIGHT_Pin GPIO_PIN_2
#define IR_RIGHT_GPIO_Port GPIOA

/* 定义电机引脚 */
#define MOTOR_LEFT_PWM_Pin GPIO_PIN_6
#define MOTOR_LEFT_PWM_GPIO_Port GPIOB
#define MOTOR_LEFT_DIR_Pin GPIO_PIN_7
#define MOTOR_LEFT_DIR_GPIO_Port GPIOB
#define MOTOR_RIGHT_PWM_Pin GPIO_PIN_8
#define MOTOR_RIGHT_PWM_GPIO_Port GPIOB
#define MOTOR_RIGHT_DIR_Pin GPIO_PIN_9
#define MOTOR_RIGHT_DIR_GPIO_Port GPIOB

/* 定义红外传感器检测阈值 */
#define IR_THRESHOLD 1000

/* 定义电机控制参数 */
#define MOTOR_PWM_MAX 1000
#define MOTOR_PWM_MIN 300
#define MOTOR_PWM_STEP 50
#define MOTOR_PWM_DELAY 5

/* 定义循迹状态 */
typedef enum {
  TRACKING_NONE,
  TRACKING_LEFT,
  TRACKING_CENTER,
  TRACKING_RIGHT
} TrackingState;

/* 定义电机方向 */
typedef enum {
  MOTOR_DIR_FORWARD,
  MOTOR_DIR_BACKWARD
} MotorDirection;

/* 定义电机 */
typedef struct {
  TIM_HandleTypeDef *htim;
  uint32_t pwm_channel;
  GPIO_TypeDef *dir_port;
  uint16_t dir_pin;
  uint16_t pwm;
  MotorDirection dir;
} Motor;

/* 定义循迹小车 */
typedef struct {
  Motor motor_left;
  Motor motor_right;
  GPIO_TypeDef *ir_left_port;
  uint16_t ir_left_pin;
  GPIO_TypeDef *ir_center_port;
  uint16_t ir_center_pin;
  GPIO_TypeDef *ir_right_port;
  uint16_t ir_right_pin;
  TrackingState tracking_state;
} TrackCar;

/* 初始化电机 */
void motor_init(Motor *motor, TIM_HandleTypeDef *htim, uint32_t pwm_channel, GPIO_TypeDef *dir_port, uint16_t dir_pin) {
  motor->htim = htim;
  motor->pwm_channel = pwm_channel;
  motor->dir_port = dir_port;
  motor->dir_pin = dir_pin;
  motor->pwm = 0;
  motor->dir = MOTOR_DIR_FORWARD;
}

/* 设置电机方向 */
void motor_set_direction(Motor *motor, MotorDirection dir) {
  if (motor->dir != dir) {
    motor->dir = dir;
    if (dir == MOTOR_DIR_FORWARD) {
      HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_RESET);
    } else {
      HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_SET);
    }
  }
}

/* 设置电机PWM */
void motor_set_pwm(Motor *motor, uint16_t pwm) {
  if (pwm > MOTOR_PWM_MAX) {
    pwm = MOTOR_PWM_MAX;
  } else if (pwm < MOTOR_PWM_MIN) {
    pwm = MOTOR_PWM_MIN;
  }
  if (motor->pwm != pwm) {
    motor->pwm = pwm;
    __HAL_TIM_SET_COMPARE(motor->htim, motor->pwm_channel, pwm);
  }
}

/* 初始化循迹小车 */
void track_car_init(TrackCar *car) {
  /* 初始化电机 */
  motor_init(&(car->motor_left), &htim3, TIM_CHANNEL_1, MOTOR_LEFT_DIR_GPIO_Port, MOTOR_LEFT_DIR_Pin);
  motor_init(&(car->motor_right), &htim3, TIM_CHANNEL_2, MOTOR_RIGHT_DIR_GPIO_Port, MOTOR_RIGHT_DIR_Pin);
  /* 初始化红外传感器 */
  car->ir_left_port = IR_LEFT_GPIO_Port;
  car->ir_left_pin = IR_LEFT_Pin;
  car->ir_center_port = IR_CENTER_GPIO_Port;
  car->ir_center_pin = IR_CENTER_Pin;
  car->ir_right_port = IR_RIGHT_GPIO_Port;
  car->ir_right_pin = IR_RIGHT_Pin;
  /* 初始化循迹状态 */
  car->tracking_state = TRACKING_NONE;
}

/* 获取红外传感器检测值 */
uint16_t ir_read(GPIO_TypeDef *port, uint16_t pin) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = pin;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  HAL_GPIO_Init(port, &GPIO_InitStruct);
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 1000);
  uint16_t value = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  return value;
}

/* 更新循迹状态 */
void track_car_update(TrackCar *car) {
  uint16_t ir_left = ir_read(car->ir_left_port, car->ir_left_pin);
  uint16_t ir_center = ir_read(car->ir_center_port, car->ir_center_pin);
  uint16_t ir_right = ir_read(car->ir_right_port, car->ir_right_pin);
  if (ir_left > IR_THRESHOLD && ir_center > IR_THRESHOLD && ir_right > IR_THRESHOLD) {
    /* 没有检测到黑线 */
    car->tracking_state = TRACKING_NONE;
  } else if (ir_left <= IR_THRESHOLD && ir_center > IR_THRESHOLD && ir_right > IR_THRESHOLD) {
    /* 检测到左边的黑线 */
    car->tracking_state = TRACKING_LEFT;
  } else if (ir_left > IR_THRESHOLD && ir_center <= IR_THRESHOLD && ir_right > IR_THRESHOLD) {
    /* 检测到中间的黑线 */
    car->tracking_state = TRACKING_CENTER;
  } else if (ir_left > IR_THRESHOLD && ir_center > IR_THRESHOLD && ir_right <= IR_THRESHOLD) {
    /* 检测到右边的黑线 */
    car->tracking_state = TRACKING_RIGHT;
  }
}

/* 控制循迹小车 */
void track_car_control(TrackCar *car) {
  switch (car->tracking_state) {
    case TRACKING_NONE:
      /* 没有检测到黑线,停止电机 */
      motor_set_pwm(&(car->motor_left), 0);
      motor_set_pwm(&(car->motor_right), 0);
      break;
    case TRACKING_LEFT:
      /* 检测到左边的黑线,向右转 */
      motor_set_direction(&(car->motor_left), MOTOR_DIR_FORWARD);
      motor_set_direction(&(car->motor_right), MOTOR_DIR_BACKWARD);
      motor_set_pwm(&(car->motor_left), MOTOR_PWM_MAX);
      motor_set_pwm(&(car->motor_right), MOTOR_PWM_MIN);
      break;
    case TRACKING_CENTER:
      /* 检测到中间的黑线,直走 */
      motor_set_direction(&(car->motor_left), MOTOR_DIR_FORWARD);
      motor_set_direction(&(car->motor_right), MOTOR_DIR_FORWARD);
      motor_set_pwm(&(car->motor_left), MOTOR_PWM_MAX);
      motor_set_pwm(&(car->motor_right), MOTOR_PWM_MAX);
      break;
    case TRACKING_RIGHT:
      /* 检测到右边的黑线,向左转 */
      motor_set_direction(&(car->motor_left), MOTOR_DIR_BACKWARD);
      motor_set_direction(&(car->motor_right), MOTOR_DIR_FORWARD);
      motor_set_pwm(&(car->motor_left), MOTOR_PWM_MIN);
      motor_set_pwm(&(car->motor_right), MOTOR_PWM_MAX);
      break;
  }
}

int main(void) {
  /* 初始化循迹小车 */
  TrackCar car;
  track_car_init(&car);
  /* 循环处理 */
  while (1) {
    /* 更新循迹状态 */
    track_car_update(&car);
    /* 控制循迹小车 */
    track_car_control(&car);
    /* 延时一段时间 */
    HAL_Delay(MOTOR_PWM_DELAY);
  }
}

以上是一份简单的循迹小车代码程序,具体实现还需要根据具体的硬件组件和需求进行修改和优化


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

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