В январе 2025 года я решил попробовать создать человекоподобного робота. Пока готова только одна рука без датчиков (рецепторов).

Роборука имеет человеческий скелет, связки и суставы, сделанные по анатомическому атласу, а также 42 мотора, установленные на роботе.
При создании робота я столкнулся с множеством проблем, в том числе касающихся ПО. О чем я и буду кратко говорить в данной статье. В конце статьи я расскажу об одном, как мне кажется, интересном эксперименте.
В качестве архитектуры я выбрал подход, где управление (мозг) будет находиться на компьютере в докер контейнерах на виртуальной машине, далее, данные через промежуточный сервис, находящийся на «железном» компьютере, по одному usb кабелю будут подаваться к контроллерам (платам), которые будут взаимодействовать с моторами (шаговыми двигателями).
Начну рассказ с кода контроллеров (плат).
Как известно, в человеческой руке 42 мышцы.
Так как робот построен на шаговых двигателях, то со стороны контроллера на каждый шаговый двигатель необходимо 4 управляющих контакта для униполярного двигателя и 3 для биполярного двигателя.
В atmega328P, чип, который я использую, всего имеет 21 выход, 2 из выходов зарезервированы для той информации, которая будет получаться со стороны компьютера.
Иными словами, к одному исполняющему контроллеру может быть подключено 4 или 5 шаговых двигателей. На практике я сделал унификацию, чтобы не путаться, и у меня всегда к одному контроллеру подключено по 4 мотора, подробнее я расскажу об этом в другой статье.
На одну руку мне потребовалось 11 исполняющих контроллеров.
Для того чтобы подключить их к компьютеру через 1 usb провод я сделал 2 уровня маршрутизаторов.
То есть архитектура будет выглядеть следующим образом:
Уровень 1. Это плата, подключенная к компьютеру. Тут лучше использовать готовую плату с драйвером на компьютере. В противном случае, могут быть проблемы с ядром операционной системы. [https://github.com/German200688/plats Softwhere_serial_balans_2403_final_2403/Softwhere_serial_balans_2403_final_2403.ino]
Уровень 2. Это промежуточная плата-контроллер, она пробрасывает сообщения от платы, подключенной к компьютеру, на «плату-драйвер». Промежуточную плату-контроллер можно сделать, как самостоятельно, так и можно купить. [https://github.com/German200688/plats Softwhere_serial_balans_2403_final_2403_copy_20240421094523/Softwhere_serial_balans_2403_final_2403_copy_20240421094523.ino]
Уровень 3. Это плата-драйвер, то есть, плата которая осуществляет непосредственную работу с шаговыми двигателями. Данную плату можно купить или сделать самостоятельно. [https://github.com/German200688/plats MySerial_sketch_Serial_ports_Test_final/MySerial_sketch_Serial_ports_Test_final.ino]

К сожалению, в силу ограничений статьи, в данной статье не представляется возможным рассмотреть особенности настройки фьюзов, протокола взаимодействия между платами и принципами его настройки, особенностями работы кода на контроллере, а также рассмотреть различия кода для униполярного и для биполярного шагового двигателя (в примере кода из github имеется код только для униполярного шагового двигателя).
Теперь я бы хотел остановиться на промежуточном сервисе, который осуществляет проброску сообщений из виртуалки на плату, подключенную к компьютеру.
В связи с тем, что в будущем, когда я буду писать уже анализаторную часть кода, я планирую развернуть несколько виртуалок, которые будут отправлять сообщения на платы и получать их с датчиков, я принял решение, на «железном» компьютере расположить сервис, который будет пробрасывать сообщения с датчиков (рецепторов) на анализатор (виртуалку), и с анализатора (виртуалки) через платы на моторы.
Как видно из кода, сервис достаточно прост [https://github.com/German200688/prodmozgwin], он берет сообщения из шины (kafka), переводит код в бинарный вид и пробрасывают сообщения дальше на плату.
Перед тем как рассказать об одном, из многочисленных экспериментов, которые я провел со своей роборукой, я бы хотел рассказать о коде, находящемся на виртуалке.
На текущий момент на виртуалке находится 2 модуля – шина (kafka) и микросервис, которым можно вызвать как группу мышц так и одну мышцу.
Наверно многие зададутся вопросом – зачем мне шина?
Если посмотреть работы по нейроанатомии [И.П. Бехтерева, Здоровый и больной мозг человека, СПб 1988], нейропсихологии [А.Р. Лурия, Высшие корковые функции человека, М 1962] и неврологии [Н.Н. Яхно, Болезни нервной системы Т2, М 2007], то у человека в мозгу находится почти логические 4 шины:
мост (область между продолговатым и средним мозгом, к нему, например, подключается мозжечок и получает данные о движениях человека);
таламус (область через которую взаимодействуют разные области мозга);
мозолистое тело (отвечает за взаимодействие между полушариями);
скорлупа базальных ганглиев (область, через которую лобная доля коры мозга посылает ответ на предложение других областей коры мозга).
Поэтому, делать ПО для робота, идентичного человеку, без шины не представляется возможным.
Что касается микросервиса [https://github.com/German200688/prodmozglin], то он может получать сообщения, как из других сервисов через кафку, так и через админку.
Он проверяет код движения в базе (я использовал postgress) и отправляет уже коды моторов с указанием скорости и направления движения на платы.
Сервис пока выполняет отладочную функцию для моторов и будет, после добавления датчиков (рецепторов), переписан как нейронная сеть без обучения (по типу робота-черепахи Эшби или аналогично поведения лягушки в эксперименте Сеченова где он убирал ей большие полушария мозга).
Изначально я планировал роботу отправлять код движения, например, согнуть пальцы, и он будет это делать.
Однако оказалось, что разные мышцы, и моторы могут перед началом движения быть в разных состояниях. Одна мышца может быть расслаблена, вторая напряжена, третья частично напряжена. Без этого учета любое движение может не получиться, так как палец может уйти в сторону, либо сухожилия или связки могут порваться. В человеческом теле эту проблему решает мозжечок, в котором хранятся состояния мышц, информация о последнем движении каждой мышцы, а также информация о натяжении всех сухожилий. То есть. мозжечок «подруливает» движения, помогая его выполнить корректно.
В роботостроении эту роль играет код на основе фильтров Калмана. Так как я пока не написал их, «подруливания» осуществляю я, через админку.
Иными словами, на текущий момент на практике применяется только админка, и через нее посылаются сразу коды мышц с указанием их направления и скорости. Системы кодировки мышц можно посмотреть в коде платы-драйвера.
Теперь давайте перейдем к эксперименту.
В начале поговорим о моторах/мышцах, используемых в данном движении.
Так как у меня каждый мотор идентичен человеческой мышце, я буду тут, как и в прошлой статье, писать не коды моторов, а названия мышц, которые идентичны тому или иному мотору.
Например, чтобы показать "класс" (большой палец вверх), необходимо использовать минимум 9 мышц:
Глубокий сгибатель пальцев - это сравнительно мощная мышца, которая идет от локтя по локтевой кости (кость, которая идет от локтя до кисти со стороны мизинца) до дистальных фаланг (кончиков пальцев) мизинца, безымянного, среднего и указательного пальцев. Когда она напрягается, сгибаются все 4 пальца сразу
·Поверхностный сгибатель пальцев - это сравнительно мощная мышца, которая идет от локтя также, как и глубокий сгибатель пальцев, главное отличие поверхностного сгибателя в том, что он крепится не к кончикам пальцев, а к середине мизинца, безымянного, среднего и указательного пальцев. Когда он напрягается, 4 пальца как-бы подтягиваются, обеспечивая более крепкое сжимание кулака и более плавное сгибание всех пальцев.
Червеобразная мышца мизинца находятся сразу под мизинцем, цепляется данная мышца к проксимальной фаланге (основанию) мизинца, с другой стороны она крепится к сухожилию глубокого сгибателя пальцев. То есть, она зависит также от поведения глубокого сгибателя пальцев.
Червеобразная мышца безымянного пальца идентична червеобразной мышце мизинца, с тем лишь отличием, что она, как видно из названия, крепится к безымянному пальцу
Червеобразная мышца среднего пальца идентична червеобразной мышце мизинца, с тем лишь отличием, что она, как видно из названия, крепится к среднему пальцу
Червеобразная мышца указательного пальца идентична червеобразной мышце мизинца, с тем лишь отличием, что она, как видно из названия, крепится к указательному пальцу
Длинный разгибатель большого пальца кисти - это сравнительно мощная мышца, которая идет от локтевой кости (кость, которая идет от локтя до кисти со стороны мизинца), плавно через лучевую кость (кость, которая идет от локтя до кисти со стороны большого пальца) и заканчивается на дистальной фаланге (под ногтем) большого пальца.
Короткий разгибатель большого пальца кисти, также, как и длинный разгибатель большого пальца идет косо от локтевой кости (кость, которая идет от локтя до кисти со стороны мизинца), однако он заканчивается на проксимальной фаланге (в середине) большого пальца.
Длинная мышца, отводящая большой палец кисти, идет, по сути, от локтя и заканчивается на тыльной стороне первой пястной кости, иными словами, данная мышца заканчивается на кости, лежащей на «мясистой части», находящейся под большим пальцем.
Теперь, когда мы обсудили какие мышцы задействованы в движении, давайте перейдем к самому движению.
Для того, чтобы совершить движение, необходимо в начале подтянуть кисть к себе, для этого используются глубокий сгибатель пальцев и поверхностный сгибатель пальцев, данные мышцы тянут сразу 4 пальца (мизинец, безымянный, средний и указательный) «на себя». Они формируют форму кулака.

Далее начинают сгибаться 4 червеобразные мышцы, которые, как мы говорили ранее, крепятся к основаниям мизинца, безымянного, среднего и указательного пальцев. Их задача полностью согнуть кулак. Как-бы подогнуть пальцы «под себя».

Последним этапом мы поднимаем большой палец. Для этого нам понадобится слаженная работа сразу 3-х мышц:
Длинная мышца, отводящая большой палец, которая поднимает большой палец, однако она также тянет его к «костяшке» указательного пальца, и если ее перенапрячь, то палец будет поднят не просто вверх, а вверх и в нашем случае назад.
Длинный разгибатель большого пальца кисти, которая будет поднимать кончик большого пальца и, если ее перетянуть, то палец будет поднят вверх неестественно.
И, конечно, короткий разгибатель большого пальца кисти – от этой мышцы ждать подвоха не стоит, она просто поднимет большой палец.


Перед тем, как подводить итоги, хочу обратить внимание, что все, что я написал, работает, когда глубокий и поверхностный сгибатели пальцев, идеально сбалансированно подтягивают пальцы. Если же окажется, что по той либо иной причине часть пальцев не подтягивается идеально, то во время напряжения мизинца, среднего, безымянного и указательного пальцев необходимо, помимо напряжения червеобразных мышц, также «жонглировать» напряжением глубокого сгибателя пальцев и поверхностного сгибателя пальцев.
Итого, мы видим из данной статьи, что даже простой показ знака «класс» является достаточно сложным движением, которое можно сделать правильным, но неестественным.