Роботы с каждым годом играют все большую роль в современной цивилизации, проникая практически во все сферы нашей жизнедеятельности. В данной статье мы рассмотрим создание робота на основе платы Raspberry Pi и ультразвукового датчика HC-SR04, способного самостоятельно объезжать препятствия, встречающиеся на его пути. Ранее мы уже рассматривали создание подобного робота на основе платы Arduino. Также на нашем сайте вы можете посмотреть все проекты, связанные с робототехникой.
Необходимые компоненты
- Плата Raspberry Pi (купить на AliExpress).
- Ультразвуковой датчик HC-SR04 (купить на AliExpress).
- Шасси робота с колесами.
- Электродвигатели постоянного тока.
- Микросхема драйвера двигателей L293D (купить на AliExpress).
- Резистор 1 кОм (купить на AliExpress).
- Конденсатор 100 нФ (купить на AliExpress).
- Источник питания.
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Принцип работы ультразвукового датчика HC-SR04
Ультразвуковой датчик HC-SR04 используется для измерения расстояний в диапазоне 2-400 см с точностью 3 мм. Датчик состоит из ультразвукового передатчика, ультразвукового приемника и схемы управления.
Ультразвуковой датчик HC-SR04 обеспечивает на своем выходе сигнал, пропорциональный дистанции до препятствия. Датчик генерирует звуковые колебания в ультразвуковом диапазоне (после получения управляющего импульса) и после этого ждет когда они вернутся к нему (эхо), отразившись от какого-нибудь препятствия. Затем, основываясь на скорости звука (340 м/с) и времени, необходимом для того чтобы эхо достигло источника (нашего датчика), датчик обеспечивает на своем выходе сигнал, пропорциональный расстоянию до препятствия.
Как показано на рисунке сначала нам нужно инициировать датчик для измерения расстояний, для этого на его триггерный контакт (trigger pin) необходимо подать логический сигнал высокого уровня длительностью не менее 10 мкс, после этого датчик генерирует серию звуковых колебаний и после получения отраженного сигнала (эхо) датчик обеспечивает на своем выходе сигнал, пропорциональный расстоянию между ним и препятствием.
Ультразвуковой сигнал отражается от поверхности, возвращается обратно и улавливается приемником ультразвукового сигнала датчика. После этого на контакте Echo датчика устанавливается напряжение высокого уровня (high) на время, пропорциональное расстоянию до препятствия.
После этого расстояние до препятствия можно рассчитать по следующей формуле:
Distance= (Time x Speed of Sound in Air (343 m/s))/2
Также на нашем сайте вы можете посмотреть другие проекты, в которых был использован ультразвуковой датчик.
Фрагмент кода программы для Raspberry Pi, который будет рассчитывать измеренное расстояние до препятствия (в см), выглядит следующим образом:
1 2 3 4 5 6 7 8 9 |
pulse_start = time.time() while GPIO.input(ECHO)==1: #Check whether the ECHO is HIGH GPIO.output(led, False) pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = round(distance,2) avgDistance=avgDistance+distance |
Переменная pulse_duration в этой программе обозначает время между передачей и приемом ультразвукового сигнала.
Схема проекта
Схема робота на Raspberry Pi, объезжающего препятствия, представлена на следующем рисунке.
Модуль ультразвукового датчика в этой схеме подключен к контактам GPIO 17 и 27 платы Raspberry Pi. Микросхема драйвера мотора L293D используется для управления двигателями в нашем проекте, ее входные контакты 2, 7, 10 и 15 подключены к контактам GPIO 12, 16, 20 и 21 платы Raspberry Pi. Приводят в движение нашего робота электродвигатели, один из которых подключен к выходным контактам 3 и 6 микросхемы L293D, а другой – к контактам 11 и 14 микросхемы.
Принцип работы робота
Принцип работы нашего робота, самостоятельно объезжающего препятствия, достаточно прост. Во время движения робота плата Raspberry Pi с помощью датчика HC-SR04 измеряет расстояние до объектов по ходу движения робота и сохраняет его в соответствующей переменной. Затем плата Raspberry Pi сравнивает значение этой переменной с заранее определенным значением и на основе этого принимает решение куда роботу двигаться дальше: вперед, назад, вправо или влево.
Структурная схема работы проекта приведена на следующем рисунке.
В данном проекте мы использовали расстояние 15 см для принятия решения о недопустимо близком расстоянии до препятствия, то есть о необходимости изменения направления движения робота. То есть если расстояние до препятствия будет 15 см или меньше, то плата Raspberry Pi будет останавливать робота, затем немного передвигать его назад и после этого поворачивать его направо или налево. После поворота плата будет снова проверять расстояние до препятствия спереди робота и если оно снова меньше 15 см, то заново повторять описанный процесс. Если же расстояние до препятствия будет больше 15 см, то робот начнет двигаться вперед до тех пор пока расстояние до препятствия впереди него не станет меньше 15 см.
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Первым делом в программе нам необходимо подключить используемые библиотеки, инициализировать необходимые переменные и контакты.
1 2 3 4 5 6 7 8 9 10 11 |
import RPi.GPIO as GPIO import time #Import time library GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) TRIG = 17 ECHO = 27 ... ..... .... ..... |
После этого мы запрограммируем ряд функций def forward(), def back(), def left(), def right() для движения робота вперед, назад, влево и вправо соответственно. Функция def stop() будет использоваться для остановки робота.
Далее, в основной программе, мы инициализируем ультразвуковой датчик, будем определять время между передачей и приемом ультразвуковой волны и на основании этого рассчитывать расстояние до препятствия. Этот процесс мы будем повторять 5 раз для повышения точности измерений.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
i=0 avgDistance=0 for i in range(5): GPIO.output(TRIG, False) time.sleep(0.1) GPIO.output(TRIG, True) time.sleep(0.00001) GPIO.output(TRIG, False) while GPIO.input(ECHO)==0: GPIO.output(led, False) pulse_start = time.time() while GPIO.input(ECHO)==1: #Check whether the ECHO is HIGH GPIO.output(led, False) pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = round(distance,2) avgDistance=avgDistance+distance |
И, наконец, если робот обнаружит препятствие впереди себя, мы запрограммируем алгоритм чтобы он объехал его (не столкнулся с ним).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
if avgDistance < 15: count=count+1 stop() time.sleep(1) back() time.sleep(1.5) if (count%3 ==1) & (flag==0): right() flag=1 else: left() flag=0 time.sleep(1.5) stop() time.sleep(1) else: forward() flag=0 |
Исходный код программы на Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
import RPi.GPIO as GPIO # подключение библиотеки для работы с контактами ввода/вывода import time # подключение библиотеки для работы с задержками GPIO.setwarnings(False) # отключаем показ любых предупреждений GPIO.setmode(GPIO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM) TRIG = 17 ECHO = 27 led = 22 m11=16 m12=12 m21=21 m22=20 GPIO.setup(TRIG,GPIO.OUT) # инициализируем GPIO TRIG в качестве цифрового выхода GPIO.setup(ECHO,GPIO.IN) # инициализируем GPIO ECHO в качестве цифрового входа GPIO.setup(led,GPIO.OUT) GPIO.setup(m11,GPIO.OUT) GPIO.setup(m12,GPIO.OUT) GPIO.setup(m21,GPIO.OUT) GPIO.setup(m22,GPIO.OUT) GPIO.output(led, 1) time.sleep(5) def stop(): print "stop" GPIO.output(m11, 0) GPIO.output(m12, 0) GPIO.output(m21, 0) GPIO.output(m22, 0) def forward(): GPIO.output(m11, 1) GPIO.output(m12, 0) GPIO.output(m21, 1) GPIO.output(m22, 0) print "Forward" def back(): GPIO.output(m11, 0) GPIO.output(m12, 1) GPIO.output(m21, 0) GPIO.output(m22, 1) print "back" def left(): GPIO.output(m11, 0) GPIO.output(m12, 0) GPIO.output(m21, 1) GPIO.output(m22, 0) print "left" def right(): GPIO.output(m11, 1) GPIO.output(m12, 0) GPIO.output(m21, 0) GPIO.output(m22, 0) print "right" stop() count=0 while True: i=0 avgDistance=0 for i in range(5): GPIO.output(TRIG, False) # устанавливаем на TRIG уровень LOW time.sleep(0.1) # задержка GPIO.output(TRIG, True) # устанавливаем на TRIG уровень HIGH time.sleep(0.00001) # задержка 0.00001 секунды GPIO.output(TRIG, False) # устанавливаем на TRIG уровень LOW while GPIO.input(ECHO)==0: # проверяем что на ECHO уровень LOW GPIO.output(led, False) pulse_start = time.time() while GPIO.input(ECHO)==1: # проверяем что на ECHO уровень HIGH GPIO.output(led, False) pulse_end = time.time() pulse_duration = pulse_end - pulse_start # время между передачей и приемом ультразвуковой волны distance = pulse_duration * 17150 # умножаем это время на 17150 (34300/2) чтобы рассчитать расстояние distance = round(distance,2) # округляем до двух точек после запятой avgDistance=avgDistance+distance avgDistance=avgDistance/5 print avgDistance flag=0 if avgDistance < 15: # проверяем меньше ли 15 см расстояние до препятствия count=count+1 stop() time.sleep(1) back() time.sleep(1.5) if (count%3 ==1) & (flag==0): right() flag=1 else: left() flag=0 time.sleep(1.5) stop() time.sleep(1) else: forward() flag=0 |