Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Перевод с сайта instructables.com, автор проекта: Matlek
В данной статье я подробно расскажу процесс изготовления «умной перчатки» и её светодиодной панели, предназначенных для повышения безопасности велосипедистов и других людей, путешествующих по дорогам. Сначала можно посмотреть небольшую демонстрацию работы:
Как это работает
В перчатке находится плата Arduino, собирающая данные с гироскопа и акселерометра. Код использует модель «крохотного машинного обучения» tinyML и распознаёт жесты: каждое движение руки анализируется и превращается в сигнал (рука наклоняется влево, вправо, вперёд, назад, и т.п.). Сигнал отправляется по Bluetooth (BLE) на другой микроконтроллер, к которому подсоединена светодиодная матрица (которую, например, можно закрепить на рюкзак). Сообразно полученному сигналу матрица выводит определённые последовательности символов – так, чтобы другие водители и велосипедисты могли понимать, что собирается сделать велосипедист (к примеру, это могут быть стрелки влево, вправо, или текст).
Происхождение проекта
Во-первых, я езжу на велосипеде на работу, и провожу в седле более часа в день (проезжая порядка 22 км). Это всегда интересно, однако я живу в одном из самых густонаселённых городов Франции, где часто происходят происшествия с участием автомобилей и велосипедистов. Также Марсель – худший во Франции город для велосипедистов — там отчаянно не хватает велодорожек. Поэтому данный проект посвящён как увеличению безопасности велосипедистов, так и попыткам обратить внимание городских властей на эту проблему.
Во-вторых, этот проект поможет всем участникам движения пообщаться и лучше понимать друг друга. С моей точки зрения большая часть неприятностей, происходящих на дороге, связана с тем, что некоторые участники движения неправильно поняли других, что в результате привело к испугу, а потом к агрессии. Мне хочется, чтобы такое устройство помогло участникам движения лучше понимать друг друга. Стрелки показывают направление, а ещё можно выводить текст по буквам (однако я целиком и полностью выступаю за вежливые и конструктивные надписи, во избежание конфликтов).
Почему «умная перчатка»?
Я начал работу над проектом зимой, и холодная погода мотивировала меня на то, чтобы закрепить устройство на перчатке. Но я быстро понял, что идея была не очень хорошей, потому что в нашей местности летом довольно жарко. Поэтому я решил, что лучше всего будет поместить устройство в коробку и закрепить на руке. Но поскольку я не знал, как назвать его по-другому, я решил оставить слово «перчатка» в названии.
«Умная» происходит от техники машинного обучения, которую я использовал в данном проекте.
Вдохновение
Проект в основном является смесью двух других проектов. Я не начинал работу с нуля, а пользовался их наработками, которые потом развивал далее. Вот, чем я вдохновлялся при разработке:
- распознавание жестов при помощи Arduino Nano 33 BLE SENSE.
- не какой-то конкретный проект, а концепция использования светодиодных матриц для велосипедистов. Таких проектов полно – некоторые используют рюкзаки с интегрированными панелями, другие просто предлагают готовую матрицу, которую можно поместить куда угодно. В любом случае, эти светодиодные матрицы управляются при помощи пульта дистанционного управления, а не распознавания жестов.
Комплектующие
Для 3D-печати – 3D-принтер или доступ к таковому.
Электроника
- Arduino Nano 33 BLE SENSE;
- Ещё один МИ с BLE (Arduino Nano 33 BLE, Arduino 33 BLE SENSE, Arduino nano 33 IOT, ESP32, и т.д.). Я решил использовать плату на ESP32.
- Светодиодная полоска (WS2812B). Я использовал 160 светодиодов, чтобы получить матрицу 20×8;
- Четырёхуровневый буфер с 3 В до 5 В: 74AHCT125.
- Конденсатор на 1000 мкФ.
- Переключатели SPST, 3 шт.
- Макетная плата.
- Провода.
- Батарейка 9 В.
- Внешний аккумулятор.
Другое
- Винты и гайки М3.
- Застёжка-липучка.
Шаг 1: подготовка (МИ, код)
Прочитав статью про Arduino и машинное обучение, я решил тоже попробовать. Поскольку в последнее время появилось несколько новых плат Arduino Nano, я сделал сравнительную табличку, чтобы сделать наилучший выбор перед покупкой.
Все платы интересные, однако для распознавания жестов я мог использовать только одну — Arduino Nano 33 BLE SENSE. Лишь у неё есть нужные датчики и поддержка Tensorflow Lite. Ещё один интересный момент – на платах Arduino Nano 33 IOT, BLE и BLE SENSE есть собственный Bluetooth, поэтому любую из них можно использовать на светодиодной матрице для приёма BLE сигналов.
Загруженный в плату код основан на множестве различных программ для Arduino, найденных мною при разработке. Поэтому перед началом работы я решил проверить их с найденными мною примерами.
Поиграемся с BLE
В данном проекте связь по Bluetooth имеет решающее значение, поскольку именно так сигнал отправляется с датчиков на светодиодную матрицу. До этого я никогда не связывал две платы Arduino по BLE. Поэтому я практиковался со следующими примерами из библиотеки ArduinoBLE:
- Скетч LedControl, используемый с платой Arduino Nano 33 BLE Sense и кнопкой с притягивающим резистором, подсоединённым к контакту 2. Пример опрашивает BLE-периферию, пока не найдёт сервис с UUID 19b10000-e8f2-537e-4f6c-d104768a1214. После его обнаружения и установления соединения он будет удалённо управлять периферийным светодиодом BLE по нажатию кнопки.
- Скетч для светодиода и Arduino Nano 33 IoT.
К сожалению, со скетчем для светодиода у меня возникло множество проблем – 3 платы «сломались» при его загрузке. Понятия не имею, в чём там была проблема, но я решил заменить плату Arduino на другой МИ с BLE – плату ESP32. С новой платой я использовал следующее:
- Скетч BLE_write из библиотеки BLE ESP32 ARDUINO. Я добавил несколько изменений, чтобы она работала с платой Arduino Nano 33 BLE SENSE. На шаге 10 вы сможете сравнить скетч BLE_write и скетч Smartglove_BLE_LED-matrix, который я написал и загрузил.
Поиграемся со встроенными RGB светодиодами
Вы знали, что у платы Arduino Nano 33 BLE SENSE есть встроенные RGB светодиоды? В данном проекте они пригодятся для проверки правильной работы распознавания жестов. Мы должны проверять, что сигнал был отправлен на светодиодную матрицу – однако поскольку панель, скорее всего, находится на спине велосипедиста, ему будет трудно понять, что распознавание жестов сработало и сигнал был отправлен.
Тут не было ничего сложного, я просто немного подправил пример Blink. Из кода видно, что красный светодиод находится на контакте 22, зелёный – на контакте 23, синий – на контакте 24. Входной сигнал LOW включает светодиод, HIGH – выключает.
const int LED_BUILTIN_RED = 22;
const int LED_BUILTIN_GREEN = 23;
const int LED_BUILTIN_BLUE = 24;
// функция setup запускается один раз после включения или перезагрузки платы
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN_RED, OUTPUT);
pinMode(LED_BUILTIN_GREEN, OUTPUT);
pinMode(LED_BUILTIN_BLUE, OUTPUT);
}
// функция loop повторяется вечно
void loop() {
digitalWrite(LED_BUILTIN_RED, LOW); // включить LED (HIGH – уровень напряжения)
delay(1000); // подождать секунду
digitalWrite(LED_BUILTIN_RED, HIGH); // выключить LED, понизив напряжение до LOW
delay(1000); // подождать секунду
digitalWrite(LED_BUILTIN_GREEN, LOW); // включить LED (HIGH – уровень напряжения)
delay(1000); // подождать секунду
digitalWrite(LED_BUILTIN_GREEN, HIGH); // выключить LED, понизив напряжение до LOW
delay(1000); // подождать секунду
digitalWrite(LED_BUILTIN_BLUE, LOW); // включить LED (HIGH – уровень напряжения)
delay(1000); // подождать секунду
digitalWrite(LED_BUILTIN_BLUE, HIGH); // выключить LED, понизив напряжение до LOW
delay(1000); // подождать секунду
}
Поиграемся с распознаванием жестов и tinyML
Наконец, я изучил руководство по использованию машинного обучения на Arduino, и попрактиковался с примером распознавания жестов. Пример делится на три основные части:
- Распознавание данных с программой IMU_Capture (и Arduino Nano 33 BLE sense);
- Обучение модели на записанных данных на google colab (на компьютере);
- Использование обученной модели на Arduino с IMU_Classifier для распознавания образов (опять на плате Arduino).
Шаг 2: перчатка 1/6 (электроника)
С шагов 2 по 7 я привожу одну и ту же схему, обозначая на ней шаги с тем, чтобы вам проще было понять процесс изготовления перчатки.
Схема электроники для перчатки очень простая:
- Плата Arduino.
- Батарейка на 9 В (я использую аккумулятор).
- Переключатель SPST.
Шаг 3: перчатка 2/6 – корпус
Корпус простой, и состоит всего из двух частей, распечатанных на 3D-принтере:
- В жёлтой части находится плата Arduino, аккумулятор и переключатель. Отверстия в корпусе позволяют перезаряжать батарею и перепрограммировать плату Arduino без необходимости разбирать корпус.
- Чёрная часть – это крышка, защищающая аккумулятор и плату.
На руку я креплю её полоской липучки.
Также я нарисовал логотип, который потом приклеил на крышку. Он обозначает велосипедиста, на которого смотрят сверху, и в нём есть три стрелочки – прямо, налево и направо. Четвёртая стрелочка отстоит от трёх остальных, потому что велосипеды не ездят назад.
Файлы
content.instructables.com/ORIG/FS2/L3M3/K9N93ZYW/FS2L3M3K9N93ZYW.stl
content.instructables.com/ORIG/F72/21NG/K9N93ZZG/F7221NGK9N93ZZG.stl
content.instructables.com/ORIG/FD3/NVS8/K9N93ZZI/FD3NVS8K9N93ZZI.stl
Шаг 4: перчатка 3/6: запись данных
После сборки устройства приходит время записи данных. Цель – записать каждый жест многократно. Я установил порог для гироскопа, и когда он выходит за это значение, Arduino начинает выводить записанные данные на монитор.
Я записал следующие жесты:
- Рука указывает влево (стандартный жест велосипедистов, обозначающий поворот налево).
- Торможение (жест пальцами, тянущимися к рычагу тормоза).
- Рука наклоняется назад.
- Рука наклоняется вперёд.
- Рука наклоняется влево.
- Рука наклоняется вправо.
Естественно, вы можете записывать свои жесты.
Для записи данных я написал программку, переключающую на светодиоде цвета после каждых 20 движений. Это помогало мне понимать, когда нужно переходить к другому жесту. Я подсоединил Arduino к компьютеру, открыл программу для отслеживания порта и положил ноутбук в рюкзак.
Записав все жесты, я перешёл к последнему этапу – скопировал данные, выведенные в программу, и сохранил их в формате csv.
content.instructables.com/ORIG/FC7/B0JT/K9UEA78V/FC7B0JTK9UEA78V.ino
Шаг 5: перчатка 4/6: обучение
Для обучения я использовал следующий пример, исправив в нём всего несколько строк. Перед обучением стоит проверить, что для каждого жеста у вас есть свой csv-файл, и данные в каждом файле относятся именно к этому жесту.
На сайте Google Colab по ссылке в разделе «Upload data» загрузите свои данные.
В разделе «Graph Data (optional)» добавьте имя одного из файлов.
filename = «Arm_left.csv»
Затем исправьте эту строчку, чтобы выводить только данные с гироскопа:
#index = range(1, len(df['aX']) + 1)
index = range(1, len(df['gX']) + 1)
Закомментируйте следующие строки – данные акселерометра мы не используем:
#plt.plot(index, df['aX'], 'g.', label='x', linestyle='solid', marker=',')
#plt.plot(index, df['aY'], 'b.', label='y', linestyle='solid', marker=',')
#plt.plot(index, df['aZ'], 'r.', label='z', linestyle='solid', marker=',')
#plt.title("Acceleration")
#plt.xlabel("Sample #")
#plt.ylabel("Acceleration (G)")
#plt.legend()
#plt.show()
В разделе «Parse and prepare the data» добавьте все названия файлов:
#GESTURES = ["punch", "flex",]
GESTURES = ["Arm_left", "Brake", "Hand_back-tilt", "Hand_front-tilt", "Hand_left-tilt", "Hand_right-tilt"]
Измените количество образцов на один жест, если меняли их в коде для Arduino:
#SAMPLES_PER_GESTURE = 119
SAMPLES_PER_GESTURE = 64
Осталось только закомментировать ускорение:
# normalize the input data, between 0 to 1:
# - acceleration is between: -4 to +4
# - gyroscope is between: -2000 to +2000
tensor += [
#(df['aX'][index] + 4) / 8,
#(df['aY'][index] + 4) / 8,
#(df['aZ'][index] + 4) / 8,
(df['gX'][index] + 2000) / 4000,
(df['gY'][index] + 2000) / 4000,
(df['gZ'][index] + 2000) / 4000
]
После прохода всей программы вы сможете скачать обученную модель.
Файлы
content.instructables.com/ORIG/F7A/GLEK/K9UEA8Z5/F7AGLEKK9UEA8Z5.csv
content.instructables.com/ORIG/FV1/853G/K9UEA8Z6/FV1853GK9UEA8Z6.csv
content.instructables.com/ORIG/FQH/OAZD/K9UEA8Z7/FQHOAZDK9UEA8Z7.csv
content.instructables.com/ORIG/F7N/P7AG/K9UEA8Z9/F7NP7AGK9UEA8Z9.csv
content.instructables.com/ORIG/FD4/WZRM/K9UEA8ZA/FD4WZRMK9UEA8ZA.csv
content.instructables.com/ORIG/F6W/7SO2/K9UEA8ZB/F6W7SO2K9UEA8ZB.csv
Шаг 6: перчатка 5/6: код для Arduino
Итоговый мой код для умной перчатки – это смесь следующих программ:
- пример «LED» из библиотеки «ArduinoBLE» (Peripheral>LED).
- «IMU_Classifier» отсюда.
Подробно тут я распространяться о них не буду, просто рекомендую прочитать оригинальные программы, чтобы лучше понимать происходящее.
Добавьте свою модель в код, и её можно будет испытывать!
Файлы
content.instructables.com/ORIG/F9N/4SBK/K9UEA98M/F9N4SBKK9UEA98M.h
content.instructables.com/ORIG/FKZ/ODO9/KB52VXZK/FKZODO9KB52VXZK.ino
Шаг 7: перчатка 6/6: испытания
Как видно из видеоролика, светодиод загорается по-разному в зависимости от распознанного жеста:
Шаг 8: светодиодная матрица 1/4: электроника
Как я уже упоминал, при закачке скетча из библиотеки ArduinoBLE для светодиода на Arduino Nano 33 BLE SENSE я столкнулся с некоторыми проблемами. Поэтому я решил вместо этой платы использовать ESP32. Поэтому на приведённых фотографиях вы можете увидеть обе платы.
Поскольку обе платы, Arduino Nano 33 BLE SENSE и ESP32, работают с логикой на 3,3 В, я добавил четырёхуровневый буфер с 3 В до 5 В (74AHCT125), как рекомендуется в инструкции от Adafruit.
Также я добавил конденсатор на 100 мкФ для защиты светодиода от резких перепадов напряжения.
Всю схему я собрал на макетной плате.
Видно, что я задействовал оба разъёма внешнего источника питания, поскольку испугался, что светодиодной матрице потребуется слишком большой ток. Поэтому матрица и МИ питаются от разных разъёмов внешнего источника питания.
Шаг 9: светодиодная матрица 2/4: корпус
Мне нужен был сборный корпус для светодиодной матрицы. Поэтому он состоит из нескольких частей (а ещё потому, что мой 3D-принтер очень крохотный), и я предусмотрел в них отверстия для болтов.
Для подсоединения панели я снова воспользовался липучкой.
Файлы
content.instructables.com/ORIG/FH6/TB4H/K9N93ZZJ/FH6TB4HK9N93ZZJ.stl
content.instructables.com/ORIG/FK3/BZPC/K9N93ZZK/FK3BZPCK9N93ZZK.stl
content.instructables.com/ORIG/FMU/ZRTY/K9N93ZZL/FMUZRTYK9N93ZZL.stl
content.instructables.com/ORIG/F38/BF1P/K9N93ZZM/F38BF1PK9N93ZZM.stl
content.instructables.com/ORIG/FJC/DQMY/K9N93ZZN/FJCDQMYK9N93ZZN.stl
content.instructables.com/ORIG/F43/ELQV/K9N93ZZQ/F43ELQVK9N93ZZQ.stl
content.instructables.com/ORIG/FJE/C5FG/K9N93ZZR/FJEC5FGK9N93ZZR.stl
content.instructables.com/ORIG/F55/1X43/K9N93ZZS/F551X43K9N93ZZS.stl
Шаг 10: светодиодная матрица 3/4: код для Arduino
Итоговый код – смесь следующих кодов (и их модификация):
- Пример BLE_Write из библиотеки BLE ESP32 ARDUINO.
- Пример MatrixGFXDemo64 из библиотеки FastLED NeoMatrix.
Подробно тут я распространяться о них не буду, просто рекомендую прочитать оригинальные программы, чтобы лучше понимать происходящее.
content.instructables.com/ORIG/FIR/RETZ/KB52VXP4/FIRRETZKB52VXP4.ino
Шаг 11: светодиодная матрица 4/4: испытания
Настало время всё проверить! После распознавания каждого жеста на светодиодную матрицу отправляется сигнал, и она показывает определённый узор. Видно, что на перчатке светодиоды зажигаются соответственно распознанному жесту.
Шаг 12: итоговые испытания и заключение
Вот как это выглядит вживую:
Я очень доволен получившимся устройством. Благодаря проекту я гораздо увереннее чувствую себя с tinyML и BLE. С тех пор я купил ещё Arduino Nano 33 IOT, и сейчас занимаюсь весьма интересным проектом, о котором напишу позже. Что бы я изменил во второй версии описанного мною устройства:
- Крышка для «перчатки». Сейчас она держится на корпусе только за счёт того, что туго надевается. Однако как-то во время поездки я задел что-то рукой, крышка соскочила и разбилась. В следующей версии прикручу её винтами.
- Корпус для светодиодной матрицы. Я почти сразу понял, что в моём корпусе отсутствует быстрый доступ к USB МИ. А мне хотелось бы иметь доступ, чтобы отлаживать код или менять его. Также без раскручивания корпуса нельзя зарядить внешний источник питания.
- Больше данных для обучения. Иногда некоторые из жестов не распознаются, а иногда распознаются ошибочно. Думаю, не хватает данных (всего 20 движений для каждого жеста). Больше движений – лучше модель, меньше ошибок.
На завершение проекта и написание этого текста у меня ушло несколько месяцев. Если что-то неясно, или какого-то файла не хватает, пишите в комментариях к оригинальной статье.