yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
Roboduino V2📖
0.Instruction manual
  • Instruction manual
1.Get started quickly
  • 01.Assembly of the Car
  • 02.Remote Control Car
  • 03.Common Problem Analysis
  • 04. Lithium Battery Pack and Charger Usage Guidelines
  • 05. Important Notes (Read Before Starting)
2.Environment Construction
  • 01.Serial port driver installation
  • 02.Arduino IDE Installation
  • 03.Arduino IDE usage
  • 04.Using third-party libraries
  • 05.Program compilation and upload
3.Basic car course
  • 01.RGB Control
  • 02.Serial Print
  • 03.KEY Read
  • 04.Buzzer control
  • 05.Logo Breath
  • 06.Servos Control
  • 07.Motor Control
  • 08.Ultrasonic Ranging
  • 09.Track Print
  • 10.Infrared Remote Print
  • 11.WIFI Camera
4.Advanced car course
  • 01.RGB Breath
  • 02.Play Music
  • 03.KEY Control RGB
  • 04.KEY Control Buzzer
  • 05.Serial Parse Data
  • 06.Parse Data Control Motor
  • 07.Parse Data Control RGB
  • 08.Parse Data Control Buzzer
  • 09.Parse Data Control Servo
5.Car motion control
  • 00.Mecanum wheel motion principle
  • 01.Car Vertical Movement
  • 02.Car Diagonal Movement
  • 03.Car Sideways Movement
  • 04.Car Rotational Movement
  • 05.Car Patrol
6.Comprehensive gameplay of car
  • 01.Car tracking
  • 02.Car Obstacle Avoid
  • 03.Car Follow Hand
  • 04.Car tracking Avoid
  • 05.Car Infrared Remote
  • 06.WiFi Control Car
  • 07.IR WiFi Control Car
7.AI vision course
  • 1. Cat(dog) detection
  • 2. Color recognition
  • 3. QR code instructions
  • 4. Person Recognition
  • 5. Face Detection
  • 6. Color Follows
  • 7. Face following
8.Expand peripherals
  • 01.Digital Tube Display
  • 02.Color Recognition
Download
  • Code
  • Library
  • Hardware manual
  • Software
  • 3D Model
  • Instruction Manual
Download ZIP

Welcome to Roboduino V2 repository

04.Car tracking Avoid

Car tracking Avoid

Car tracking AvoidDevice connectionHardware connectionSoftware connectionImplementation ideasCode analysisExperimental results

Use the button K1 to control the on and off of the car tracking + ultrasonic obstacle avoidance function.

xxxxxxxxxx
Since the previous tutorial has explained the basic knowledge of all car modules, the car control tutorial will not be repeated, and the main focus is on the implementation ideas of the car functions!

Device connection

Hardware connection

Use the Type-B data cable to connect Arduino Uno and the computer.

Software connection

Open the "Arduino IDE" software and select the model and serial port number corresponding to the development board.

Implementation ideas

Use the three-way patrol module to obtain the position of the car relative to the black route, and control the movement of the car based on this position.

Button K1: turn on or off the car tracking function;

Three-way patrol module: get the position of the car head relative to the black line;

Ultrasonic module: get the distance of the object in front of the car;

Car control:

The three-way patrol module is located on the left side of the black line, and the car turns left;

The three-way patrol module is located in the middle of the black line, and the car goes straight;

The three-way patrol module is located on the right side of the black line, and the car turns right;

The object in front of the car is less than the set distance (15cm): the car stops.

xxxxxxxxxx
The actual code also analyzes the situation where the three-way patrol module detects all black lines, and the code controls the forward movement in this situation.

Code analysis

Here is only a brief introduction to the code content. For detailed code, it is recommended to refer to the corresponding code file, which is provided in the download area!

  • Include Wire、Adafruit_PWMServoDriver library

x
#include <Wire.h>                     // 包含Wire(I2C)通讯库 Include Wire library
#include <Adafruit_PWMServoDriver.h>  // 包含Adafruit PWMServoDriver库 Include Adafruit PWMServoDriver library
  • Define motors, buttons, three-way patrol, ultrasonic module control pins, I2C address, motor frequency, initial speed, etc.

​x
// 定义电机控制引脚 Define motor control pins
#define Motor_L1_F_PIN 11  // 控制小车左前方电机前进 Control the motor on the left front of the car
#define Motor_L1_B_PIN 10  // 控制小车左前方电机后退 Control the motor back on the left front of the car
#define Motor_L2_F_PIN 8   // 控制小车左后方电机前进 Control car left rear motor forward
#define Motor_L2_B_PIN 9   // 控制小车左后方电机后退 Control the car left rear motor back
#define Motor_R1_F_PIN 13  // 控制小车右前方电机前进 Control the right front motor of the car to move forward
#define Motor_R1_B_PIN 12  // 控制小车右前方电机后退 Control the motor back on the right front of the car
#define Motor_R2_F_PIN 14  // 控制小车右后方电机前进 Control car right rear motor forward
#define Motor_R2_B_PIN 15  // 控制小车右后方电机后退 Control car right rear motor back

// 定义底层驱动芯片参数 Bottom-layer driver chip related parameters
#define Bottom_Layer_Driver_ADDR 0x40

// 定义PWM频率 Define PWM frequency
#define PWM_FREQUENCY 50

// 定义按键引脚和控制状态 Define pin and key(button) states
#define KEY_PIN 7
#define Press_KEY 0
#define Release_KEY 1

// 定义三路循迹模块引脚 Define the three-way line patrol module pins
#define L_TRACK_PIN A2
#define M_TRACK_PIN A1
#define R_TRACK_PIN A0

// 定义超声波模块控制引脚 Define ultrasonic control pins
#define TRIG_PIN 11
#define ECHO_PIN 12

// 定义巡线阈值 Define the patrol threshold
const int Threshold = 500;

float Distance = 0.0;
const float FarDistance = 50.0;
const float MidDistance = 30.0;
const float NearDistance = 15.0;

bool bCar_Switch = false;

int iCarSpeed = 50;
unsigned int uTimeOut = 0;
  • Enumerate the common movement modes of omnidirectional cars

x
// 枚举全向小车的常见运动方式 Enumerate the common movement modes of omnidirectional cars
enum OmniDirectionalCar {
  STOP,
  FORWARD,
  BACKWARD,
  LEFT,
  RIGHT,
  LEFT_ROTATE,
  RIGHT_ROTATE,
  LEFT_FORWARD,
  RIGHT_BACKWARD,
  RIGHT_FORWARD,
  LEFT_BACKWARD,
};
  • Create an instance of the Adafruit_PWMServoDriver class

x
// 创建Adafruit_PWMServoDriver类的实例 Create an instance of the Adafruit_PWMServoDriver class
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(Bottom_Layer_Driver_ADDR);
  • Setting the Motor Speed

x
/**
 * @brief 设置单个电机速度 Setting the Motor Speed
 * @param motor_forward_pin: 控制电机前进引脚 Control the motor forward pin
 * @param motor_backward_pin: 控制电机后退引脚 Control the motor backward pin
 * @param motor_speed: 设置电机速度 Setting the Motor Speed
 * @retval 无 None
 */
void setMotorSpeed(uint16_t motor_forward_pin, uint16_t motor_backward_pin, int motor_speed) {
  motor_speed = map(motor_speed, -255, 255, -4095, 4095);
  if (motor_speed >= 0) {
    pwm.setPWM(motor_forward_pin, 0, motor_speed);
    pwm.setPWM(motor_backward_pin, 0, 0);
  } else if (motor_speed < 0) {
    pwm.setPWM(motor_forward_pin, 0, 0);
    pwm.setPWM(motor_backward_pin, 0, -(motor_speed));
  }
}
  • Set the car movement mode and speed

x
/**
 * @brief 设置小车运动方式和速度 Set the car movement mode and speed
 * @param Movement: 小车运动方式 Car movement
 * @param Speed: 小车运动速度 Car speed
 * @retval 无 None
 */
void setCarMove(uint8_t Movement, int Speed) {
  switch (Movement) {
    case STOP:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, 0);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, 0);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, 0);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, 0);
      break;
    case FORWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, Speed);
      break;
    case BACKWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, -Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, -Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, -Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, -Speed);
      break;
    case LEFT:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, -Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, -Speed);
      break;
    case RIGHT:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, -Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, -Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, Speed);
      break;
    case LEFT_ROTATE:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, -Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, -Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, Speed);
      break;
    case RIGHT_ROTATE:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, -Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, -Speed);
      break;
    case LEFT_FORWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, 0);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, 0);
      break;
    case RIGHT_BACKWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, 0);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, -Speed);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, -Speed);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, 0);
      break;
    case RIGHT_FORWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, 0);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, 0);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, Speed);
      break;
    case LEFT_BACKWARD:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, -Speed);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, 0);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, 0);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, -Speed);
      break;
    default:
      setMotorSpeed(Motor_L1_F_PIN, Motor_L1_B_PIN, 0);
      setMotorSpeed(Motor_L2_F_PIN, Motor_L2_B_PIN, 0);
      setMotorSpeed(Motor_R1_F_PIN, Motor_R1_B_PIN, 0);
      setMotorSpeed(Motor_R2_F_PIN, Motor_R2_B_PIN, 0);
      break;
  }
}
  • Get key(button) status

x
/**
 * @brief 获取按键状态 Get key(button) status
 * @param pin: 按键控制引脚 Control key(button) pins
 * @retval 按键状态 Key(button) Status
 */
int getKeyState(uint8_t pin) {
  if (digitalRead(pin) == LOW) {
    delay(20);
    if (digitalRead(pin) == LOW) {
      while (digitalRead(pin) == LOW)
        ;
      return Press_KEY;
    }
    return Release_KEY;
  } else {
    return Release_KEY;
  }
}
  • Get ultrasonic distance

x
/**
 * @brief 获取超声波距离 Get ultrasonic distance
 * @param trigPin: 触发测距引脚 Trigger pin
 * @param echoPin: 接收测距引脚 Echo pin
 * @retval 转换的距离 Measured distance (cm)
 */
float getDistance(int trigPin, int echoPin) {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  long duration = pulseIn(echoPin, HIGH);
  float distance = (duration * 0.034 / 2);
  return distance;
}
  • Car line patrol function

x
/**
 * @brief 小车巡线功能 Car line patrol function
 * @param iLeftPin: 左边循迹传感器 Left tracking sensor
 * @param iMidPin: 中间循迹传感器 Middle tracking sensor
 * @param iRightPin: 右边循迹传感器 Right tracking sensor
 * @retval 无 None
 */
void PatrolCar(int iLeftPin, int iMidPin, int iRightPin) {
  int leftValue = analogRead(iLeftPin);
  int middleValue = analogRead(iMidPin);
  int rightValue = analogRead(iRightPin);

  // The following is a simple judgment
  if ((leftValue < Threshold && middleValue > Threshold && rightValue < Threshold) | (leftValue > Threshold && middleValue > Threshold && rightValue > Threshold)) {
    setCarMove(FORWARD, iCarSpeed);
  } else if (leftValue > Threshold && middleValue < Threshold && rightValue < Threshold) {
    setCarMove(LEFT_ROTATE, iCarSpeed);
  } else if (leftValue < Threshold && middleValue < Threshold && rightValue > Threshold) {
    setCarMove(RIGHT_ROTATE, iCarSpeed);
  } else if (leftValue < Threshold && middleValue < Threshold && rightValue < Threshold) {
    uTimeOut++;
    delay(20);
    if (uTimeOut > 100) {
      uTimeOut = 0;
      setCarMove(STOP, 0);
    }
  }
}
  • Tracking and obstacle avoidance function

x
/**
 * @brief 小车巡线避障功能 Tracking and obstacle avoidance function
 * @param 无 None
 * @retval 无 None
 */
void Car_Track_Avoid() {
  Distance = getDistance(TRIG_PIN, ECHO_PIN);
  delay(10);
  if (Distance > NearDistance) {
    PatrolCar(L_TRACK_PIN, M_TRACK_PIN, R_TRACK_PIN);
  } else {
    setCarMove(STOP, 0);
  }
}
  • Set the car function switch

x
/**
 * @brief 设置小车功能开关 Set the car function switch
 * @param 无 None
 * @retval 开启/关闭 true/false
 */
bool setCarSwitch() {
  if (getKeyState(KEY_PIN) == Press_KEY) {
    bCar_Switch = !bCar_Switch;
  }
  return bCar_Switch;
}
  • Initialization Code

xxxxxxxxxx
void setup() {
  Wire.begin();                   // 初始化I2C通讯 Initialize I2C communication
  delay(1000);                    // 如果小车功能异常,可以增加这个延时 If the function is abnormal, you can increase the delay
  pwm.begin();                    // PWM初始化 Initialize the Pulse Width Modulation (PWM) library
  pwm.setPWMFreq(PWM_FREQUENCY);  // 设置PWM频率 Set the PWM frequency
  setCarMove(STOP, 0);            // 设置小车停止状态 Set the car to stop state
}
  • Looping code

xxxxxxxxxx
void loop() {
  // 按键控制小车巡线避障功能启停 The key control car patrol line obstacle avoidance function start and stop
  if (setCarSwitch()) {
    Car_Track_Avoid();
  } else {
    setCarMove(STOP, 0);
  }
}

Experimental results

After compiling the program successfully, upload the code to the Arduino Uno development board.

After the program starts, press the K1 button to start and stop the car tracking (patrol) + obstacle avoidance function.

Actual use: We can put the car on the designated track route for testing. Some obstacles can be placed on the track route; then press the K1 button to start the car function and observe the entire patrol + obstacle avoidance effect. If you need to stop the car function, you can press the K1 button to turn off the car tracking (patrol) + obstacle avoidance function.

xxxxxxxxxx
The drive motor needs an external battery pack and turn on the expansion board switch to drive normally.
The burning program cannot use other programs to occupy the serial port or an external serial communication module (for example: WiFi camera module), otherwise the program cannot be burned or an error message will be prompted!
Car Follow Hand
Car Infrared Remote

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文