Авто с управлением удаленным компьютером
Сейчас одной из актуальных обсуждаемых тем являются беспилотные автомобили. Некоторые пытаются сделать их на базе 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
Все готово. Конечно, такой автомобиль не выпустишь на дороги общего пользования, но использовать устройства на предприятии вполне возможно.