Недавно появившиеся на рынке компьютеры и ноутбуки с возможностью управления жестами рук с каждым годом становятся все популярнее. Эта технология позволяет нам управлять определенными функциями на компьютере/ноутбуке просто двигая руками перед ним. Выглядит это потрясающе, но, к сожалению, такие компьютеры пока еще достаточно дорого стоят. Поэтому в данной статье мы рассмотрим собственный (недорогой) проект управления компьютером с помощью жестов рук используя мощь технологий Arduino и Python.
В нашем проекте мы будем использовать два ультразвуковых датчика, с помощью которых будет определяться положение наших рук и на основе этого управляться медиа плеер (VLC). В нашем проекте мы рассмотрим только самые простые основы подобного управления, но, поняв его, вы сможете самостоятельно реализовать более продвинутые проекты управления просто изменяя коды приведенных в данной статье программ.
Прежде чем начинать реализацию данного проекта вам необходимо изучить статью на нашем сайте про взаимодействие Arduino и Python и вам необходимо установить на компьютер Python и библиотеку для него pyserial.
Принцип работы проекта
Концепция нашего проекта достаточно проста. Мы будем размещать два ультразвуковых датчика сверху монитора компьютера, которые будут измерять с помощью Arduino расстояние между нашими руками и монитором компьютера. А затем на основании этого измеренного расстояния мы будем выполнять определенные действия.
Для выполнения этих действия на компьютере мы будем использовать библиотеку Python pyautogui. Команды от платы Arduino в компьютер будут передаваться через последовательный порт (USB). Эти данные будут считываться программой на Python, которая в это время должна быть запущена на компьютере.
Работа схемы
Схема устройства представлена на следующем рисунке.
Как видите, схема нашего проекта достаточно простая – достаточно соединить два ультразвуковых датчика с платой Arduino. Ультразвуковые датчики работают от напряжения 5V, поэтому в нашей схеме их питание осуществляется непосредственно с платы Arduino. Сама плата Arduino запитывается по кабелю USB от компьютера – по этому же кабелю осуществляется и передача данных. Когда все соединения в схеме сделаны разместите получившуюся конструкцию на компьютере/ноутбуке как показано на рисунке ниже. Мы для крепления этих элементов использовали двухсторонний скотч, но вы можете сделать это так, как вам будет удобно. После этого можно приступать непосредственно к программированию.
Программирование платы Arduino
Основная цель платы Arduino в этом проекте – это измерять расстояние с помощью ультразвуковых датчиков. Полный код программы приведен в конце статьи, здесь же обсудим его наиболее важные фрагменты.
При помощи определения расстояний до руки мы можем запрограммировать несколько действий для нашего проекта. Мы запрограммировали 5 действий, но вы при желании можете увеличить их количество.
Действие 1. Когда обе руки размещены на определенном (достаточно далеком) расстоянии перед датчиками плеер VLC должен выполнять функцию Play/Pause.
Действие 2. Когда правая рука размещена на определенном (достаточно далеком) расстоянии перед датчиком видео должно перематываться вперед (Fast Forward) на один шаг.
Действие 3. Когда левая рука размещена на определенном (достаточно далеком) расстоянии перед датчиком видео должно перематываться назад (Rewind) на один шаг.
Действие 4. Когда правая рука размещена на определенном (достаточно близком) расстоянии перед датчиком и если она двигается по направлению к датчику то видео должно перематываться вперед, а если она удаляется от датчика, то видео должно перематываться назад.
Действие 5. Когда левая рука размещена на определенном (достаточно близком) расстоянии перед датчиком и если она двигается по направлению к датчику, то громкость звука в видео должна увеличиваться, а если она удаляется от датчика, то громкость звука в видео должна уменьшаться.
Теперь давайте рассмотрим как это все можно запрограммировать. Сначала мы должны инициализировать и задать режимы работы для необходимых контактов ввода/вывода. Два ультразвуковых датчика подключены к цифровым контактам платы Arduino 2, 3, 4 и 5 и запитаны от контакта +5V платы. Последовательную связь между платой Arduino и языком программирования Python будем осуществлять на скорости 9600 бод/с.
1 2 3 4 5 6 7 8 9 10 11 12 |
const int trigger1 = 2; //Trigger pin первого датчика const int echo1 = 3; //Echo pin первого датчика const int trigger2 = 4; //Trigger pin второго датчика const int echo2 = 5;//Echo pin второго датчика void setup() { Serial.begin(9600); pinMode(trigger1, OUTPUT); pinMode(echo1, INPUT); pinMode(trigger2, OUTPUT); pinMode(echo2, INPUT); } |
Нам необходимо рассчитывать расстояние между датчиком и рукой каждый раз перед тем как выполнять какое-либо действие. Поскольку мы это будем делать очень часто, то вполне логично оформить все это в виде функции, которую мы назвали calculate_distance() – при вызове она будет определять нам расстояние между датчиком и рукой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/*###Function to calculate distance###*/ void calculate_distance(int trigger, int echo) { digitalWrite(trigger, LOW); delayMicroseconds(2); digitalWrite(trigger, HIGH); delayMicroseconds(10); digitalWrite(trigger, LOW); time_taken = pulseIn(echo, HIGH); dist= time_taken*0.034/2; if (dist>50) dist = 50; } |
Внутри основной функции loop мы будем проверять измеренное значение расстояния и на основании этого выполнять одно из действий, описанных выше. Для хранения информации от наших рук до ультразвуковых датчиков мы будем использовать переменные distL и distR.
1 2 3 4 5 |
calculate_distance(trigger1,echo1); distL =dist; // расстояние для левого датчика calculate_distance(trigger2,echo2); distR =dist; // расстояние для правого датчика |
Поскольку мы теперь знаем расстояния для обоих датчиков мы можем сравнить их с заранее определенными значениями и на основании этого выполнить определенные действия. К примеру, если обе руки помещены на расстоянии более 40 см от датчиков, мы должны play/pause (воспроизводить/ставить на паузу) видео. Соответственно, через последовательный порт будет передаваться слово “Play/Pause”.
1 2 |
if ((distL >40 && distR>40) && (distL <50 && distR<50)) //Detect both hands {Serial.println("Play/Pause"); delay (500);} |
Если только правая рука размещена перед датчиком мы должны быстро перематывать видео вперед на один шаг, а если только левая рука – мы должны быстро перематывать видео назад на один шаг. Соответственно, в данном случае через последовательный порт связи должны передаваться слова “Rewind” или “Forward”.
1 2 3 4 5 |
if ((distL >40 && distL<50) && (distR ==50)) //обнаруживаем левую руку {Serial.println("Rewind"); delay (500);} if ((distR >40 && distR<50) && (distL ==50)) //обнаруживаем правую руку {Serial.println("Forward"); delay (500);} |
Для управления уровнем звука мы будем использовать другую технологию чтобы предотвратить ложные срабатывания. Для управления уровнем звука мы должны разместить левую руку на расстоянии примерно 15 см от датчика и если после этого мы ее будем двигать по направлению к датчику, то уровень звука будет уменьшаться, а если мы будем отдалять ее от датчика, то уровень звука будет увеличиваться. Соответственно, в данном случае через последовательный порт связи будут передаваться слова “Vup” или “Vdown”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//Lock Left - Control Mode if (distL>=13 && distL<=17) { delay(100); //Hand Hold Time calculate_distance(trigger1,echo1); distL =dist; if (distL>=13 && distL<=17) { Serial.println("Left Locked"); while(distL<=40) { calculate_distance(trigger1,echo1); distL =dist; if (distL<10) //рука приближается к датчику {Serial.println ("Vup"); delay (300);} if (distL>20) //рука отдаляется от датчика {Serial.println ("Vdown"); delay (300);} } } } |
Аналогичный подход мы будем использовать и для правой руки для управления направлением перемотки видео. Если мы будем приближать правую руку к датчику, то видео будет перематываться вперед, а если отдалять – то видео будет перематываться назад. Соответственно, в данном случае через последовательный порт связи будут передаваться слова “Rewind” или “Forward”.
Программирование Python
Программа на Python для этого проекта также достаточно проста. Нам всего лишь необходимо установить последовательную связь с платой Arduino и затем выполнять несколько простых функций клавиатуры. Но первым шагом на пути к этому должна стать установка модуля pyautogui для Python. Убедитесь в том, что вы его установили, иначе программа работать не будет.
Выполните следующую последовательность шагов чтобы установить pyautogui для windows. Если вы используете другие операционные системы, то шаги будут немного другими. Перед выполнением этих шагов убедитесь в том, что ваш компьютер имеет соединение с сетью интернет.
Шаг 1. Откройте окно ввода команд в Windows (режим командной строки) и смените в нем каталог на тот, куда установлен python. По умолчанию это должна быть следующая команда:
cd C:\Python27
Шаг 2. Внутри каталога с python выполните команду python –m pip install –upgrade pip чтобы произвести апгрейд вашего pip. Pip представляет собой инструмент в языке python, который позволяет нам легко устанавливать модули для python. Когда апгрейд этого модуля будет произведен (как показано на следующем рисунке) можно переходить к следующему шагу.
python –m pip install –upgrade pip
Шаг 3. Используйте команду “python –m pip install pyautogui” чтобы установить модуль pyautogui. Когда процесс будет завершен вы должны увидеть примерно следующую картину:
python –m pip install pyautogui
Теперь, когда мы установили модули pyautogui и pyserial (их установка рассмотрена в предыдущей статье на эту тематику), мы можем приступать к написанию программы на python. Полный код этой программы приведен в конце статьи, здесь же мы рассмотрим его наиболее важные фрагменты.
Сначала подключим все три необходимых нам модуля (pyautogui, serial python и time) в программу.
1 2 3 |
import serial #используется для последовательной связи import time #используется для организации задержек в программе import pyautogui |
Далее нам необходимо установить соединение с Arduino через последовательный (COM) порт. В нашем случае Arduino подсоединена к COM 18. Используйте диспетчер устройств Windows чтобы определить к какому COM порту подсоединена Arduino и на основании этого скорректируйте следующую строку.
1 2 |
ArduinoSerial = serial.Serial('com18',9600) #создаем объект порта последовательной связи с именем ArduinoSerial time.sleep(2) #ждем 2 секунды чтобы установилась последовательная связь |
Далее внутри бесконечного цикла while мы будем часто прослушивать COM порт, принимать поступающие по нему слова, сравнивать их с заранее определенными словами и на основании результатов сравнения выполнять соответствующие нажатия на клавиатуре.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
while 1: incoming = str (ArduinoSerial.readline()) #считываем данные с последовательного порта связи и печатаем их в виде строки print incoming if 'Play/Pause' in incoming: pyautogui.typewrite(['space'], 0.2) if 'Rewind' in incoming: pyautogui.hotkey('ctrl', 'left') if 'Forward' in incoming: pyautogui.hotkey('ctrl', 'right') if 'Vup' in incoming: pyautogui.hotkey('ctrl', 'down') if 'Vdown' in incoming: pyautogui.hotkey('ctrl', 'up') |
Как вы можете видеть из представленного фрагмента кода, чтобы нажать нужную клавишу мы используем, к примеру, команду вида “pyautogui.typewrite(['space'], 0.2)”, которая нажимает клавишу пробела на 0.2 секунды. Если вам нужно нажать сочетание горячих клавиш, например, ctrl+S, то в этом случае вам нужно использовать команду “pyautogui.hotkey('ctrl', 's')”.
Мы использовали приведенные сочетания клавиш поскольку они используются в плеере VLC. Аналогичный подход вы можете использовать для управления любой другой программой на вашем компьютере, в которой предусмотрено управление с помощью горячих клавиш.
Тестирование работы проекта
Сделайте все соединения, показанные на схеме, и загрузите приведенный в конце код программы в плату Arduino. Также запустите приведенный код программы на python на вашем компьютере.
Теперь во время воспроизведения видеозаписи на вашем компьютере с помощью плеера VLC вы может использовать ваши руки для управления этим плеером. Более подробно все эти процессы вы можете посмотреть в видео, приведенном в конце статьи.
Мы надеемся что вам понравился этот проект и вы на его основе сможете создать нужные вам проекты по управлению компьютером с помощью жестов рук.
Исходный код программы
Код программы для Arduino
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 |
const int trigger1 = 2; //Trigger pin первого датчика const int echo1 = 3; //Echo pin первого датчика const int trigger2 = 4; //Trigger pin второго датчика const int echo2 = 5;//Echo pin второго датчика long time_taken; int dist,distL,distR; void setup() { Serial.begin(9600); pinMode(trigger1, OUTPUT); pinMode(echo1, INPUT); pinMode(trigger2, OUTPUT); pinMode(echo2, INPUT); } /*###функция для определения расстояния###*/ void calculate_distance(int trigger, int echo) { digitalWrite(trigger, LOW); delayMicroseconds(2); digitalWrite(trigger, HIGH); delayMicroseconds(10); digitalWrite(trigger, LOW); time_taken = pulseIn(echo, HIGH); dist= time_taken*0.034/2; if (dist>50) dist = 50; } void loop() { //бесконечный цикл calculate_distance(trigger1,echo1); distL =dist; //расстояние для левого датчика calculate_distance(trigger2,echo2); distR =dist; //расстояние для правого датчика //раскомментируйте для отладки /*Serial.print("L="); Serial.println(distL); Serial.print("R="); Serial.println(distR); */ //Pause Modes -Hold if ((distL >40 && distR>40) && (distL <50 && distR<50)) //обнаруживаем обе руки {Serial.println("Play/Pause"); delay (500);} calculate_distance(trigger1,echo1); distL =dist; calculate_distance(trigger2,echo2); distR =dist; //Control Modes //Lock Left - Control Mode if (distL>=13 && distL<=17) { delay(100); //Hand Hold Time calculate_distance(trigger1,echo1); distL =dist; if (distL>=13 && distL<=17) { Serial.println("Left Locked"); while(distL<=40) { calculate_distance(trigger1,echo1); distL =dist; if (distL<10) //Hand pushed in {Serial.println ("Vup"); delay (300);} if (distL>20) //Hand pulled out {Serial.println ("Vdown"); delay (300);} } } } //Lock Right - Control Mode if (distR>=13 && distR<=17) { delay(100); //Hand Hold Time calculate_distance(trigger2,echo2); distR =dist; if (distR>=13 && distR<=17) { Serial.println("Right Locked"); while(distR<=40) { calculate_distance(trigger2,echo2); distR =dist; if (distR<10) //правая рука приближается к датчику {Serial.println ("Rewind"); delay (300);} if (distR>20) //правая рука отдаляется от датчика {Serial.println ("Forward"); delay (300);} } } } delay(200); } |
Код программы для Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import serial #подключаем библиотеку для работы с портом последовательной связи import time #библиотека для организации задержек в программе import pyautogui ArduinoSerial = serial.Serial('com18',9600) # создаем объект порта последовательной связи с именем ArduinoSerial time.sleep(2) #ждем 2 секунды чтобы установилась последовательная связь while 1: incoming = str (ArduinoSerial.readline()) # считываем данные с последовательного порта связи и печатаем их в виде строки print incoming if 'Play/Pause' in incoming: pyautogui.typewrite(['space'], 0.2) if 'Rewind' in incoming: pyautogui.hotkey('ctrl', 'left') if 'Forward' in incoming: pyautogui.hotkey('ctrl', 'right') if 'Vup' in incoming: pyautogui.hotkey('ctrl', 'down') if 'Vdown' in incoming: pyautogui.hotkey('ctrl', 'up') incoming = ""; |
Добрый вечер, делаю управление mp3 плеером через ардуино, все по вашей схеме. Когда запускаю python, срабатывает только первая в списке команда, те в вашем случае это пробел. Причем в окне питона видно что он получает все команды от ардуино, но почему то срабатывает в плеере только первая.
Здравствуйте, то есть у вас срабатывает только функция Play/Pause, а остальные не работают? А значения переменных в программе python вы можете проверить в процессе ее работы? Правильные ли она получает данные? И в вашем плеере используются те же самые горячие клавиши (ctrl + left, ctrl + right и т.д.) что и в представленной программе? Проверяли управление плеером с помощью горячих клавиш в обычном режиме его работы (то есть без нашей конструкции)?