Начиная с физических переключателей способ нашего взаимодействия с электронными устройствами значительно изменился за эти годы. Мы перешли от переключателей к сенсорным экранам, и исследования в этом направлении продолжают расширять границы. Сегодня у нас есть технологии распознавания жестов, с помощью которых мы можем управлять машинами и получать к ним доступ без физического соприкосновения с ними. Хотя это может показаться чем-то из ряда вон выходящим, но испытать распознавание жестов вы можете самостоятельно, в домашних условиях! И в этой статье мы расскажем как это можно сделать.
Для знакомства с технологией распознавания жестов мы выбрали модуль распознавания жестов PAJ7620. Этот модуль выделяется тем, что он поставляется с девятью предварительно запрограммированными распознаваниями жестов. Многие другие датчики жестов на рынке либо распознают меньше жестов, либо предоставляют только необработанные данные, что затрудняет взаимодействие с ними. PAJ7620 упрощает этот процесс, что делает его идеальным выбором для нашего исследования.
Ранее на нашем сайте мы рассматривали следующие проекты, связанные с распознаванием жестов:
- управление компьютером с помощью жестов рук и Arduino;
- управляемая жестами роботизированная рука на Arduino Nano;
- распознавание жестов с помощью Raspberry Pi и OpenCV;
- управляемый жестами видеоплеер на Raspberry Pi и MediaPipe;
- умный дом на ESP12 с управлением жестами и компьютерном зрении.
Необходимые компоненты
- Плата Arduino UNO (купить на AliExpress).
- Модуль распознавания жестов PAJ7620 (купить на AliExpress).
- ЖК дисплей 16х2 с модулем I2C (купить на AliExpress).
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Датчик распознавания жестов PAJ7620
Датчик жестов PAJ7620 — универсальный и удобный модуль, идеально подходящий для любителей электроники. В основе этого модуля лежит чип PAC720, который объединяет возможности распознавания жестов с общим интерфейсом I2C, создавая комплексную систему датчиков анализа изображений. Этот усовершенствованный модуль может распознавать различные жесты человеческих рук, что делает его крайне полезным для интерактивных приложений.
В частности, он может распознавать девять различных жестов: движение вверх, вниз, влево, вправо, вперед, назад, по часовой стрелке, против часовой стрелки и махание рукой. Эти возможности позволяют использовать широкий спектр приложений, от простых улучшений проектов до сложных интерактивных систем. Простота использования и широкая функциональность делают датчик жестов PAJ7620 ценным дополнением к любому набору электронных инструментов.
На изображении выше вы можете видеть переднюю и заднюю стороны модуля распознавания жестов PAJ7620. Это небольшой, простой для понимания модуль во всех отношениях. Чтобы лучше ознакомиться с этим модулем, давайте кратко узнаем его характеристики!
Спецификация модуля
Сейчас мы говорим о модуле PAJ7620, но на самом деле его полное название — PAJ7620U2. Это важно знать, если вы думаете об использовании всех возможностей этой интегральной схемы. Давайте кратко рассмотрим характеристики этого модуля.
Параметр | Символ | Пределы | Пределы | Пределы | Единица измерения |
Мин. | Типичный | Макс. | |||
Напряжение питания | Vcc | 3.3 | 5 | 6 | В |
Напряжение на контакте ввода-вывода | Vio | 1.8 | — | 3.3 | В |
Ток питания | Ic | — | 370 | 800 | мА |
Диапазон обнаружения жестов | Dop | 5 | — | 15 | см |
Рабочая Температура | Top | -40 | — | 85 | °С |
Температура хранения | Tstorage | -40 | — | 125 | °С |
Этот модуль совместим с любым микроконтроллером, имеющим аппаратную поддержку интерфейса I2C. Единственное, что нужно помнить, это уровень напряжения на контакте ввода-вывода. Этот модуль принимает только напряжение до 3,3 В. Если вы используете микроконтроллер на 5 В или что-то выше, я предлагаю использовать преобразователь логического уровня между линиями данных. Кроме того, на рынке доступно множество модулей сдвига уровня, с которыми вы можете ознакомиться в Интернете.
Еще одна интересная вещь, на которую стоит обратить внимание, это то, что у него довольно большой диапазон срабатывания, который составляет около 20 см, но наиболее точный диапазон, указанный производителем, составляет около 15 см. Теперь давайте немного углубимся в технические детали датчика и его распиновку.
Распиновка модуля распознавания жестов PAJ7620
Поскольку это модуль, то здесь нет особой сложности. Всего 5 контактов, которые действительно легко понять. Его распиновка показана на следующем рисунке.
Назначение его контактов описано в следующей таблице.
Номер контакта | Имя контакта | Описание |
1 | VCC | напряжение питания |
2 | GND | земля (общий провод) |
3 | SCL | линия синхронизации I2C |
4 | SDA | линия передачи данных I2C |
5 | INT | контакт прерывания |
Начиная с Vcc, это входной контакт напряжения, который поддерживает до 6 В благодаря своим внутренним линейным регуляторам напряжения. Тем не менее, для оптимальной долгосрочной производительности рекомендуется придерживаться напряжения 5 В. Далее идут выводы SCL и SDA, которые являются выводами связи интерфейса I2C. Интересный факт заключается в том, что PAJ7620 также поддерживает связь по интерфейсу SPI, но эти контакты не выведены наружу модуля. Так что, если вы предпочитаете использовать SPI, проверьте другие возможные модули или сделайте свою собственную печатную плату. Просто!
Далее идет вывод прерывания. Я обнаружил, что он отвечает за индикацию распознавания жеста. Обычно он высокий, а в случае обнаружения жеста становится низким, что очень удобно с точки зрения написания кода программы. Считать данные из регистра можно только после считывания этого сигнала, что снижает количество ложных запросов к микросхеме PAJ7620.
Кратко основные принципы взаимодействия с модулем PAJ7620 представлены на следующей анимированной картинке.
Вы можете видеть, что низкий сигнал доступен только в течение короткого времени, потому что в нашем коде мы уже получили код распознанного жеста, поэтому флаг прерывания был очищен.
Схема модуля распознавания жестов PAJ7620
Ниже вы можете увидеть фактическое изображение модуля PAJ7620 с его обозначенными основными блоками. Он состоит из следующих компонентов: сама микросхема PAJ7620, основная схема регулирования мощности, схема регулирования мощности светодиодов и сеть подтягивающих резисторов.
Схема силовой части модуля PAJ7620 представлена на следующем рисунке.
На представленном рисунке вы можете видеть силовую секцию, которая отвечает за питание отдельных компонентов модуля PAJ7620. Как вы знаете, присутствуют три отдельные секции, которым требуются три отдельных напряжения: VBUS (1,8 В — 3,3 В), VDD (2,8 В — 3,6 В) и VLED (3,0 В — 4,2 В). VDD — это основной источник питания, а VBUS — это источник питания шины. Оба они имеют общий LDO, который обеспечивает линейный выход 3,3 В из-за их низкого энергопотребления. VLED питается от другого отдельного LDO, который также является линейным стабилизатором выхода 3,3 В.
На следующем рисунке мы можете увидеть интерфейсы модуля PAJ7620.
Изображение, которое вы видите выше, показывает соединения модуля PAJ7620. Вы можете легко это понять, так как это довольно просто. Здесь не нужны никакие дополнительные компоненты. Эти источники питания были напрямую подключены к соответствующим контактам микросхемы. Одна вещь, которую вам нужно знать, это то, что контакты SPI удерживаются как контакты без соединения — они не были выведены наружу.
Наконец, на следующем рисунке вы можете видеть подтягивающие резисторы, подключенные к входам/выходам модуля PAJ7620, чтобы обеспечить стабильное логическое состояние для выводов.
Как работает модуль распознавания жестов PAJ7620?
Разделим этот раздел на две части, сначала рассмотрим внутреннюю часть, а затем перейдем к внешней.
Внутренняя часть модуля PAJ7620
Внутренняя часть модуля — не самое запутанное. Это просто камера, которая творит эту магию. Внутри есть камера 60×60 пикселей вместе с ИК-светодиодом и встроенным процессором. Так что, да, движения захватываются камерой и передаются в блок извлечения объекта и распознавания жестов, а распознанный жест сохраняется в банке регистров и считывается через аппаратные контакты I2C.
Если вы хотите защитить датчик от внешней среды, пожалуйста, обратитесь к официальному техническому описанию модуля paj7620 для получения информации о процедурах, которые для этого необходимо произвести.
Внешняя обработка данных модулем PAJ7620
Внешняя работа модуля также достаточно проста. В диапазоне от 5 до 15 см от датчика с углом обзора 60 градусов, если мы покажем любой из следующих жестов, он будет распознан, и мы сможем мгновенно получить результат через интерфейс I2C.
На представленном рисунке вы можете видеть знаки жестов рук, которые может распознавать модуль. Позвольте мне раскрыть некоторые особенности здесь: вы даже можете обнаружить больше жестов, буквально больше 9, просто объединив основные жесты. И мы можем делать такую функциональность в обычном режиме модуля. Если вы предпочитаете использовать более высокую частоту кадров, которая известна как игровой режим, вы можете также это использовать. Чтобы узнать больше об этих экспериментах, вы можете использовать следующую ссылку, которая перенаправит вас на DFRobot_PAJ7620U2. Там есть примеры программ, которые применяют концепцию, которую мы рассмотрели в этом разделе статьи.
Схема проекта
Для простоты понимания работы схемы мы используем ЖК-дисплей с поддержкой I2C. Но вы можете использовать любой другой удобный вам дисплей или ограничиться выводом информации в окно монитора последовательной связи.
Схема подключения модуля распознавания жестов PAJ7620 к плате Arduino представлена на следующем рисунке.
В данной схеме мы использовали одинаковую цветовую кодировку проводов для всей этой статьи, например, КРАСНЫЙ для 5 В или положительного источника питания, ЧЕРНЫЙ для заземления или отрицательного источника питания, ЗЕЛЕНЫЙ для контакта последовательных данных (SDA) интерфейса I2C и СИНИЙ для контакта синхронизации (SCL) интерфейса I2C.
На представленной схеме вы можете заметить, что мы использовали резисторы для соединения выводов данных Arduino с модулем PAJ7620. И у этого решения есть определенная цель. Фактическое максимальное пороговое напряжение контактов ввода-вывода модуля PAJ7620, которое они могут выдержать, составляет 3,3 В. Поэтому, поскольку мы собираемся соединить модуль PAJ7620 с 5-вольтовым микроконтроллером (платой), резисторы используются для ограничения тока в линиях данных. Это не идеальное решение, но в качестве хобби-проекта этот трюк пригодится. Если вы хотите использовать модуль PAJ7620 в каком-нибудь коммерческом продукте, я предлагаю использовать двунаправленный модуль сдвига уровней, доступный на рынке.
Собранная конструкция проекта представлена на следующем рисунке.
Объяснение работы кода
Поскольку мы живем в эпоху Arduino, нам не нужно беспокоиться о сопряжении этого датчика PAJ7620 с платой Arduino. У нас есть множество готовых библиотек для этого. Среди них я выбрал библиотеку, созданную DFRobot, которая называется DFRobot_PAJ7620U2. Вы можете установить библиотеку paj7620 , клонировав ее непосредственно в папку Library вашего Arduino, либо установить ее любым другим удобным вам способом.
Также мы можем выполнить поиск в менеджере библиотек Arduino IDE, просто введя PAJ7620 в его поле поиска, и потом установить эту библиотеку из результатов поиска.
Но поскольку в наш проект мы также добавили ЖК-дисплей, подключенный по интерфейсу I2C, давайте добавим и библиотеку для работы с ним. Вы можете добавить ее по этой ссылке: Arduino-LiquidCrystal-I2C-library.
Первым делом в коде программы подключим необходимые библиотеки.
1 2 3 |
#include <DFRobot_PAJ7620U2.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> |
Чтобы улучшить визуализацию нашего проекта, мы добавим в программу несколько пользовательских символов. Обратите внимание, что вы можете использовать только 8 пользовательских символов одновременно.
1 2 3 4 5 6 7 8 9 10 |
uint8_t rightChar[8] = { B00000, B00000, B00100, B00010, B11111, B00010, B00100, B00000 }; uint8_t leftChar[8] = { B00000, B00000, B00100, B01000, B11111, B01000, B00100, B00000 }; uint8_t upChar[8] = { B00000, B00000, B00100, B01110, B10101, B00100, B00100, B00000 }; uint8_t downChar[8] = { B00000, B00100, B00100, B10101, B01110, B00100, B00000, B00000 }; uint8_t forwardChar[8] = { B00100, B10101, B01110, B00100, B00000, B00000, B01110, B01110 }; uint8_t backwardChar[8] = { B00100, B01110, B10101, B00100, B00000, B00000, B01110, B01110 }; uint8_t clockwiseChar[8] = { B01110, B10001, B00001, B00001, B01010, B01100, B01110, B00000 }; uint8_t antiClockwiseChar[8] = { B00000, B01110, B01100, B01010, B00001, B00001, B10001, B01110 }; uint8_t waveRightChar[8] = { B00111, B00011, B00101, B01000, B00010, B10100, B11000, B11100 }; uint8_t waveLeftChar[8] = { B11100, B11000, B10100, B00010, B01000, B00101, B00011, B00111 }; |
Далее, в функции void setup(), мы собираемся соединить два аппаратных компонента по интерфейсу I2C. Начнем этот процесс мы функцией lcd.begin(), а продолжим — функцией paj.begin(). Исчерпывающее руководство по работе с интерфейсом I2C в платах Arduino вы можете найти в этой статье.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
void setup() { Serial.begin(115200); delay(300); lcd.begin(); lcd.createChar(1, waveRightChar); lcd.createChar(2, waveLeftChar); lcd.createChar(3, upChar); lcd.createChar(4, downChar); lcd.createChar(5, forwardChar); lcd.createChar(6, backwardChar); lcd.createChar(7, clockwiseChar); lcd.createChar(8, antiClockwiseChar); Serial.println("Gesture recognition system base on PAJ7620U2"); while (paj.begin() != 0) { Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?"); delay(500); } Serial.println("PAJ7620U2init completed, start to test the gesture recognition function"); paj.setGestureHighRate(false); } |
В приведенном фрагменте кода функция paj.begin() используется для обеспечения правильного соединения между модулем PAJ7620 и платой Arduino Uno. Как только эта функция возвращает true
, цикл while
завершается и выполняются следующие функции.
1 |
paj.setGestureHighRate(false); |
Если в функцию paj.setGestureHighRate() передадим в качестве параметра true, то мы включим более высокую скорость чтения, также известную как игровой режим модуля PAJ7620. Следует отметить, что если вы используете игровой режим, вы можете использовать предварительно встроенные 9 жестовых знаков, но не дополнительные четыре расширенных жеста.
Далее у нас идет функция void loop() — основной цикл программы. В нем функция paj.getGesture() используется для получения шестнадцатеричного кода последнего распознанного жеста из банка регистров PAJ7620 через интерфейс I2C. Если полученные данные равны 0, жест не считывается; в противном случае, в случае любого значения, мы можем предположить, что жест распознан. После этого он сравнивается с предопределенными переменными в библиотеке PAJ7620, которые вы можете увидеть на рисунке после приведенного фрагмента кода.
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 |
void loop() { DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture(); if (gesture != paj.eGestureNone) { lcd.clear(); String description = paj.gestureDescription(gesture); Serial.println("--------------Gesture Recognition System---------------------------"); Serial.print("gesture code = "); Serial.println(gesture); Serial.print("gesture description = "); Serial.println(description); Serial.println(); switch (gesture) { case 1: lcd.setCursor(3, 0); lcd.write(byte(1)); lcd.print(" "); lcd.print("RIGHT"); lcd.print(" "); lcd.write(byte(1)); break; // … program for other conditions are used default: lcd.print("New Gesture"); break; } } } |
Чтобы не путаться, я преобразовал шестнадцатеричные числа в десятичные. Вот они:
— None = 0
— Right = 1
— Left = 2
— Up = 4
— Down = 8
— Forward = 16
— Backward = 32
— Clockwise = 64
— AntiClockwise = 128
— Wave = 256
— WaveSlowlyDisorder = 512
— WaveSlowlyLeftRight = 3
— WaveSlowlyUpDown = 12
— WaveSlowlyForwardBackward = 48
— All = 255
Далее полученные значения передаются в switch case для выполнения соответствующей функции. В нашем случае мы изменяем отображаемые символы в соответствии с полученным распознанным кодом жеста. Вот и все, на этом написание кода завершено. Полный код программы вы можете найти ниже.
Тестирование работы проекта
После загрузки кода в плату Arduino наш проект готов к распознаванию жестов и отображению их на экране. Неудивительно, ниже вы можете увидеть GIF-файлы рабочей демонстрации основных распознаваемых жестов, а именно: Вправо, Влево, Вверх, Вниз, Вперед, Назад, По часовой стрелке, Против часовой стрелки и Волна.
После этого вы можете увидеть распознавание расширенных жестов, а именно: медленное помахивание рукой в знак беспорядка, медленное помахивание рукой влево-вправо, медленное помахивание рукой вверх-вниз и медленное помахивание рукой вперед-назад, на приведенной ниже GIF-анимации.
Здесь все просто. Поскольку я установил модуль PAJ7620 на низкую частоту дискретизации, мне удалось распознать 13 типов жестов. Как я уже упоминал, если вам нужна высокоскоростная дискретизация, вы можете получить только 9 жестов, чего может быть достаточно в некоторых случаях.
Исходный код программы
Вот ссылка на репозиторий GitHub, где вы можете найти полный код программы и схемы, использованные в этой статье.
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
#include <DFRobot_PAJ7620U2.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> // Set the LCD address to 0x27 for a 16 chars and 2 line display LiquidCrystal_I2C lcd(0x27, 16, 2); uint8_t rightChar[8] = { B00000, B00000, B00100, B00010, B11111, B00010, B00100, B00000 }; uint8_t leftChar[8] = { B00000, B00000, B00100, B01000, B11111, B01000, B00100, B00000 }; uint8_t upChar[8] = { B00000, B00000, B00100, B01110, B10101, B00100, B00100, B00000 }; uint8_t downChar[8] = { B00000, B00100, B00100, B10101, B01110, B00100, B00000, B00000 }; uint8_t forwardChar[8] = { B00100, B10101, B01110, B00100, B00000, B00000, B01110, B01110 }; uint8_t backwardChar[8] = { B00100, B01110, B10101, B00100, B00000, B00000, B01110, B01110 }; uint8_t clockwiseChar[8] = { B01110, B10001, B00001, B00001, B01010, B01100, B01110, B00000 }; uint8_t antiClockwiseChar[8] = { B00000, B01110, B01100, B01010, B00001, B00001, B10001, B01110 }; uint8_t waveRightChar[8] = { B00111, B00011, B00101, B01000, B00010, B10100, B11000, B11100 }; uint8_t waveLeftChar[8] = { B11100, B11000, B10100, B00010, B01000, B00101, B00011, B00111 }; DFRobot_PAJ7620U2 paj; void setup() { Serial.begin(115200); delay(300); lcd.begin(); lcd.createChar(1, waveRightChar); lcd.createChar(2, waveLeftChar); lcd.createChar(3, upChar); lcd.createChar(4, downChar); lcd.createChar(5, forwardChar); lcd.createChar(6, backwardChar); lcd.createChar(7, clockwiseChar); lcd.createChar(8, antiClockwiseChar); Serial.println("Gesture recognition system base on PAJ7620U2"); while (paj.begin() != 0) { Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?"); delay(500); } Serial.println("PAJ7620U2init completed, start to test the gesture recognition function"); paj.setGestureHighRate(false); lcd.backlight(); lcd.setCursor(4, 0); lcd.print("Ready to"); lcd.setCursor(3, 1); lcd.print("Recognize"); } void loop() { DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture(); if (gesture != paj.eGestureNone) { lcd.clear(); String description = paj.gestureDescription(gesture); Serial.println("--------------Gesture Recognition System---------------------------"); Serial.print("gesture code = "); Serial.println(gesture); Serial.print("gesture description = "); Serial.println(description); Serial.println(); switch (gesture) { case 1: lcd.setCursor(3, 0); lcd.write(byte(1)); lcd.print(" "); lcd.print("RIGHT"); lcd.print(" "); lcd.write(byte(1)); break; case 2: lcd.setCursor(4, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("LEFT"); lcd.print(" "); lcd.write(byte(2)); break; case 4: lcd.setCursor(5, 0); lcd.write(byte(3)); lcd.print(" "); lcd.print("UP"); lcd.print(" "); lcd.write(byte(3)); break; case 8: lcd.setCursor(4, 0); lcd.write(byte(4)); lcd.print(" "); lcd.print("DOWN"); lcd.print(" "); lcd.write(byte(4)); break; case 16: lcd.setCursor(2, 0); lcd.write(byte(5)); lcd.print(" "); lcd.print("FORWARD"); lcd.print(" "); lcd.write(byte(5)); break; case 32: lcd.setCursor(2, 0); lcd.write(byte(6)); lcd.print(" "); lcd.print("BACKWARD"); lcd.print(" "); lcd.write(byte(6)); break; case 64: lcd.setCursor(2, 0); lcd.write(byte(7)); lcd.print(" "); lcd.print("CLOCKWISE"); lcd.print(" "); lcd.write(byte(7)); break; case 128: lcd.setCursor(4, 0); lcd.write(byte(8)); lcd.print(" "); lcd.print(" "); lcd.print(" "); lcd.write(byte(8)); lcd.setCursor(1, 1); lcd.print("ANTI-CLOCKWISE"); break; case 256: lcd.setCursor(4, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("WAVE"); lcd.print(" "); lcd.write(byte(1)); break; case 512: lcd.setCursor(2, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("SLOW WAVE"); lcd.print(" "); lcd.write(byte(1)); lcd.setCursor(4, 1); lcd.print("DISORDER"); break; case 3: lcd.setCursor(2, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("SLOW WAVE"); lcd.print(" "); lcd.write(byte(1)); lcd.setCursor(3, 1); lcd.print("LEFT-RIGHT"); break; case 12: lcd.setCursor(2, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("SLOW WAVE"); lcd.print(" "); lcd.write(byte(1)); lcd.setCursor(4, 1); lcd.print("UP-DOWN"); break; case 48: lcd.setCursor(2, 0); lcd.write(byte(2)); lcd.print(" "); lcd.print("SLOW WAVE"); lcd.print(" "); lcd.write(byte(1)); lcd.setCursor(1, 1); lcd.print("FORWARD-BACKWARD"); break; default: lcd.print("New Gesture"); break; } } } |