Проект 11: Робот который ездит по линии
Этот проект основан на роботе, собранном из набора 4WD Smart Car Kit, который будет следовать за линией и выполнять различные виды поворотов с помощью четырех датчиков линии. Используя управление двумя моторами через библиотеку AlashMotorControlX2, робот будет обнаруживать и следовать за черной линией на белом фоне. В этом проекте робот будет выполнять нормальные и резкие повороты в зависимости от показаний датчиков линии.
Принцип работы
Датчики линии определяют, находится ли робот на линии или вне ее. В зависимости от показаний датчиков, Arduino принимает решение о направлении движения робота: вперед, налево, направо, резкий поворот налево или резкий поворот направо. Моторы управляются через библиотеку AlashMotorControlX2.
Необходимые компоненты
Arduino Uno
4 датчика линии
Модуль драйвера двигателя L298N или TA6586
2 DC мотора
Источник питания
Шасси робота с колесами
Трасса с черной линией на белом фоне
Подключение компонентов
Подключение датчиков линии:
Крайний левый датчик → пин 2
Центральный левый датчик → пин 3
Центральный правый датчик → пин 4
Крайний правый датчик → пин 12
VCC → 5V Arduino
GND → GND Arduino
Подключение модуля L298N:
ENA → пин 10 (управление скоростью левого мотора)
IN1 → пин 9 (направление левого мотора)
IN2 → пин 8 (направление левого мотора)
IN3 → пин 7 (направление правого мотора)
IN4 → пин 6 (направление правого мотора)
ENB → пин 5 (управление скоростью правого мотора)
VCC → 5V Arduino
GND → GND Arduino
VM → внешний источник питания
Настройка чувствительности датчиков линии
Чтобы робот мог точно следовать за линией, необходимо правильно настроить чувствительность каждого датчика линии. Для этого необходимо выполнить следующие шаги:
Настройка чувствительности датчиков:
Каждый датчик линии имеет потенциометр, с помощью которого можно регулировать его чувствительность. Поворачивайте потенциометр, пока датчик не начнет стабильно реагировать на линию.
Для точной настройки датчиков можно использовать специальный проект «Датчик линии», в котором подробно описан процесс настройки чувствительности датчиков. Обратитесь к этому проекту для получения более детальной информации.
Тестирование и корректировка:
После настройки чувствительности датчиков, протестируйте робота на линии. Убедитесь, что робот корректно распознает линию и выполняет необходимые повороты.
Если робот не следует линии должным образом, попробуйте скорректировать чувствительность датчиков и скорость моторов.
Продолжайте регулировать настройки, пока робот не начнет двигаться идеально по линии.
Алгоритм работы
Робот работает по следующему алгоритму:
Считывание датчиков - все 4 датчика линии считывают состояние поверхности
Анализ положения - определяется, на какой части линии находится робот
Выбор действия: - Все датчики на белом → движение вперед - Центральный левый на черном → поворот налево - Центральный правый на черном → поворот направо - Крайний левый на черном → резкий поворот налево - Крайний правый на черном → резкий поворот направо
Выполнение действия - робот выполняет выбранное движение
Повторение - цикл повторяется
Пример кода для L298N
// Подключаем библиотеку
#include <AlashMotorControlX2.h>
// Определение пинов для моторов (стиль AlashMotorControlX2)
// Мотор A - Левый мотор
const unsigned int PIN_IN1_A = 9; // Пин IN1 левого мотора (Логика HIGH = вперед для мотора A)
const unsigned int PIN_IN2_A = 8; // Пин IN2 левого мотора (Логика LOW = вперед для мотора A)
const unsigned int PIN_EN_A = 10; // Пин Enable (PWM) левого мотора - должен быть PWM-пином!
// Мотор B - Правый мотор
const unsigned int PIN_IN1_B = 7; // Пин IN1 правого мотора (Логика HIGH = вперед для мотора B)
const unsigned int PIN_IN2_B = 6; // Пин IN2 правого мотора (Логика LOW = вперед для мотора B)
const unsigned int PIN_EN_B = 5; // Пин Enable (PWM) правого мотора - должен быть PWM-пином!
// Инициализация двух моторов для L298N с PWM (Enable пинами)
// Используем конструктор с 6 параметрами
AlashMotorControlX2 motors(PIN_IN1_A, PIN_IN2_A, PIN_EN_A,
PIN_IN1_B, PIN_IN2_B, PIN_EN_B,
DRIVER_L298N, // Явно указываем тип драйвера (по умолчанию L298N)
DRIVER_L298N);
// Определение пинов для датчиков линии
const unsigned int SENSOR_EXTREME_LEFT = 2; // Крайний левый датчик
const unsigned int SENSOR_CENTER_LEFT = 3; // Центральный левый датчик
const unsigned int SENSOR_CENTER_RIGHT = 4; // Центральный правый датчик
const unsigned int SENSOR_EXTREME_RIGHT = 12; // Крайний правый датчик
// Определение состояний робота
#define STATE_FORWARD 0
#define STATE_RIGHT 1
#define STATE_LEFT 2
#define STATE_SUPER_RIGHT 3
#define STATE_SUPER_LEFT 4
#define STATE_STOP 5
int state = STATE_FORWARD; // Начальное состояние
// Параметры скорости
int SpeedAll = 80; // Базовая скорость (0-255)
int SuperTurnSpeedAll = 150; // Скорость для резких поворотов (0-255)
int TurnSpeedAll = 100; // Скорость для обычных поворотов (0-255)
// Переменные для хранения состояния датчиков
boolean centerLeftActive = false;
boolean centerRightActive = false;
boolean extremeLeftActive = false;
boolean extremeRightActive = false;
void setup() {
Serial.begin(9600); // Инициализация последовательного порта
while (!Serial) {
; // Ожидание открытия Serial Monitor
}
Serial.println("Line Follower - AlashMotorControlX2 (L298N with PWM)");
// Установка пинов датчиков как входы
pinMode(SENSOR_EXTREME_LEFT, INPUT);
pinMode(SENSOR_CENTER_LEFT, INPUT);
pinMode(SENSOR_CENTER_RIGHT, INPUT);
pinMode(SENSOR_EXTREME_RIGHT, INPUT);
// Установка начальной скорости
motors.setSpeed(SpeedAll);
Serial.println("Setup complete.");
}
void loop() {
// Чтение состояния датчиков линии
extremeLeftActive = (digitalRead(SENSOR_EXTREME_LEFT) == HIGH);
centerLeftActive = (digitalRead(SENSOR_CENTER_LEFT) == HIGH);
centerRightActive = (digitalRead(SENSOR_CENTER_RIGHT) == HIGH);
extremeRightActive = (digitalRead(SENSOR_EXTREME_RIGHT) == HIGH);
// Определение целевого состояния
int targetState;
if (centerLeftActive == centerRightActive && extremeLeftActive == extremeRightActive) {
targetState = STATE_FORWARD;
} else if (centerLeftActive) {
targetState = STATE_LEFT;
} else if (centerRightActive) {
targetState = STATE_RIGHT;
} else if (extremeLeftActive) {
targetState = STATE_SUPER_LEFT;
} else if (extremeRightActive) {
targetState = STATE_SUPER_RIGHT;
} else {
targetState = STATE_FORWARD; // По умолчанию вперед
}
// Вывод информации о состоянии
Serial.println(targetState);
// Если состояние не изменилось, выходим из текущей итерации loop
if (state == targetState) {
return;
}
// Обновляем состояние и выполняем соответствующее действие
state = targetState;
switch (state) {
case STATE_FORWARD:
goForward();
Serial.println("F");
break;
case STATE_RIGHT:
turnRight();
Serial.println("R");
break;
case STATE_LEFT:
turnLeft();
Serial.println("L");
break;
case STATE_SUPER_RIGHT:
turnSuperRight();
Serial.println("SR");
break;
case STATE_SUPER_LEFT:
turnSuperLeft();
Serial.println("SL");
break;
case STATE_STOP:
stopMotors();
Serial.println("S");
break;
}
delay(50); // Задержка
}
// Функции управления движением
void goForward() {
motors.setSpeed(SpeedAll);
motors.forward();
}
void turnLeft() {
int turnSpeed = constrain(SpeedAll + TurnSpeedAll, 0, 255);
motors.setSpeedA(turnSpeed);
motors.setSpeedB(turnSpeed);
motors.backwardA();
motors.forwardB();
}
void turnRight() {
int turnSpeed = constrain(SpeedAll + TurnSpeedAll, 0, 255);
motors.setSpeedA(turnSpeed);
motors.setSpeedB(turnSpeed);
motors.forwardA();
motors.backwardB();
}
void turnSuperLeft() {
int superTurnSpeed = constrain(SpeedAll + SuperTurnSpeedAll, 0, 255);
motors.setSpeedA(superTurnSpeed);
motors.setSpeedB(superTurnSpeed);
motors.backwardA();
motors.forwardB();
}
void turnSuperRight() {
int superTurnSpeed = constrain(SpeedAll + SuperTurnSpeedAll, 0, 255);
motors.setSpeedA(superTurnSpeed);
motors.setSpeedB(superTurnSpeed);
motors.forwardA();
motors.backwardB();
}
void stopMotors() {
motors.stop();
}
Пример кода для TA6586
// Подключаем библиотеку
#include <AlashMotorControlX2.h>
#include <AlashMotorDriverType.h> // Подключаем для использования DRIVER_TA6586
// Определение пинов для моторов TA6586
// ВАЖНО: Для TA6586 пины IN1 и IN2 ДОЛЖНЫ быть PWM-пинами!
// Пример для Arduino Uno/Nano (PWM пины: 3, 5, 6, 9, 10, 11)
// Мотор A - Левый мотор
const unsigned int PIN_IN1_A = 9; // Пин IN1 для левого мотора (PWM)
const unsigned int PIN_IN2_A = 10; // Пин IN2 для левого мотора (PWM)
// Пин Enable НЕ используется для TA6586
// Мотор B - Правый мотор
const unsigned int PIN_IN1_B = 5; // Пин IN1 для правого мотора (PWM)
const unsigned int PIN_IN2_B = 6; // Пин IN2 для правого мотора (PWM)
// Пин Enable НЕ используется для TA6586
// Инициализация двух моторов для драйвера TA6586
AlashMotorControlX2 motors(PIN_IN1_A, PIN_IN2_A, // Пины мотора A
PIN_IN1_B, PIN_IN2_B, // Пины мотора B
DRIVER_TA6586, // Тип драйвера для мотора A
DRIVER_TA6586); // Тип драйвера для мотора B
// Определение пинов для датчиков линии
const unsigned int SENSOR_EXTREME_LEFT = 2;
const unsigned int SENSOR_CENTER_LEFT = 3;
const unsigned int SENSOR_CENTER_RIGHT = 4;
const unsigned int SENSOR_EXTREME_RIGHT = 12;
// Определение состояний робота
#define STATE_FORWARD 0
#define STATE_RIGHT 1
#define STATE_LEFT 2
#define STATE_SUPER_RIGHT 3
#define STATE_SUPER_LEFT 4
#define STATE_STOP 5
int state = STATE_FORWARD; // Начальное состояние робота
// Параметры скорости
int SpeedAll = 80;
int SuperTurnSpeedAll = 150;
int TurnSpeedAll = 100;
// Переменные для хранения состояния датчиков
boolean right = false; // Активен центральный правый датчик
boolean left = false; // Активен центральный левый датчик
boolean Sright = false; // Активен крайний правый датчик
boolean Sleft = false; // Активен крайний левый датчик
void setup() {
Serial.begin(9600);
while (!Serial) {
; // Ожидание открытия Serial Monitor
}
Serial.println("Line Follower Robot - AlashMotorControlX2 (TA6586 Driver)");
// Установка пинов датчиков как входы
pinMode(SENSOR_EXTREME_LEFT, INPUT);
pinMode(SENSOR_CENTER_LEFT, INPUT);
pinMode(SENSOR_CENTER_RIGHT, INPUT);
pinMode(SENSOR_EXTREME_RIGHT, INPUT);
Serial.println("Setup complete. Starting loop...");
}
void loop() {
// Чтение состояния датчиков линии
Sleft = (digitalRead(SENSOR_EXTREME_LEFT) == HIGH);
left = (digitalRead(SENSOR_CENTER_LEFT) == HIGH);
right = (digitalRead(SENSOR_CENTER_RIGHT) == HIGH);
Sright = (digitalRead(SENSOR_EXTREME_RIGHT) == HIGH);
// Определение целевого состояния
int targetState;
if (left == right && Sleft == Sright) targetState = STATE_FORWARD;
else if (left) targetState = STATE_LEFT;
else if (right) targetState = STATE_RIGHT;
else if (Sleft) targetState = STATE_SUPER_LEFT;
else if (Sright) targetState = STATE_SUPER_RIGHT;
else targetState = STATE_FORWARD;
// Если состояние не изменилось, ничего не делаем
if (state == targetState) {
return;
}
// Обновляем состояние и выполняем соответствующее действие
state = targetState;
switch (state) {
case STATE_FORWARD:
forward();
break;
case STATE_RIGHT:
rightTurn();
break;
case STATE_LEFT:
leftTurn();
break;
case STATE_SUPER_RIGHT:
superRightTurn();
break;
case STATE_SUPER_LEFT:
superLeftTurn();
break;
case STATE_STOP:
stopMotors();
break;
}
delay(10);
}
// Функции управления движением для TA6586
void forward() {
int constrainedSpeed = constrain(SpeedAll, 0, 255);
motors.setSpeed(constrainedSpeed);
motors.forward();
}
void leftTurn() {
int turnSpeed = constrain(SpeedAll + TurnSpeedAll, 0, 255);
motors.setSpeedA(turnSpeed);
motors.setSpeedB(turnSpeed);
motors.backwardA();
motors.forwardB();
}
void rightTurn() {
int turnSpeed = constrain(SpeedAll + TurnSpeedAll, 0, 255);
motors.setSpeedA(turnSpeed);
motors.setSpeedB(turnSpeed);
motors.forwardA();
motors.backwardB();
}
void superLeftTurn() {
int superTurnSpeed = constrain(SpeedAll + SuperTurnSpeedAll, 0, 255);
motors.setSpeedA(superTurnSpeed);
motors.setSpeedB(superTurnSpeed);
motors.backwardA();
motors.forwardB();
}
void superRightTurn() {
int superTurnSpeed = constrain(SpeedAll + SuperTurnSpeedAll, 0, 255);
motors.setSpeedA(superTurnSpeed);
motors.setSpeedB(superTurnSpeed);
motors.forwardA();
motors.backwardB();
}
void stopMotors() {
motors.stop();
}
Результат работы
После загрузки кода робот будет:
Двигаться вперед, когда все датчики находятся на белой поверхности
Поворачивать налево при обнаружении линии центральным левым датчиком
Поворачивать направо при обнаружении линии центральным правым датчиком
Выполнять резкий поворот налево при обнаружении линии крайним левым датчиком
Выполнять резкий поворот направо при обнаружении линии крайним правым датчиком
Настройка параметров
Для оптимизации работы робота можно изменить следующие параметры:
Базовая скорость: Измените SpeedAll для регулировки скорости движения вперед
Скорость поворота: Измените TurnSpeedAll для настройки скорости обычных поворотов
Скорость резкого поворота: Измените SuperTurnSpeedAll для настройки скорости резких поворотов
Задержка цикла: Измените delay(50) для настройки частоты обновления состояния
Заключение
Этот проект позволяет создать робота, который следует за линией и выполняет различные виды поворотов, используя четыре датчика линии и библиотеку AlashMotorControlX2 для управления моторами. Важно правильно настроить чувствительность датчиков линии и отрегулировать скорость робота, чтобы он мог корректно следовать за линией.
Для более детальной информации по настройке датчиков линии обратитесь к проекту «Датчик линии». Экспериментируйте с настройками и компонентами, чтобы убедиться, что робот работает корректно и следует за линией.