Сейчас одной из актуальных обсуждаемых тем являются беспилотные автомобили. Некоторые пытаются сделать их на базе Raspberry Pi и используя технологию компьютерного зрения. Это нормальное решение, которое имеет свои достоинства и недостатки.
Другой, но более простой способ — это автомобиль, следящий за линией. Такие роботы следуют за определенной цветной линии, нарисованной на дорожном покрытии. Такой способ можно реализовать с помощью камеры или ИК-датчика.
Мастер реализовал еще один способ, в котором дорожному покрытию не нужны линии, а автомобилю следящие датчики.
В данном случае задача реализована следующим образом: дорога запрограммирована на удаленном компьютере и он же, компьютер дает команды автомобилю, куда нужно повернуть и когда остановится.
На экране удаленного компьютера движется автомобиль по заданному маршруту. Программа вычисляет траекторию движения и два авто, один на компьютере, второй на дороге, синхронно выполняют команды.Давайте посмотрим видео, и в самом начале его будет демонстрация работы такого комплекса.
Инструменты и материалы:-Arduino Nano;-Модуль драйвера двигателя L298n;-Мотор + колеса — 4шт;-Модуль Bluetooth HC05;
-Соединительные провода;
-Паяльные принадлежности;
-Лист ПВХ;
-Аккумулятор 7,4 В;
-Клеевой пистолет;Шаг первый: корпус
Корпус или платформа авто сделана из ПВХ. В принципе материал и форма значения не имеют и авто нужен только как способ проверки работы комплекса.
Размечает и вырезает платформу. Закрепляет двигатели и подключает провода.Шаг второй: плата и схема
Мастер разработал схему с помощью программы EasyEDA. Затем разработал печатную плату и заказал ее изготовление на соответствующем сервисе. Скачать файлы для изготовления платы можно здесь.После изготовления платы все собрал и подключил.
Левые моторы к D5, D6
Правые моторы к D3, D4
Модуль Bluetooth
VCC к 5 В
Gnd к Gnd
tx к Arduino Rx
Rx к Arduino Tx
После монтажа подключил аккумуляторы.Шаг третий: программирование Arduino
Теперь можно загрузить программу в робота. Поскольку модуль bluetooth подключен к аппаратному последовательному порту, мастер снимает перемычку перед загрузкой кода.
Сначала он определил, к какому выводу подключены двигатели


// Declare motor pins
// motors of same side work as one
// so we can consider both as one.
int rightMotor1 = 2; // right side
int rightMotor2 = 3;
int leftMotor1 = 5; // left side
int leftMotor2 = 6;
Затем устанавливает выводы двигателя как выходные данные в функции setup ()
// Set pin modes
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
Затем инициализировал последовательную связь для получения данных от модуля Bluetooth —
// Initialize serial communication
Serial.begin(9600);
Эта часть проверяет байтовые данные из последовательного порта, к которому подключен модуль Bluetooth.
// Variable to store received data
byte command;
// Get command data from bluetooth serial port
command = Serial.read();
Команды следующие:
‘f’ — вперед
‘b’ — назад
‘l’ — влево
‘r’ — вправо
У каждого мотора есть два контакта. Чтобы запустить их в нужном направлении, нам нужно сделать один вывод HIGH, а другой — LOW. Если они оба одновременно HIGH или LOW, моторы не будут вращаются.
if (command == 'f'){
// indicates forward motion
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
Загружает код с помощью Arduino.ide и переходит к следующему шагу.
/* ** Virtual Path Following Robot *
* Robot Actuator's program
*
* This robot takes commands from a python program
* and follows those commands. This robot demonstrates
* virtual path following robots and it's scopes.
*
* *********** License: GPL3+ *************
* You should receive a copy of the license
* with this program.
*
* (c) author: ashraf minhaj
* mail : ashraf_minhaj@yahoo.com
*
* Tutorial for this project:
* http://youtube.com/fusebatti
* http://youtube.com/fusebatti
*
* written on 15th Feb 2021
*/
// Declare motor pins
// motors of same side work as one
// so we can consider both as one.
int rightMotor1 = 2; // right side
int rightMotor2 = 3;
int leftMotor1 = 5; // left side
int leftMotor2 = 6;
// Variable to store received data
byte command;
void setup() {
// Set pin modes
pinMode(rightMotor1, OUTPUT);
pinMode(rightMotor2, OUTPUT);
pinMode(leftMotor1, OUTPUT);
pinMode(leftMotor2, OUTPUT);
// Initialize serial communication
// at 9600 buad rate
// sender/python code will also use
// the same buad
Serial.begin(9600);
}
void loop() {
// Get command data from bluetooth serial port
command = Serial.read();
// Decide which way to go based on received data
if (command == 'f'){
// indicates forward motion
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
}
if (command == 'b'){
// Backward motion
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
}
if (command == 'r'){
// Right turn
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, HIGH);
digitalWrite(leftMotor1, HIGH);
digitalWrite(leftMotor2, LOW);
}
if (command == 'l'){
// Left turn
digitalWrite(rightMotor1, HIGH);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, HIGH);
}
if (command == 's'){
// Stops the robot/car
digitalWrite(rightMotor1, LOW);
digitalWrite(rightMotor2, LOW);
digitalWrite(leftMotor1, LOW);
digitalWrite(leftMotor2, LOW);
}
}
Шаг четвертый: код Python
Сначала нужно загрузить программу python (python.org/downloads).
Для работы программы нужны две библиотеки: pygame и pySerial. Мастер установил их из командной строки вот таким способом:
$ pip install pygame
$ pip install pySerial
Затем нужно установить алгоритм «чтения» дороги и движения по ней машины.


bg = pygame.image.load ("track1.png")
car = pygame.image.load ("car.png")
Чтобы отправить данные с ПК на Bluetooth Arduino, сначала нужно подключить модуль Bluetooth к своему компьютеру.
Включаем Bluetooth
Переходим в panel > device manager
Далее Search for new devices
Добавляем устройство (HC05) вводим пароль (по умолчанию «0000» или «1234»]
Затем кликает по свойствам устройства, чтобы получить номер порта HC05, на PC он был ‘COM8’. Python соединяется так:
PORT = "COM8"
BUADRATE = 9600
robot = serial.Serial(PORT, BUADRATE) # connect robot
Чтобы робот проверил окружение, нужно найти центр машины:
# find the center of the car and draw a point on that
center_x, center_y = (int(car_x + 40 /2), int(car_y + 40 / 2))
Остальная часть кода проверяет дорогу и поворачивает или перемещает машину. Данные в Arduino через последовательный порт отправляются следующим образом:
# start the robot
robot.write(b'f')
# turn left
robot.write(b'l')
Теперь можно загрузить код:
"""
** Virtual Path Follower Robot **
License: GPL3
You should receive a copy of license with this program.
(c) author: ashraf minhaj
mail : ashraf_minhaj@yahoo.com
Written on 15th Feb 2021
"""
""" install -
$ pip install pygame
$ pip install pySerial
"""
# import library
import pygame
import serial
from time import sleep
# robot port and buadrate
# change these according to your need
PORT = "COM8"
BUADRATE = 9600
# initialize things
pygame.init()
robot = serial.Serial(PORT, BUADRATE) # connect robot
# create window with size (our image size)
window = pygame.display.set_mode((700,400)) # track 1
#window = pygame.display.set_mode((1155,399)) # track 2
# load image file
bg = pygame.image.load("track1.png")
#bg = pygame.image.load("track2.png")
car = pygame.image.load("car.png")
car = pygame.transform.scale(car, (40, 40)) # resize car image
""" main loop varibales and things """
# set up timer clock
clock = pygame.time.Clock()
# initial x y axis position of the car
car_x = 30
car_y = 260
JUMP_VALUE = 25 # turning point value
direction = 'y_up' # cars current direction
run = 1
# start the robot
robot.write(b'f')
DELAY = .400
# main loop
while run:
clock.tick(30) # update the window/run loop by this speed
#check for events
for event in pygame.event.get():
# quit button clicked
if event.type == pygame.QUIT:
run = 0
# position images
window.blit(bg, (0, 0)) # load the track image
window.blit(car, (car_x, car_y)) # the car image
# record last x, y pos of car
last_x, last_y = car_x, car_y
# find the center of the car and draw a point on that
center_x, center_y = (int(car_x + 40 /2), int(car_y + 40 / 2))
pygame.draw.circle(window, (0,255,255), (center_x, center_y), 5, 5)
# check surrounding (4 direction data)
# the calibration value is the pixel from car's sensor/mid point
# so it checks for road info 30 pixels far from the sensor.
# 255 means we have a clear white road
cal_value = 30 # calibrate this to get good data
y_up = window.get_at((center_x, center_y - cal_value))[0]
y_down = window.get_at((center_x, center_y + cal_value))[0]
x_right = window.get_at((center_x + cal_value, center_y))[0]
x_left = window.get_at((center_x - cal_value, center_y))[0]
#print("y_up ", y_up)
#print("y_down ", y_down)
#print("x_right", x_right)
#print("x_left ", x_left)
#print("-----------")
# determine which way to go
# go up
if y_up == 255 and direction == 'y_up' and x_left != 255 and x_right != 255:
# move up
car_y -= 2 # decrease pixel and move the car on y axis
# make the turn
if y_up == 255 and direction == 'y_up' and x_left != 255 and x_right == 255:
# make a right turn
direction = 'x_right'
car_y -= JUMP_VALUE
car_x += JUMP_VALUE
car = pygame.transform.rotate(car, -90)
window.blit(car, (car_x, car_y))
print('Turn Right')
robot.write(b'r')
sleep(DELAY)
robot.write(b'f')
# go x right
if y_up != 255 and direction == 'x_right' and y_down != 255 and x_right == 255:
car_x += 2
if y_down == 255 and direction == 'x_right' and x_left == 255 and x_right == 255:
# make a turn from x_right
car = pygame.transform.rotate(car, -90)
direction = 'y_down'
car_y += JUMP_VALUE + 5
car_x += JUMP_VALUE
window.blit(car, (car_x, car_y))
print('Turn Right')
robot.write(b'r')
sleep(DELAY)
robot.write(b'f')
# go y down
if y_down == 255 and direction == 'y_down' and x_left != 255 and x_right != 255:
# move down
car_y += 2
# left turn
if y_down == 255 and direction == 'y_down' and x_left != 255 and x_right == 255:
# turn from y_down
car = pygame.transform.rotate(car, 90)
direction = 'x_right'
car_y += JUMP_VALUE
car_x += JUMP_VALUE
print('Turn left')
robot.write(b'l')
sleep(DELAY)
robot.write(b'f')
# turn to y up
if y_up == 255 and direction == 'x_right' and x_left == 255 and x_right == 255:
# turn from y_down
car = pygame.transform.rotate(car, 90)
direction = 'y_up'
car_y -= JUMP_VALUE + 5
car_x += JUMP_VALUE
print('Turn left')
robot.write(b'l')
sleep(DELAY)
robot.write(b'f')
# if car is stopped
if car_x == last_x and car_y == last_y:
# stop the engine sound
print("STOPPED")
robot.write(b's')
pygame.display.update() # update the window
pygame.quit() #close everything
Все готово. Конечно, такой автомобиль не выпустишь на дороги общего пользования, но использовать устройства на предприятии вполне возможно.

