+7-960-0655211 (Билайн)
+7-987-4207734 (МТС)
интернет-магазин
доставка по России и СНГ
работаем с 2010 года

Робот "Ходок" фирмы Gekko - реализация на Arduino

ГлавнаяИнформацияСтатьи

Робот "Ходок" фирмы Gekko - реализация на Arduino



Введение.

В этой статье вы сможете найти детальное описание процесса сборки робота «Ходок», являющегося типичным представителем робототехнической машины. Его механическая часть реализована из следующих компонентов фирмы Gekko:

· Кронштейн Многоцелевой для серво Gekko ASB-04 (пара) - 3 пары

· Кронштейн "П" для серво Gekko ASB-09 (пара) - 3 пары

· Кронштейн "Г" для серво Gekko ASB-06 (пара) - 1 пара

· Кронштейн Швеллер для серво Gekko ASB-53 - 1 шт

· Кронштейн Стопа робота Gekko ARF-01 (пара) - 1 пара

Эти компоненты вы можете приобрести либо все вместе Двуногий робот Gekko "Ходок" (конструктор без электроники), либо по отдельности в этом разделе сайта.  При покупке всего механического комплекта робота вы так же получите:

· Сервопривод Feetech FS5103B или Сервопривод TowerPro MG995 (в зависимости от комплектации): - 6 шт

· Набор из 4 качалок для серво - 6 шт

Эти же компоненты вы так же сможете купить, отдельно перейдя по ссылка указанным в их названии, я же из соображений «наличия других компонентов» брал запчасти отдельно и в моем роботе установлены сервоприводы фирмы HobbyKing (НК151138), которые, к слову сказать, существенно хуже по всем показателям, чем рекомендованные Сервопривод Feetech FS5103B, как по показателям силовым, так и по точности отработки, так и по разбросу параметров среди экземпляров одного типа. Но это не говорит о том, что при повторении проекта, необходимо покупать дешевые китайские сервы, как у меня в проекте. Напротив, если сгодились мои, то более качественные сервоприводы только упростят процесс отладки.

Электронная часть робота, реализованная из следующих компонентов:

· Контроллер DFRduino Nano v3 на ATmega328 + FT232RL (arduino) - 1 шт

· Плата расширения ввода/вывода DFRobot v1 для Arduino Nano - 1 шт

· Держатель батареи 4-AA закрытый с выключателем - 1 шт

· Датчик дальности Sharp GP2Y0A21YK0F 10-80см (аналоговый) - 1 шт

· Аккумулятор AA емкость 2500mA/H(китайские взяты в ларьке) - 4 шт

Так же для установки датчика дальности Sharp, использованного в проекте необходимо приобрести еще один элемент механической части конструкции не входящий в состав стандартного комплекта робота «Ходок» фирмы Gekko, но произведенный этим же поставщиком, а именно:

· Держатель датчика Gekko ASH-01 - 1 шт

Как видите, все кроме аккумуляторов (которые вполне можно заменить любыми батарейками типа АА), можно приобрести в разделах сайта РОБОТОТЕХНИКА на страницах, которого, вы читаете данную статью, и который, непосредственно обладает правом на её размещение. Так же вы можете использовать любые другие компоненты, которые на ваш взгляд, лучше подходят для целей реализации данного проекта, но в этом случае возможные некоторые расхождения между моим описанием и реальной картиной вашего творческого процесса;)

1) Описание функционала робота «Ходок».

Робот «Ходок» (далее по описанию просто робот) - представляет собой двуного прямоходящего андроида с моделью передвижения имитирующей человеческую походку.

В рамках этой статьи вы научитесь собирать и приводить данного робота в движение. При этом в него будет заложен следующий функционал:

1) Автоматический режим – при этом робот будет самостоятельно передвигаться, шагая прямо и при появлении перед собой препятствия (в виде любого непрозрачного для инфракрасного излучения предмета) будет разворачиваться вправо или влево с целью обойти препятствие. В случае если препятствие не удается обойти (например, робот застрял в углу) будет включаться режим передвижения задом до момента выхода за границу зоны взаимодействия с препятствием.

2) Функционально-исполнительный режим – при этом робот будет устанавливать положение сервоприводов в соответствии с положением управляющих элементов на форме приложения для Windows. В этом режиме будет осуществляться создание всех моделей поведения, которые будут доступны в роботе.

2) Принципы управления роботом.

Возможно, вам может показаться, что мой ход преподнесения информации слишком избыточный и пора бы уже преступить к  сборке робота и его запуску в пешее путешествие, но позволю вас огорчить – что бы заставить этого робота ходить придется много поработать и узнать немало новой информации о принципах управления данным кибернетическим объектом. У меня для вас 2 новости (все как в бородатом анекдоте) одна плохая, другая хорошая. Начну с плохой. Для того что бы управлять этим роботом не подучится вызвать стандартную функцию типа:

роботВперед(Пока не устанешь)

так как этой функции просто нет, и вряд ли будет. Так же вам вряд ли удастся создать сколько-нибудь жизнеспособный линейный алгоритм для управления роботом, что-то вроде повернуть сервопривод 1 на косинус угла сервопривода 2 и тому подобных решений. И этому виной ряд причин:

1) Все сервоприводы даже дорогие и весьма надежные имеют разброс рабочих характеристик. Т.е. один и тот же сигнал для каждого сервопривода установит вал привода не в строго одинаковое положение.

2) Все сервоприводы имеют нелинейности по всей шкале своего возможного запаса хода. Т.е. например изменение длительности импульса с 1800 до 1900 микросекунд может привести к перемещению вала на большей или меньший угол, чем например изменение длительности с 1900 до 2000 микросекунд, причем положение этих нелинейностей может существенно отличаться для любых двух сервоприводов, даже из одной партии.

3) Даже если не брать в расчет мелкие нелинейности по различным участкам шкалы имеются и существенные общие нелинейности характерные для всех сервоприводов одного типа.  Может оказаться так, что во всех экземплярах шкала чуть более растянута в начале и чуть более сжата в конце с плавным переходом от начала до конца. С одной стороны может показаться, что это искажение не столь существенно т.к. оно характерно для всех сервоприводов в равной степени. Но если посмотреть на практическую сторону вопроса, то становится ясно, что сервоприводы на разных ногах стоят в обратной положении т.е, если робот например наклоняется вперед то один из сервоприводов делает положительное приращение, а второй отрицательное и в этом случае наличие даже обще характерного для всех приводов искажения очень сильно усложняет процесс создания линейного алгоритма управления.

4) Стандартный сервопривод не имеет полностью свободного хода на 360 градусов, а он способен вращаться в определенном секторе, обычно общая его протяженность составляет от 200-270 градусов. При сборке робота вы установите все сервоприводы в совершенно случайные положения, т.к. вам будет необходимо в первую очередь обеспечить наличие возможного хода в конструктивных пределах. Т.е вы поставите сервоприводы так что бы робот имел как можно более широкие пределы поворота частей при этом, постаравшись сделать эти пределы схожими на обеих конечностях. После  того как вы это сделаете ваше и без того не простая линейная модель по мимо всех сотен поправочных коэффициентов на нелинейности сервоприводов обзаведется еще и массивом исходных положений сервоприводов и позициями максимальных возможных передвижений.

Этот не малый список проблем далеко не полный, из тех, что вам придется преодолеть в попытке написания своего линейного алгоритма управления роботом и при этом даже если  у вас это получится (что у меня, например, очень плохо получилось), ваше устройство станет практически неповторяемым. Если вы захотите написать статью о робототехнике подобную этой или просто поделиться своими исходниками с другом, который решил собрать себе такое же устройство вы столкнетесь с тем, что вам опять придется собирать огромное количество уникальной информации для каждого сервопривода его проекта. А если же вы захотите выйти за рамки этого проекта и собрать, например робота не на 6 сервоприводах как этот, а например на 18 (например 6-ногий паук с ногами с 3 степенями свободы) или еще большим числом, то ваш проект может запросто разбиться о невероятные трудозатраты. Так же если вы захотите в какой-то день оптимизировать вашего робота или добавить новый функционал, либо просто немного изменить имеющийся, это станет очень непростой задачей.  Таким образом, линейный алгоритм слабо применим для моделей с ходовой частью, реализованной на сервоприводах под управлением платформы Arduino и технически реализованный указанными выше средствами. Для того что бы реализовать линейный алгоритм управления роботом необходимы существенно более серьезные вычислительные мощности и более серьезные технические средства, а в конце этой статьи вы сможете найти их описание, но ведь мы хотели реализовать ходящего робота теми средствами, которые у нас есть… Как же быть? Тем более, я обещал, что будет и хорошая новость))

В этой статье я опишу, как управлять роботом использую дискретный алгоритм управления. В чем заключается суть этого алгоритма. Необходимо путем подачи на робота управляющих сигналов с компьютера установить его сервоприводы в положения соответствующие устойчивым промежуточным значениям планируемой модели поведения. Например, мы хотим, что бы робот сделал один шаг правой ногой, это действие можно совершить поочередно перейдя из одного дискретного состояния в другое при чем, для того что бы робот сохранял устойчивость во всех точках этого движения перемещения должны осуществляться между заведомо устойчивыми позициями. Далее я приведу примерный список позиций которые робот должен поочередно пройти что бы сделать один шаг правой ногой:

1) Наклонить опорные сервоприводы так, что бы робот перенес центр тяжести на левую ногу и правая нога немного оторвалась от земли

2) вернуть роботу относительно прямое положение при этом, не потеряв устойчивость левой ноги стопу правой ноги позиционировать  параллельно земли

3) Поднять правую ногу вперед сложив её в колене, что бы сохранить положение стопы параллельным земли, левую ногу немного сложить в колене, при этом немного отклонив корпус назад для сохранения у корпуса положения параллельного земле

4) Наклонив опорные сервоприводы перенести центр тяжести равномерно на обе ноги.

Обратите внимание что если пропустить хотя бы одно из указанных действий робот не сможет сохранить устойчивость и он либо будет одновременно двумя ногами «ёрзать» по земле(если пропустить 1 шаг), либо просто упадет назад (если пропустить 3 шаг). Т.о. для того что бы реализовать любую модель движения робота достаточно разбить все большое движение на дискретные устойчивые позиции и заставить робота плавно и одновременно всеми сервоприводами переходить из одной позиции в другую. На практике нам необходимо просто получить координаты сервоприводов в контрольных точках, т.е. узнать какой длительности импульсов соответствует та или иная позиция робота, далее необходимо создать массив, включающий в себя все контрольные точки и передать этот массив функции, которая сможет организовать плавный и синхронизированный по времени процесс перехода из одной точки в другую. Хорошая новость заключается в том, что я уже реализовал все этапы необходимые для того что бы данный метод работал просто и очевидно, вам же осталось только понять что к чему и решительно преступить реализации первого, по настоящему удобного в программировании ходящего робота. Прекрасно понимая ваше желание преступить к сборке позволю себе предостеречь вас от этого шага так как для того что бы вам не пришлось в дальнейшем еще раз разбирать робота придется все таки выполнить указания следующей главы.

3) Предварительная подготовка.

В среде разработки Arduino имеется библиотека Servo созданная специально для управления сервоприводами. С помощью нее можно достаточно просто задать положение сервопривода. Причем положение можно задавать как в градусах, так и в микросекундах. С одной стороны может показаться, что управлять градусами проще, но это не совсем так по следующим причинам:

1) Управляя градусами мы можем задать положения сервоприводов только в пределах от 0 до 180 градусов, если мы передадим значение более 180 то будет отработано 180 и соответственно если передать меньше 0 то будет отработано 0. На практике же разница между положением которое серва отрабатывает при 0 и 180 далеко не всегда равна 180 градусам, а это может быть как 160 так и 200 градусов, т.е. точность совсем не какая. Так же стоит отметить что конструктивно сервопривод может довернуться дальше как в сторону 0 так и в сторону 180. Т.о. образом может возникнуть ситуация при которой вы установите сервопривод, механически проверите его возможность двигаться в пределах конструктивной свободы. Когда начнете на него подавать сигнал окажется, что при задании позиции с помощью с управления градусами вы не сможете переместить движок серво в крайнее конструктивное положение т.к. 0 или 180 будет находиться раньше чем, то положение, куда бы вы хотели переместить вал.

2) Для того что бы точно позиционировать вал привода в некоторых случаях разрешения в 1 градус может быть не достаточно, например если двигать системой с большой длиной рычага (как например бедренный сустав робота), в этих случаях перемещения в даже в 1 градус могут выглядеть достаточно резкими и рывковыми. При управлении длительностью импульса реальное разрешение более чем в 10 раз превосходит разрешения при управлении градусами.

3) Не каких тригонометрических расчетов в процедуре при движении робота осуществляться не будет и по этой причине какой-либо практической необходимости в применении градусов просто нет.

Из вышесказанного вы, наверно поняли уже поняли что в тех скетчах, которыми мы будем оперировать в рамках этой статьи управление сервоприводами будет осуществляться методом передачи длительности импульса в микросекундах. Теперь осталось только выяснить некоторые возможности конкретно тех сервоприводов, которыми вы располагаете, что бы система работала точно. Нам необходимо получить предельные значения длительностей импульса при которых конкретно ваши сервоприводы смогут перемещаться во всем возможном секторе и для этого необходимо выполнить следующую последовательность действий:

1) Нумеруем сервоприводы в нашем случае от 0 до 5 (т.е. их всего 6). До тех пор пока робот не будет запущен, и не будут получены все необходимые сведения, нанесенные на сервоприводы номера должны четко просматриваться. Нумеровать сервоприводы стоит карандашом или тонким маркером.

2) Необходимо залить на вашу отладочную плату  исходник (их обычно в данной среде называют скетчами) в начале я указал DFRduino Nano, но может сгодиться любая плата, рассчитанная на программирование в среде разработки Arduino. В этой статье я не буду описывать, что такое Arduino и как с ней бороться т.к. я рассчитываю, что вы хоть немного уже в этом и сами разобрались. Скетч, который вы будете загружать на плату делает следующее действие: к плате необходимо подключить любой переменный резистор сопротивлением от 10 до 50 килоОм и один сервопривод, которым мы будем управлять с помощью резистора, при этом текущее значение длительности импульса будет возвращаться на монитор порта. В чем заключается смысл этого действия? Нам необходимо получить для каждого из ваших сервоприводов предельные величины длительностей импульса которые переводят сервопривод из одного крайнего положения в другое. Полученные величины для каждого сервопривода необходимо зафиксировать и выбрать максимальное и минимальное значение. Ниже приведу таблицу с примером:

 Номер сервы 

 Минимум 

 Максимум 

0

450

2750

1

400

2700

2

500

2680

3

470

2730

4

450

2640

5

480

2800


Максимальное и минимальное значение я отметил жирным шрифтом в таблице. Итогом выполнения этого шага станет наличие предела, который в моем случае составил 400-2800 микросекунд. Что дает нам этот предел? В рамках этого предела все наши сервоприводу могут быть переведены и в минимальное и в максимальное значение. Далее в статье полученный на этом этапе предел я буду называть рабочим  пределом сервоприводов, хотелось бы, что бы вы понимали, что ваши значения будут отличаться от моих поэтому этот шаг вам будет необходимо провести самому. Выше была теория, дальше будет практика. Собираем следующую схему, представленную на рисунке ниже.



Т.о. управляющий вывод потенциометра подключен к выводу A0, а сервопривод подключен в цифровому выводу 7. Далее загружаем следующий скетч.

 #include <Servo.h>//Подключение библиотеки Servo

int PtnPin = A0;//Вывод потенциометра

int SrvPin = 7;//Тестируемый серво

int MinTiming = 400;//Нижняя граница длительности

int MaxTiming = 2800;//Верхняя граница длительности

Servo TestServo;//Рабочая переменная типа Servo

void setup(){

  Serial.begin(9600);//Инициализация Serial-соединения

TestServo.attach(SrvPin,MinTiming,MaxTiming);

pinMode(PtnPin,INPUT);

  //Инициализация сервопривода

}

void loop(){

  int i = map(analogRead(PtnPin),0,1023,MinTiming,MaxTiming);

//Преобразование сигнала от потенциометра из 0..1023 в 300..3000

  TestServo.writeMicroseconds(i);

  //Перемещение сервопривода в положение соответствующее сигналу

  Serial.println(i);

  //Отправка текущего значение в монитор порта

  delay(100);//Задержка на выполнение перемещения

}

После этого необходимо выбрать в среде разработки пункт меню:

Сервис àМонитор порта (Servis à Serial Monitor для английской версии) или комбинацию клавиш Ctrl+Shift+M. После этого появится диалоговое окно консоли, в которой вы сможете наблюдать текущее значение длительности импульса, подаваемое на сервопривод.  Дальше необходимо перемещая движок потенциометра определить крайние точки для каждого сервопривода, занести значения в таблицу и определить рабочий предел сервоприводов.

В результате проделанной работы был получен рабочий период ваших сервоприводов. Хочу остановиться на том, что стандартное значение длительности импульса соответствующее значениям 0..180 составляют 544..2400. И если использовать метод attach() в следующей варианте:

TestServo.attach(SrvPin);

Т.е. не указываю верхнюю и нижнюю границы изменения длительности то разницы между управления градусами и длительностью не будет т.к. вы по прежнему не сможете переместить вал привода за границы соответствующие 0..180 градусов, но задав при инициализации значения, отличающиеся от стандартных 544..2400 вы сможете расширить(или если необходимо сузить) управляемую область перемещения сервы. Если указанные мной в скетче значения (400..2800) не смогут переместить ваши сервы в крайние положения вы можете экспериментальным путем еще немного расширить эти границы, если же вы превысите определенный предел заложенный в вашем сервоприводе конструктивно вы легко это сможете заметить по дергающемуся характеру передвижения и резкому сужению предела регулировки. От качества проведения этой части настройки существенно зависит качество вашего конечного результата, по этой причине не поленитесь и проведите исследование тщательно, что бы не пришлось, потом к нему опять возвращаться. Вы же не хотите, что бы при испытании робота при прохождении крайних участков подвижного сектора робот падал на землю и начинал конвульсивно дергать конечностями? ;) Так же хочу остановиться на том что общая величина рабочей области т.е. в моем случае 2800-400=2400  не должная превышать значения 2703, это связанно с некоторыми принципами функционирования предложенного мной программного обеспечения.

4) Сборка робота.

После всех слов и подготовительной части можно со спокойной совестью преступить к сборке робота. Для комфортного выполнения всей этой операции нам могут потребоваться следующие инструменты:

1) Малая и средняя крестообразные отвертки с намагниченными наконечниками.

2) Круглогубцы малые либо рожковые ключи на 3 и 5,5мм

3) Паяльник маломощный (не более 30 Вт) с тонким жалом и набором паяльных принадлежностей (припой и флюс).

4) Вышедший из строя или ненужный компьютерный шлейф IDE 40 или 80 жильный

5) Термоусадочные трубки диаметром 1,5 и 3мм, либо другие менее практичные кембрики, ну или, в крайнем случае, изоляционная лента.

6) Дрель с набором сверл

И возможно другие незначительные мелочи.

В процессе эксплуатации данного робота я многократно его разбирал и вновь собирал, поэтому успел определить наиболее простую последовательность сборки. Вам предлагаю действовать так же. Поехали!

Шаг 1

Нам потребуется:

1) Кронштейн Многоцелевой для серво Gekko ASB-04 - 1шт

2) Кронштейн Стопа робота Gekko ARF-01 - 1шт

Скрепляем эти элементы вместе как показано на картинке. При этом винты DIN965 М2х5 (заподлицо) идущие в комплекте со стопами вставляем через отверстия указанные на рисунке красным со стороны пола, гайки же затягиваем ключом или круглогубцами с той стороны, которая видна на картинке как верхняя.



Шаг 2

Нам потребуется:

1) Кронштейн Многоцелевой для серво Gekko ASB-04 - 1шт

2) Кронштейн Швеллер для серво Gekko ASB-53 - 1шт 

Аналогично первому шагу пользуемся картинками, их две, что позволяет точно определить порядок сборки.  Соединяем винтами DIN7985 М2х5.





Шаг 3

Нам потребуется:

1) Кронштейн "П" для серво Gekko ASB-09 - 2шт

Тут все совсем просто.  Соединяем винтами DIN7985 М2х5.



Шаг 4

Нам потребуется:

1) Кронштейн Многоцелевой для серво Gekko ASB-04 - 1шт

2) Кронштейн "П" для серво Gekko ASB-09 - 1шт 

3) Кронштейн "Г" для серво Gekko ASB-06 - 1шт

Тут, пожалуй, немного сложней, но главное собрать все точно по картинке, что бы потом не морщить мозг на тему «как же тут блин?…» Используем все те же винты DIN7985 М2х5. На двух картинках думаю, вы легко разберетесь, в чем загвоздка.





Шаг 5

Нам потребуются все 7 элементов собранные на первых 4-х шагах, а так же Шарикоподшипник с фланцем Gekko ABB-03: 3 пары, их можно легко купить по указанной ссылке, но делать этого не стоит, так как они поставляются в комплекте с Кронштейн "П" для серво Gekko ASB-09, поэтому у вас и так есть все что надо. Все составные элементы робота необходимо объединить в так называемый «скелет робота», т.е. почти робот, но без мяса (сервоприводов). Что бы вы не имели возможности где-то пойти по неправильному пути, при выполнении этой операции, ниже я приведу картинку поясняющую порядок комплектования и расположения элементов подвижного соединения.



1 – Подшипник 8*4; 2 – гайка М3; 3 – подвижная сторона противоположная размещению сервопривода(Кронштейн "П" для серво Gekko ASB-09); 4 – гравер М3; 5 – винт М3-10; 6 – подвижная часть прилегающая к сервоприводу (Кронштейн Многоцелевой для серво Gekko ASB-04)

Почитав описание к картинке, я думаю, вы сразу поняли, что все совсем просто и вряд ли допустите ошибки, но поясняющие картинки по сборе естественно будут.





Наверно, глядя на картинку, вы и впрямь поверили, что после этого шага робот и впрямь будет так браво стоять, но к несчастью робот будет представлять собой довольно жалкое зрелище, более похожее на жителя кукольного театра. Но волноваться не стоит, так как следующим шагом мы обязательно сделаем его точно таким же, как на картинке в начале статьи.

Шаг 6

Для заключительной сборки механической части робота нам потребуется:

1) Сервопривод Feetech FS5103B – 6шт (как я уже говорил сгодиться  любые сервоприводы, которые у вас имеются в хозяйстве главное что бы они были типо размера Servo Standart)



Примерно таких габаритов.

2) Набор из 4 качалок для серво, из этого набора нам пригодится только один тип стандартные круглые с отверстиями для монтажа.

Необходимо прикрутить качалки ко всем сервоприводам, что бы они начали выглядеть примерно так или лучше.



Теперь необходимо вставить все сервоприводы на свои места в Кронштейн Многоцелевой для серво Gekko ASB-04. При этом необходимо провести провода от сервоприводов так, что бы они находились на своих местах, и в последствии не пришлось снимать из-за них сервоприводы.  Ниже на картинке вы можете рассмотреть порядок посадки сервы на свое место.



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



Если же по каким-то причинам ваш робот «не хочет» собраться и выглядеть как на картинке выше, вам непременно поможет этот Файл. Этот исполнительный файл имеет в себе 3D модель этого робота и вы сможете легко разобраться со спорными моментами, которые я мог упустить.

Шаг 7

На этом этапе сборке нам потребуется:

1) Робот собранный на шагах 1-6

2) Контроллер DFRduino Nano v3 на ATmega328 + FT232RL (arduino)

3) Плата расширения ввода/вывода DFRobot v1 для Arduino Nano

4) Держатель батареи 4-AA закрытый с выключателем

5) Винт DIN7985 М3х20: 4 шт

6) Гайка DIN934 М3: 8 шт

7) Дрель с набором сверл

Снимаем крышку с держателя батарей и прикладываем к ней плату расширения ввода/вывода. Намечаем шилом места под отверстия для крепления платы на крышку. Сверлим отверстия сверлом 3,2мм, продеваем винты в отверстия шляпками в сторону батарей, а с другой стороны накручиваем на каждый винт по две гайки  М3. Эти гайки будут создавать зазор между платой и поверхностью крышки держателя. Теперь вставляем в ячейки держателя батарейки (аккумуляторы) и подгоняем надфилем головки винтов что бы они не мешали нормальному закрыванию крышки. После этого держатель батарей имеет вид как на картинке.



Хочется отметить, что в своем роботе я использую самодельную плату расширения вводов выводов, и она имеет следующий вид:



Вы же можете применять ту плату расширения, которую я указал, т.к. это существенно проще. Теперь необходимо закрепить плату расширения на винтах крышки, установить плату Arduino Nano и подключить к ней питание от держателя. Питание необходимо подвести минус к GND плюс к +5v, позволю себе заострить на этом внимание т.к. если подать питание на Vin, то то 5 вольт от батарей поступит на вход стабилизатора напряжения, а для него минимальное напряжение на входе равняется примерно 6,5-7вольтам при меньшем же напряжении питание не будет проходить через микросхему. После необходимо убедиться, что плата работает. Далее можно отсоединить крышку от держателя. Теперь необходимо закрепить держатель батарей на поверхность швеллера, являющегося основанием робота. Для того, что бы винты не мешали нормальной укладке батарей, их нужно разместить вне отсека для батарей. Для этого необходимо снять заглушку закрывающую отсек над батарейками в котором размещается выключатель и сделать отверстия в этом отсеке. Для прочности конструкции необходимо сделать 2 отверстия диаметром 3,2мм, причем эти же отверстия необходимо сдублировать и в швеллере. После этого необходимо закрепить на швеллере держатель батарей. После закрепления заглушку можно установить на свое место. Если вы меня правильно поняли у вас должно получиться примерно так.



В заключение этого шага сборки необходимо подстыковать крышку от держателя батарей к держателю. Далее необходимо подключить питание от батарей к плате расширения. Стоит отметить, что если вы используете другую плату, то порядок её размещения вам придется разработать самостоятельно.

Шаг 8

На этом этапе сборки нам необходимо установить датчик дальности Sharp и для этого нам потребуется:

1) Датчик дальности инфракрасный Sharp GP2Y0A21YK0F 10-80см (аналоговый)

2) Держатель датчика Gekko ASH-01

3) Кабель 3-жильный 2.54 мм М -> JST (30 см)

4) Паяльник маломощный (не более 30 Вт) с тонким жалом и набором паяльных принадлежностей (припой и флюс).

Для начала необходимо подготовить кабель для датчика дальности вы можете конечно взять готовый Кабель 3-жильный 2.54 мм М -> JST (30 см), но на мой взгляд он слишком длинный, поэтому я изготовил его самостоятельно. Для этого я отделил 3 жилы кабеля от IDE шлейфа длиной 15 см . Выпаял из датчика дальности разъем. Впаял в отверстия от разъема  провод с другой же стороны установил Разъем розетка 3-вывода шаг 2.54 мм. Порядок коммутации при этом следующий:

1)    Впаиваем провода в датчик подряд без перехлестов

2)    При подключении проводов к розетки последовательность выходит не прямая как при пайке к сенсору. Если разместить сенсор излучателем вверх, площадкой с контактами в сторону вас, то левый вывод – сигнальный, средний вывод – земля, правый вывод – плюс питания.  Если разместить фишку подключения к Arduino аналогичным образом что бы сигнальный вывод был слева, то средним проводом должен быть плюс питания а правый – земля. Таким образом при подключении провода к фишке необходимо предусмотреть смену расположения контактов. На следующей картинке я постарался схематично изобразить порядок подключения.



А на этом фото я сфотографировал как это выглядит в действительности, обратите внимание, что сигнальный провод у меня белый поэтому вы сможете точно понять какие именно провода необходимо перехлестнуть.



После того как сенсор готов необходимо его установить. но сначала нам придется немного попотеть. Берем Держатель датчика Gekko ASH-01, находим в на нем угол 90 градусов и распрямляем его. Т.е. у вас имеется вот такая деталь.



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

Теперь необходимо на распрямленный держатель установить сенсор. При этом временно отложить скопленный трудовой фанатизм, который вы наверно успели подкопить при распрямлении держателя, так как крепежные ушки сенсора, не смотря на именитого производителя, имеют весьма ненадежную конструкцию.

Далее необходимо подключить разъем вашего датчика дальности к одному из аналоговых входов вашей Arduino. В моем случае я использовал вывод A0.

После выполнения этого шага ваш робот должен обзавестить примерно вот такой физиономией.



Шаг 9

Этот шаг будет заключительным и кому-то может и вовсе не требоваться. Нам необходимо удлинить провода сервоприводов до длины при которой они будут без каких-либо натяжений подключаться к Плате Arduino. Все зависит от того на сколько длинные провода ваших сервоприводов. Для сервоприводов бедренного сустава (т.е. верхней пары) вполне достаточно длины 15-17см и если ваши сервоприводы имеют длину более чем на 5см большую, целесообразней будет провода укоротить. Для того что бы укоротить провод можно либо его просто отрезать и на конце разместить новый Разъем розетка 3-вывода шаг 2.54 мм, либо если таковых не имеется можно просто отрезать участок провода и спаять концы при этом каждый провод заизолировать термоусадочной трубкой диаметром 1,5мм. Так же можно по окончании операции сращивания провода скрепить место соединения более толстой термоусадочной трубкой диаметром 3-5мм. Для сервоприводов коленного сустава (средней пары) оптимальной длиной будет примерно 25-30см, соответственно если длина больше ее желательно уменьшить как в предыдущем случае если меньше, то необходимо нарастить длину провода за счет вставки в разрез трехжильного провода взятого из IDE шлейфа.  Для сервоприводов сустава стопы (нижняя пара) оптимальной длиной может быть примерно 30-35см.

После того как вы обеспечили необходимую длину проводников, разъемы сервоприводов необходимо разместить в цифровые выводы Arduino, при этом порядок и последовательность особой роли не имеет, но желательно не размещать сервоприводы в выводы следующих номеров: 0,1 – т.к. эти выводы используются системой в качестве RX и TX. Так же не стоит использовать аналоговые выводы A0-A7, т.к. не смотря на то что любой вывод  можно назначить аналоговым выходом, в библиотеке servo может возникнуть проблема с использованием аналоговых выводов, если же вы все таки решили использовать эти выводы необходимо их явно назначить выходными используя pinMode(Ax, OUTPUT). Т.о. для размещения лучше выбрать выводы 2-13. Я подключил сервоприводы к цифровым выводам 3-8.

В завершение следует проверить наличие свободы действия у всех конечностей и отбортовать провод по корпусу с помощью хомутов.

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

5) Настройка программы Beepod Controller

После долгой подготовки и сборки можно преступить к реализации программной части робота. Специально для целей данной статьи мной была написана простая, но достаточно удобная утилита для создания моделей поведения робота и сейчас я вам объясню, как с ней работать.

Программа Beepod Controller (далее просто программа) организует интуитивно понятный пользовательский интерфейс с помощью которого можно установить положения сервоприводов робота в произвольное положение. При этом программа позволяет сохранять, загружать сохраненные а так же произвольно редактировать модели поведения робота, представляющие собой наборы статичных положений при последовательном выполнении которых робот может делать различные действия такие как например: Шагать вперед, Шагать назад, Поворачивать налево, Поворачивать на право и т.п.  Для позиционирования сервоприводов робота программа считывает положения органов управления, шифрует комбинацию из 6 чисел специальным образом и отправляет шифрованную комбинацию роботу через COM-интерфейс. Для работы программы на роботе должен быть залит специальный скетч, который принимает шифрованные посылки, расшифровывает их и плавно, а так же синхронно перемещает сервоприводы в положения соответствующие переданной комбинации.  Таким образом, для начала работы с программой на робота необходимо залить скетч, который предварительно нужно настроить под ваши параметры.

В третьей главе статьи вы определяли Рабочие пределы сервоприводов, теперь эти значения нам пригодятся для настройки скетча, у меня эти значения как я уже говорил равны 400 и 2800. Так же нам понадобится список цифровых выводов, к которым вы подключили ваши сервоприводы, в моем примере это 3,4,5,6,7,8. Так же при заливке скетча необходимо обратить внимание на номер COM-порта, которым система назначила Arduino-девайс, применяемый в проекте, в моем случае это COM4. Стоит так же для себя зафиксировать тот факт, что в исходнике указана скорость соединения 9600 и её необходимо будет установить и в программе. Скетч имеет вид:

//Beepod_Model.ino

//Подключение к проекту библиотеки Servo

#include <Servo.h>

//Номера пинов с сервоприводами

int NumControl[] = {3,4,5,6,7,8};

//Исходное положение

int StartPos[] = {1600, 1600, 1600, 1600, 1600, 1600};

Servo Servos[6];//Массив сервоприводов

int APos[6];//Массив хранит предыдущие координаты сервоприводов для

//расчета дискретных шагов приращения для перехода на заданную позицию

int BPos[6];//Массив для передачи параметров новой позиции

int ServCount = 6;//Константа хранит количество сервоприводов

int MinTiming = 400;//Минимальная длительность импульса

int MaxTiming = 2800;//Максимальная длительность импульса

String St;//Глобальная строчная переменная для приема шифрованной

//пачки хранящей информацию о новой позиции

 

//Функция производит плавный одновременный переход сервоприводов

//из текущей позиции в заданную параметром xPos

void MovePos(int xPos[]){

int Delta=0;//Переменная для хранения величины приращения

int MaxDelta=0;//Переменная для хранения максимальной величины приращения

//В этом цикле определяется максимальная величина приращения

for (int i=0; i<ServCount; i++){

//Абсолютное приращение i-того элемента

    Delta=abs(APos[i]-xPos[i]);

//если i-тое приращение больше текущего значения максимального

//Приравниваем i-тое максимальному 

    if (MaxDelta < Delta) MaxDelta = Delta;

}

MaxDelta/=10;//Уменьшаем значение в 10 раз

//Этот цикл опредляет количество дискретных шагов, за которые

//будет выполнен полный переход из APos в xPos

for (int i=0; i<MaxDelta; i++)

//В данном цикле происходит проход по всем 6 сервоприводам в

//рамках действий одного дискретного шага

    for (int j=0; j<ServCount; j++){

//j-тый сервопривод перемещается на i-том шаге на

//величину равную (1/количество шагов)*общая величина приращения

      Servos[j].writeMicroseconds(map(i,0,MaxDelta,APos[j],xPos[j]));

//Пауза предназначенна для обеспечения плавного движения

//при совершении переходов с большой амплитудой

      delayMicroseconds(1000);

    }

//В этом цикле новая позиция сервоприводов станет предыдущей

//для следующего вызова функции

  for (int i=0; i<ServCount; i++)

    APos[i]=xPos[i];

}

//Начальная инициализация

void setup(){

//Инициализация сервоприводов

for (int i=0; i<ServCount; i++){

    Servos[i].attach(NumControl[i],MinTiming,MaxTiming);

//Вычисление и присвоение "предыдущей позиции"

    APos[i]=Servos[i].readMicroseconds();

//Эта скорость должна соответствовать установленной в программе

Serial.begin(9600);

//Переход в стартовую позицию

MovePos(StartPos);

}

void loop(){

  byte a=0;

  byte b=0;

//Если в буфере Serial-порта есть данные

while (Serial.available()){

//Чтение 1 символа из буфера

    char Ch=Serial.read();

//если не символ @ то добавляем символ к строке

//наличие сиввола @ означает конец шифрованного послания

    if (Ch!=64) St+=Ch;

    else{

//В этом цикле шифрованое послание расшифровывается и

//перемещается в BPos

      for(int i=0; i<ServCount; i++){

        if (St[i*2]<=90) a=St[i*2]-65; else a=St[i*2]-71;

        if (St[i*2+1]<=90) b=St[i*2+1]-65; else b=St[i*2+1]-71;

        BPos[i]=(a*52)+b+MinTiming;

      }

//Вызов перемещения в новую позицию

      MovePos(BPos);

//Очистка буфера приема строки

      St = "";

    }

  }

После того как вы загрузили скетч робот должен принять, какое-то кривое положение соответствующее значению 1600 микросекунд для всех ваших сервоприводов. Значение 1600 выбрано не случайно, оно находится в середине шкалы перемещения сервопривода, т.е. если вы установили сервоприводы верно, они примут эти положения без особых нагрузок и попыток изменить конструкцию корпуса. Теперь можно запустить программу Beepod Controller, которую вы сможете скачать по ЭТОЙ ссылке. Скачайте программу и мы сможем продолжить работу.

Распакуйте архив с программой в любое удобное место и в каталоге Beepod Controller вы обнаружите каталог Models в котором программа будет по умолчанию сохранять модели и там же их первым делом искать при попытке загрузить, так же вы там найдете исполнительный файл BeeControl.exe – это и есть программа, и командный файл ADMIN.CMD – предназначенный для запуска программы в административном режиме. Так же после первого запуска в этом каталоге появится файл config.dt – хранящий настройки программы и файл TMP – хранящий содержимое компонента формы в котором будут храниться числовые значения. Программа автоматически сохраняет все настройки и изменения полученные в рабочую сессию.

Для начала работы с программой вам необходимо сделать первый запуск в административном режиме, это позволит тонко настроить программу для её дальнейшего использования. Запустите программу с командной строкой –s либо просто запустите командный файл ADMIN.CMD сначала запустится черное окно командной строки затем и окно программы. Для удобства вы можете закрыть черное окно командной строки, т.к. в нем нет дальнейшей необходимости а программа должна иметь примерно такой вид.



 

Первым делом нам необходимо настроить параметры подключения:

1) В поле порт введите номер порта которым система назначила вашу Arduino плату

2) Установите скорость подключения 9600, если она стоит другая

3) Введите значения ваших Рабочих пределов сервоприводов в поля Min и Max (там где у меня введено 400 и 2800)

4) Подключите робота к USB разъему (если он не был подключен уже) и нажмите кнопку Connect, либо комбинацию клавишь Ctrl-N либо сделайте двойной клик по красной лампе на форме. Если после этого лампа индикатор стала зеленой значит все в порядке, если же нет проверьте еще раз номер порта и подключение платы к USB.

Теперь необходимо определить какому управляющему движку соответствует, какой сервопривод в роботе и промаркировать их в полях, которые по умолчанию заполнены значениями SERVO 1…SERVO 6. Для того что бы это сделать необходимо плавно пошевелить каждый движок и определить какой сервопривод при этом приводится в движение. Как вы будете подписывать ваши приводы – это дело ваше, я же предпочел вариант примерно такой: Бедро 1, Бедро 2, Колено 1, Колено 2, Стопа 1, Стопа 2.  Подписи в полях можно ставить использую буквы Русского, Английского алфавита, если вы попытаетесь ввести туда что-то  например на Иврите, кодировка будет искажена.

Преступаем к самому ответственному шагу настройки программы. Необходимо перемещая движки получить от робота симметричную, устойчивую позу, которая в дальнейшем будет применять как исходная во всех моделях. По той простой причине, что данная поза будет ключевой и вы будете её наблюдать чаще всего, а так же она будет использоваться в качестве стартовой позы и в других переходных фазах работы, например в режиме стояния на месте, желательно сделать эту позу как можно более точной. Определить качество установки исходного положения можно по наличию (а скорей отсутствию) каких-либо посторонних рычаний у всех сервоприводов робота, если какой-то привод издает неправильные звуки, значит он испытывает излишние нагрузки и его необходимо немного ослабить в сторону переноса тяжести на аналогичный привод второй ноги. В своем проекте эту фазу калибровки я выполнял с помощью стетофонендоскопа (это медицинский прибор для прослушивания внутренних физиологических звуков при терапевтическом обследовании). С помощью данного прибора очень легко найти источник шума и точно его локализовать. После того как вы точно уверились в том, что найденная позиция точно соответствует всему вышесказанному, необходимо поочередно нажать на все кнопки с надписью Def, что сохранить это положение как положение по умолчанию. Что бы проверить, что все сделано правильно расстройте положения сервоприводов в любое случайное положение и нажните кнопку Default, после этого робот должен будет принять то положение, которое вы сохранили. В дальнейшем нажимая на эту кнопку, вы всегда сможете вывести робота из любых изощренных поз, в которые вы будете его загонять.

В заключение осталось настроить рабочие сектора для каждого сервопривода. Дело в том что далеко не каждому сервоприводу будучи зажатым в рамки механической конструкции посчастливится иметь возможность изменять свое положение от Min и до Max при этом неиспользуемые части сектора перемещения ползунков будет сужать возможности плавной регулировки положения. Что бы этого избежать вам осталось установить начало и конец шкал для каждого сервопривода. Для того что бы это сделать вам необходимо совершить следующий обряд:

1) Возьмите робота одной рукой за основание корпуса

2) Перемещайте первый движок в сторону уменьшения до тех пор, пока сервопривод не отклонит конструкцию до максимально возможного положения, как правила при попутке переместить движок дальше сервопривод естественно не двигается, но начинает сильно рычать. Выведите минимум до положения, когда привод еще не рычит, но уже находится в конце возможного пути и нажмите на кнопку Min, расположенную напротив соответствующего движка. После этого ползунок движка резко перемесится в левый конец шкалы и потеряет возможность установить значение ниже. Если так и произошло, значит вы идете по нужному пути.

3) Нажмите на кнопку Default и ползунок отскочит в положение исходной позиции.

4) Теперь аналогичным образом найдите максимально возможное положение, после чего нажмите кнопку Max соответствующую этому ползунку. Теперь ползунок отскочил в максимальное правое положение закрыв возможность установки положения больше чем выбрано.

5) Нажмите кнопку Default

6) Теперь несколько раз переместите ползунок в обе стороны до крайних положений и убедитесь что, ваша серва точно загнана в нужные рамки. Если же вы недостаточно сильно сузили какой-то предел можно еще раз его сузить. Если же при установке границ вы все таки перегнули палку и слишком сильно сузили границы, вам необходимо сделать следующее:

1) Нажмите кнопку Default и запомните положение соответствующее исходному для этого сервопривода

2) Нажмите кнопку Res на против этого движка, при этом все его настройки сбросятся.

3) Установите движок в исходное положение и нажмите кнопку Def

4) Еще раз повторите настройки Min и Max для этого движка.

После того как первый сервопривод загнан в рамки «культурного поведения», вам осталось всего-ничего – повторить эти действия над остальными 5 приводами. Дам лишь совет – запишите значение по умолчанию перед тем как вы его случайно сбросите и что бы потом не пришлось его заново искать.

После того, как вы настроили все сервоприводы нажмите в очередной раз кнопку Default, и полюбовавшись этой красотой нажмите на кнопку Record или ReWrite (так как при пустом поле эти кнопки полностью идентичны). После этого в поле редактирования появится строка включающая в себя 6 чисел соответствующих вашему значению по умолчанию. Теперь выделите эту строку (если по каким-то неизвестным мне причинам она не выделилась сама) и нажмите кнопку Copy One или Copy All (при наличии одной строки они так же идентичны). После этого в вашем буфере обмена появилась строка из поля (т.е. как будто вы ее скопировали). Теперь необходимо открыть тот скетч, который залит в роботе и вместо 1600, 1600, 1600, 1600, 1600, 1600 вставьте ваше реальное значение стартовой позиции, не забыв удалить запятую в конце. После этого сохраните скетч в этом положении, положите его резервную копию на ближнюю полку вашего компьютера. Теперь нажмите кнопку Disconect, или дважды кликните по зеленой лампе. После этого выключите программу Beepod Controller. В принципе не кто не мешает вам использовать программу и в административном режиме, но при этом вы не застрахованы от случайного нажимания «не на ту» кнопку. Теперь загрузите измененный скетч в робота и убедитесь, что робот после включения действительно занял «уже надоевшую» исходную позицию. Если это так, значит вы полностью настроили и робота и программу, а значит готовы преступать к дальнейшим действиям

6) Описание работы с Beepod Controller в обычном режиме.

В предыдущей части статьи мы настроили программу, но не особенно углублялись в состав и назначение её органов управления. Сейчас я попробую кратко остановиться на этих моментах, а так как большую часть времени вы будете работать с программой в обычном режиме (не административном), то и все описания будут касаться в первую очередь этого режима. Программа в этом режиме выглядит примерно так:



1) Элементы установки длительности импульсов на сервоприводах. Вы можете менять длительность импульса, т.е. изменять углы на сервоприводах как непосредственно перемещая движки компонентов TrackBar, так и вводом значений в поля редактирования (Edit), которые расположены рядом с каждым TrackBar-ом. Причем в поле редактирования можно вводить только цифры и если введенное число входит в предел допустимых значений изменения длительности для выбранного компонента, то это значение автоматически применится и установится на соответствующем TrackBar-е. Хочется отметить что для точного позиционирования движка удобно использовать колёсико мышки.



2) Элементы управления соединением. Это три элемента – поле ввода COM-порта (возможные значения COM0..COM255), вываливающийся список выбора скорости соединения (возможные значения 115200, 57600, 38400, 31250, 28800, 19200, 14400, 9600, 4800, 2400, 1200, 600, 300 т.к. других значений не предусмотрено в библиотеке Serial из поставки Arduino) и картинка показывающая статус соединения. Картинку статуса соединения можно использовать для соединения и рассоединения, это можно сделать двойным кликом по компоненту.



3) Элементы хранения значений и управления режимом их передачи. Эти элементы включают в себя 4 кнопки и поле для хранения значений.

а) Кнопка «А» становится активной при включении режима одиночной передачи посылок и она предназначена для включения автоматической передачи. Если эта кнопка не активна, значит в настоящий момент используется Автоматический режим (и в её нажатии нет необходимости). В автоматическом режиме программа отправляет значения на робота в течении 100 миллисекунд после последнего изменения положений элементов управления. Т.е. если вы будете плавно перемещать движок сервопривода, то значения будет отправляться не с максимально-допустимой для соединения скоростью, а строго раз в 100 миллисекунд, если же вы не двигаете компоненты и значения не менялось более 100 миллисекунд, то отправка не будет осуществляться.

б) Кнопка «1»  становится активной если включен Автоматический режим передачи данных и неактивной после её нажатия и включения одиночного режима. В одиночном режиме так же становятся активными кнопки «<» «>», которые предназначенны для отправки разовых значений. Нажатие на кнопку «<» вызывает отправку на робота значений установленных на элементах управления. При нажатии на кнопку «>» на робота отправляется значение выбранное в поле для хранения значений, если же это поле пустое, то как и в случае нажатия «<» отправляются значение установленное на компонентах.

в) Поле хранения значений. В этом поле хранятся значения сохраненные со значений установленных на компоненте, а так же загруженные из файла. Двойным кликом по значению в этом поле вызывается отправка этого значения на робота, т.е. эта операция аналогична нажатию на «>».



4) Поле управляющих кнопок. В программе имеется 13 управляющих кнопок. Дальше немного о каждой.

Кнопка «Record» - при нажатии сохраняет и переносит в поле хранения установленное на компонентах значение.

Кнопка «ReWrite» - перезаписывает выбранное в поле хранения значение, установленным на компонентах. Если поле хранения пустое эта кнопка аналогична «Record».

Кнопки «Copy One» и «Copy All» - предназначены для копирования значений из поля хранения. «Copy One» копирует одно выбранное значение, «Copy All» - все значения из поля хранения.

Кнопка «TOP» - позволяет редактировать последовательность записей в поле хранения, при нажатии на эту кнопку выделенное поле (если оно не первое или не единственное) перемещается на позицию вверх, а то поле которое находилось над ним становится под ним.

Кнопка «Delete» - удаляет выделенную запись в поле хранения.

Кнопка «Clear» - очищает поле хранения.

Кнопка «Conect» - вызывает открытие выбранного COM-порта с выбранной скоростью соединения.

Кнопка «Disconect» - закрывает соединение с COM-портом.

Кнопка «Load» -  открывает диалог выбора файла для загрузки сохраненных моделей поведения (последовательностей записей). По умолчанию диалог находится в каталоге Models в каталоге программы.

Кнпка «Save» - открывает диалог сохранения файла для сохраниения созданной модели поведения (последовательностей записей). По умолчанию диалог находится в каталоге Models в каталоге программы.

Кнопка «Default» - переводит робота и все компоненты в исходное положение.

Кнопка «Exit» - завершение программы.



7) Написание моделей поведения робота.

После  того как в предыдущих частях статьи мы настроили программу Beepod Controller и кратко рассмотрели назначение компонентов программы, нам осталось создать модели поведения робота согласно которым робот будет совершать движения. Для целей данной статьи необходимо создать следующие модели:

1) Хождение вперед (forward)

2) Хождение назад (revers)

3) Разворот влево (left)

4) Разворот вправо (right)

Хочется отметить, что данная часть самая сложная и ответственная и как бы я не хотел на этой стадии вам помочь качество результата зависит только от вас, да и в целом то, что у вас в конечном итоге получится, будет абсолютно уникальным и неповторимым. Скорей всего эта стадия может занять много времени, но с использование предоставленной мной программы это будет довольно увлекательно. Ниже я постараюсь достаточно подробно показать вам свои модели поведения, вы же в свою очередь можете постараться её перенести на своего робота либо пойти по пути совершенно новому, а может быть вы сделав как у меня все потом переделаете под свой лад. Главное, что от вас требуется - это понять, как это делать и какие при этом существуют проблемы. Преступаем!

Если вы действуете в последовательности предусмотренной статьей, то в настоящий момент на вашем роботе загружен скетч из 5 раздела статьи, ваша программа Beepod Controller настроена, и вы уже имеете общие сведения о работе с программой. Если это не так выполните действия, предусмотренные в 5 разделе и прочитайте 6 раздел статьи. Подключите робота к компьютеру запустите программу Beepod Controller проверьте что бы настройки соединения (COM-порт и скорость) соответствовали вашим значениям и нажмите на кнопку «Conect». Если все хорошо то вы увидите зеленую кнопку лампу, говорящую о наличии соединения с роботом. Робот должен установиться в исходное положение. Подключите к роботу дополнительное напряжение питания 5 вольт или просто включите переключатель на держателе батарей, что бы запитать робота от него. Это необходимо потому, что робот потребляет при работе более 500мА тока и питания от USB интерфейса не хватает и при резких движениях робота он может перезагружаться, а при этом будет теряться соединение с программой. Начинаем делать первую модель поведения – (Forward), которая научит вашего робота ходить вперед.

1) Нажмите «Default», а затем «Record». В поле появились уже знакомые цифры положения по умолчанию. Мой робот при этом находится в таком положении:



2) Теперь необходимо перевалить робота на одну из ног в моем случае на левую, при этом опорная левая нога немного сгибается в колене назад а подвешенная правая нога перемещена вперед и колено согнуто вперед при этом имеет следующий вид:



Если вы правильно установили положение, нажмите «Record» и в поле появится второе значение, соответствующее этому значению. Хочу обратить внимание что несмотря на то что это значение по счету второе, но при циклическом выполнении всей модели выполнения робот не будет после каждого полного шага переходить в исходное (первое) положение, поэтому для этой модели поведения первой позицией будет эта. Т.о. робот начиная движение занимает исходное положение, затем это положение а дальше проходя весь цикл будет пропуская исходное начинать заново именно с этой позиции. Нам необходимо сделать так, что бы последний дискрет этой модели поведения мог гармонично перейти в эту позицию.

3) Следующая позиция практически идентична предыдущей за исключением того что стопа опорной левой ноги немного выпрямляется, а стопа подвешенной правой ноги внешней стороной наклоняется в сторону земли. В принципе это движение можно исключить, но оно позволяет роботу при переносе центра тяжести на обе ноги сделать это плавно, т.к. у опорной ноги  будет при переносе тяжести небольшая дополнительная опорная точка. При этом робот имеет вид:



4) Следующим шагом робот переносит центр тяжести с левой ноги на обе, при этом правая нога находится впереди. Робот имеет вид:



5) Перенос центра тяжести на правую ноги, при этом левая не полностью теряет опору, а колени и бедра переносят центр тяжести так, что бы робот сохранил устойчивость. Создание этого участка требует очень тщательной проработки и вам скорей всего придется постоянно придерживать робота, что бы тот не падал при ваших поисках опоры. В моем случае это положение имеет вид:



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



7) Эта позиция аналогична 3, опять же с поправкой на ноги



8) Теперь соответственно аналог 4 позиции.



9) Как вы наверно успели догадаться эта позиция полный зеркальный аналог 5 позиции, она же является последней в полном цикле из 8 позиций, так как 2 позиция является первой. Смотрим картинку:



После выполнения всех операций в вашем поле хранения позиций должно быть 9 записей. Первая запись – исходная позиция и со 2 по 9 модель поведения – forward. Для того что бы полностью довести до ума эту модель вам придется многократно пройти ее двойным кликом по записям поля, и если робот ходит так как надо значит вы все верно сделали и модель можно сохранять. Для этого выделите первую запись (исходная позиция) и удалите её нажав кнопку «Delete». Теперь нажмите кнопку «Save» и введите имя файла, его удобней всего назвать forward.txt. После чего нажмите OK в диалоговом окне сохранения файла.

Для того что бы создать модель поведения «Revers» - т.е. хождение назад нам достаточно просто обратить модель поведения «forward». В принципе вам не кто не мешает создать эту модель другим способом, но для целей этой статьи, на мой взгляд достаточно такого варианта. Т.о. делаем копию файла forward.txt, переименовываем её в revers.txt и открываем в стандартном блокноте, после чего просто меняем последовательность строк. При этом 1-я позиция становится 8-й, 2-я – 7-й, 3-я – 6-й, 4-я – 5-й, 5-я – 4-й, 6-я – 3-й, 7-я – 2-й и наконец 8-я – 1-й. После этой рекомбинации сохраняем файл  revers.txt, загружаем его с помощью кнопки «Load» в программу и проходя последовательно все шаги убеждаемся что все сделали верно. В принципе перекомбинировать строки файла forward.txt, можно очень просто и с помощью самой программы использую кнопку «TOP», в общем, кому как удобно.

Теперь научим робота разворачиваться. Как я уже говорил вы можете самостоятельно создавать совершенно любые модели поведения, и разворот можно реализовать например делая одной из ног более короткий шаг или еще какм-либо другим способом, но для простоты повторения в этой статье я предлагаю очень простой и действенный способ разворота при чем разворот будет осуществляться практически на месте и всего в 2 движения:

1) Установка робота в исходное положение. Тут думаю все и так понятно но все-таки сдублирую картинку:



2) Одна нога, причем противоположная стороне разворота переносится вперед и ставится на пятку. Соответственно если повторять это движение в цикле т.е. переходить в исходное затем нога на пятку и т.д. то при каждом таком движении робот будет совершать разворот примерно на 20-30 градусов в зависимости от степени сцепления стопы с землей и высоты подъема стопы. Ниже приведу сначала картинку позиции для разворота вправо затем аналогичную влево.





После того как вы получили указанные позиции у вас должны получиться два файла right.txt и left.txt в каждом из которых содержится модель состоящая из двух позиций – исходная и с поднятой соответствующей ногой. Таким образом, цель этой части статьи выполнена могу лишь посоветовать еще раз перепроверить каждую модель путем её пошагового выполнения в программе.

8) Запуск и отладка робота.

Вот наконец-то, мы подобрались к заключительной части нашего нелегкого совместного пути. Нам осталось только подготовить и залить исходник рабочего скетча и отладить робота.

В предыдущей части мы получили с вами модели поведения и у вас если вы все сделали должный были получиться следующие файлы: forward.txt, revers.txt, right.txt, left.txt.Ниже я приведу как эти файлы выглядят у меня, у вас они конечно име.т совершенно другие цифры, но на примере моих файлов вы легко сможете сделать аналогичные действия со своими.

forward.txt

1079, 1733, 1749, 2046, 2239, 2293,

1079, 1733, 2135, 2046, 2239, 2293,

1079, 1733, 1509, 1741, 2241, 2293,

1018, 1733, 1127, 1094, 2286, 2293,

776, 1454, 1115, 1645, 1629, 1608,

776, 1454, 1115, 1065, 1629, 1608,

776, 1291, 1438, 1615, 1629, 1608,

776, 1291, 1997, 1972, 1629, 1608,

revers.txt

776, 1291, 1997, 1972, 1629, 1608,

776, 1291, 1438, 1615, 1629, 1608,

776, 1454, 1115, 1065, 1629, 1608,

776, 1454, 1115, 1645, 1629, 1608,

1018, 1733, 1127, 1094, 2286, 2293,

1079, 1733, 1509, 1741, 2241, 2293,

1079, 1733, 2135, 2046, 2239, 2293,

1079, 1733, 1749, 2046, 2239, 2293,

right.txt

576, 1238, 1414, 1701, 2239, 2293,

792, 1278, 1203, 1510, 2215, 1651,

left.txt

576, 1238, 1414, 1701, 2239, 2293,

833, 1037, 1522, 1918, 2239, 2293,

Для того что бы формат этих файлов совпадал с тем что нам нужно в скетче в конце каждой строки нам необходимо добавить по еще одному числу. Седьмое число определяет время выполнения участка (в миллисекундах) Т.е. если например написать 1000 то переход из текущего на тот момент значения в положение определяемое строкой будет произведен за 1000 миллисекунд, т.е. 1 секунду. Седьмое число необходимо указать для каждой строки и вычислить его можно лишь опытным путем, что вы сможете успешно самостоятельно сделать после того как закончите статью, но сейчас вам необходимо установить туда любые значения  что бы хотя бы изготовить первый «опытный» образец. По этой причине рекомендую использовать для начала мои значения длительностей смотрим ниже и делаем у себя так же (добавленные числа я отметил жирным шрифтом):

forward.txt

1079, 1733, 1749, 2046, 2239, 2293, 350,

1079, 1733, 2135, 2046, 2239, 2293, 350,

1079, 1733, 1509, 1741, 2241, 2293, 600,

1018, 1733, 1127, 1094, 2286, 2293, 350,

776, 1454, 1115, 1645, 1629, 1608, 350,

776, 1454, 1115, 1065, 1629, 1608, 350,

776, 1291, 1438, 1615, 1629, 1608, 600,

776, 1291, 1997, 1972, 1629, 1608, 350

revers.txt

776, 1291, 1997, 1972, 1629, 1608, 550,

776, 1291, 1438, 1615, 1629, 1608, 950,

776, 1454, 1115, 1065, 1629, 1608, 550,

776, 1454, 1115, 1645, 1629, 1608, 550,

1018, 1733, 1127, 1094, 2286, 2293, 550,

1079, 1733, 1509, 1741, 2241, 2293, 950,

1079, 1733, 2135, 2046, 2239, 2293, 550,

1079, 1733, 1749, 2046, 2239, 2293, 550

right.txt

576, 1238, 1414, 1701, 2239, 2293, 800,

792, 1278, 1203, 1510, 2215, 1651, 800

left.txt

576, 1238, 1414, 1701, 2239, 2293, 800,

833, 1037, 1522, 1918, 2239, 2293, 800

В скетче рабочей программы робота модели поведения будет храниться в 4 массивах, значения которых вам необходимо заполнить своими значениями. В моем случае эти массивы имеют вид:

int StepForvard[] = {

1079, 1733, 1749, 2046, 2239, 2293, 350,

1079, 1733, 2135, 2046, 2239, 2293, 350,

1079, 1733, 1509, 1741, 2241, 2293, 600,

1018, 1733, 1127, 1094, 2286, 2293, 350,

776, 1454, 1115, 1645, 1629, 1608, 350,

776, 1454, 1115, 1065, 1629, 1608, 350,

776, 1291, 1438, 1615, 1629, 1608, 600,

776, 1291, 1997, 1972, 1629, 1608, 350};

 

int StepRevers[] = {

776, 1291, 1997, 1972, 1629, 1608, 550,

776, 1291, 1438, 1615, 1629, 1608, 950,

776, 1454, 1115, 1065, 1629, 1608, 550,

776, 1454, 1115, 1645, 1629, 1608, 550,

1018, 1733, 1127, 1094, 2286, 2293, 550,

1079, 1733, 1509, 1741, 2241, 2293, 950,

1079, 1733, 2135, 2046, 2239, 2293, 550, 

1079, 1733, 1749, 2046, 2239, 2293, 550};

 

int StepRight[] = {

576, 1238, 1414, 1701, 2239, 2293, 800,

792, 1278, 1203, 1510, 2215, 1651, 800};

 

int StepLeft[] = {

576, 1238, 1414, 1701, 2239, 2293, 800,

833, 1037, 1522, 1918, 2239, 2293, 800};

Так же вам естественно придется исправлять как и в случае с исходником beepod_model.ino (на котором робот работает с Beepod Controller) следующие параметры:

1) Исходную позицию. В исходнике указана моя:

int StartPos[] = {576, 1238, 1414, 1701, 2239, 2293, 500};

соответственно последнее число оставляем тем же, но впоследствии, вы можете менять и это временную константу.

2)Необходимо установить ваши пределы изменения сервоприводов

int MinTiming = 400;

int MaxTiming = 2800;

ставите те же значения, что и ставили в прошлом исходнике

3)    Если вы внимательно изучите исходник, то поймете что массивы с моделями «проигрываются» с помощью функции PlaySteps(массив_модели, число_шагов). Т.о. если в разработанных вами моделях количество шагов будет отличатся от моего, вам придется исправить константы хранящие эти числа:

int ForwardStepCount = 8;

int ReversStepCount = 8;

int RightStepCount = 2;

int LeftStepCount = 2;

4) Вам придется опытным путем подбирать значение константы:

int MinDist = 200;

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

Дальше я приведу, рабочий скетч робота, который вы после адаптации под свои условия можете заливать на робота и начинать бесконечную чреду его совершенствования. В чем, я могу вам пожелать только удачи и терпения.

#include <Servo.h> //Подключение библиотеки Servo

int SensorPin = A0; // Сенсор

int ServCount = 6; // Количество сервоприводов

int MinDist = 200; // Порог определения фронтальных препятствий

int MinTiming = 400; //Рабочий предел сервоприводов (минимум)

int MaxTiming = 2800; // Рабочий предел сервоприводов (максимум)

int StartTimeOut = 5000; //Длительность паузы после включения

int ForwardStepCount = 8; //Количество шагов в модели Forward

int ReversStepCount = 8; // Количество шагов в модели Revers

int RightStepCount = 2; // Количество шагов в модели Right

int LeftStepCount = 2; // Количество шагов в модели Left

int Entrop = 10; //Максимальный предел энтропийных флюктуаций

int NumControl[] = {3,4,5,6,7,8}; //Массив номеров выводов с сервоприводами

//Координаты исходной позиции

int StartPos[] = {576, 1238, 1414, 1701, 2239, 2293, 500};

// Переменная для хранения значения таймера обратного хода

unsigned long ReversTimer = 0;

unsigned long ReversTimeOut = 18000; //Константа хранящая предел таймера

boolean isReversTimer=false; //Флаг запущенности таймера

int Signal = 0; //Переменная хранит результат измерения сенсора

Servo Servos[6]; //Массив сервоприводов

int APos[6]; //Массив хранит прошлую позицию

//Модель поведения forward

int StepForward[] = {

1079, 1733, 1749, 2046, 2239, 2293, 350,

1079, 1733, 2135, 2046, 2239, 2293, 350,

1079, 1733, 1509, 1741, 2241, 2293, 600,

1018, 1733, 1127, 1094, 2286, 2293, 350,

776, 1454, 1115, 1645, 1629, 1608, 350,

776, 1454, 1115, 1065, 1629, 1608, 350,

776, 1291, 1438, 1615, 1629, 1608, 600,

776, 1291, 1997, 1972, 1629, 1608, 350};

//Модель поведения revers

int StepRevers[] = {

776, 1291, 1997, 1972, 1629, 1608, 550,

776, 1291, 1438, 1615, 1629, 1608, 950,

776, 1454, 1115, 1065, 1629, 1608, 550,

776, 1454, 1115, 1645, 1629, 1608, 550,

1018, 1733, 1127, 1094, 2286, 2293, 550,

1079, 1733, 1509, 1741, 2241, 2293, 950,

1079, 1733, 2135, 2046, 2239, 2293, 550, 

1079, 1733, 1749, 2046, 2239, 2293, 550};

//Модель поведения right

int StepRight[] = {

576, 1238, 1414, 1701, 2239, 2293, 800,

792, 1278, 1203, 1510, 2215, 1651, 800};

//Модель поведения left

int StepLeft[] = {

576, 1238, 1414, 1701, 2239, 2293, 800,

833, 1037, 1522, 1918, 2239, 2293, 800};

 

//Функция производит плавный одновременный переход сервоприводов

//из текущей позиции в заданную параметром xPos

void MovePos(int xPos[]){

int Delta=0; //Переменная для хранения величины приращения

int MaxDelta=0; //Переменная для хранения максимальной величины приращения

unsigned long a=0; 

  unsigned long b=0;

  unsigned long TimeIter=0;  //Переменная для итерации таймера

unsigned long DeltaTime=0; //Переменная для хранения времени выполнения кода

// Переменная для хранения временной точки начала отчета

unsigned long TimePoint=0;

//В данном цикле вычисляется максимальная величина приращения

for (int i=0; i<ServCount; i++){

    Delta=abs(APos[i]-xPos[i]); 

    if (MaxDelta < Delta) MaxDelta = Delta;

}

//Переменная делится на 10. Если не уменьшить значение переменной,

//то при больших приращениях не хватит процессорного времени для

// выполнения  за малые периоды времени

MaxDelta/=10;

//Цикл с количество итераций равным числу дискретных приращений при переходе из

// текущего положения в заданное

for (int i=0; i<MaxDelta; i++)

//Цикл с 6 повторениями для последовательного приращения на каждом из 6 приводов

    for (int j=0; j<ServCount; j++){

      TimePoint = micros();//Сохранение временной точки

//Перемещение j-того сервопривода на i-том шаге на величину равную

//1/MaxDalta*величину общего приращения для j-того сервопривода

      Servos[j].writeMicroseconds(map(i,0,MaxDelta,APos[j],xPos[j]));

      a=xPos[ServCount]*1000.0;

      b=MaxDelta*ServCount;

      TimeIter=a/b; //Вычисление необходимой длины паузы

//Вычисление времени затраченного на выполнение кода от

//сохранения TimePoint до этого момента

      DeltaTime=micros()-TimePoint;

//Если итерация выполнена за время меньше чем необходимая пауза – делаем паузу

      if (DeltaTime<TimeIter) delayMicroseconds(TimeIter-DeltaTime);

    }

//В этом цикле новое положение перемещают в массив APos для

//последующего использования в качестве «прошлого» значения

for (int i=0; i<ServCount; i++) APos[i]=xPos[i];

}

 

void setup(){

//В этом цикле инициализируются сервоприводы и текущее значение

//сервоприводов сохраняется в качестве «прошлого» значения

for (int i=0; i<ServCount; i++){

    Servos[i].attach(NumControl[i],MinTiming,MaxTiming);

    APos[i]=Servos[i].readMicroseconds();

}

MovePos(StartPos); //Переход в исходную позицию

delay(StartTimeOut); //Стартовая пауза

}

 

//Эта функция производит «проигрывание» моделей поведения.

//Ей сообщается массив хранящий массив модели и число шагов.

void PlaySteps(int arSteps[], int StepCount){

  int arTMP[ServCount+1]; //В этом массиве хранится 1 шаг модели

//Цикл с числом итераций равным числу шагов модели

for(int i=0; i<StepCount; i++){

//Цикл с 6 итерациями

    for(int j=0; j<ServCount+1; j++)

//В массив переносится i-тый шаг модели

      arTMP[j]=arSteps[j+(ServCount+1)*i]+random(-Entrop, Entrop);

    MovePos(arTMP); //Перемешение на i-тый шаг модели

  }

}


//Функция делает 10 замеров показания сенсора и возвращает среднее арифметическое

int CheckSensor(){

int summ = 0; //Переменная для хранения суммы

for (int i=0; i<10; i++) //Цикл 10 операций

    summ+=analogRead(SensorPin); //Полученные значения суммируются

return summ/=10; //деление на 10 и возврат

}

 

//ОСНОВНАЯ ЧАСТЬ

void loop()

{

Signal=CheckSensor();//Получение среднего значения сенсора

if (Signal>MinDist){ //Если цель ближе чем надо

    if (!isReversTimer){ //Если таймер не включен

      isReversTimer=true; //Включение таймера

      ReversTimer=millis();//Сохранение временной точки

    }

    else{//Если таймер включен

//Если таймер работает больше чем время до включения реверса

      if (millis()-ReversTimer>ReversTimeOut){

//10 шагов назад с возможным выходом, если до препятствия меньше порога

        for(int i=0; i<10; i++){

          PlaySteps(StepRevers,ReversStepCount);

          if (CheckSensor()<MinDist)break;

        }

        ReversTimer=millis();//Обнуление таймера

      }

    }

    if (random(2)==1){ //Если 1 то..

      PlaySteps(StepRight,RightStepCount); //Делаем поворот вправо

      if(Signal<CheckSensor())//Если до цели по прежнему меньше порога

//Цикл из 10 поворотов влево с возможным выходом,

//если до препятствия меньше порога

        for(int i=0; i<10; i++){ 

          PlaySteps(StepLeft,LeftStepCount);

          delay(400);

          if (CheckSensor()<MinDist)break;

        }      

    }else{//если 0..

      PlaySteps(StepLeft,LeftStepCount); //Делаем поворот влево

      if(Signal<CheckSensor())//Если до цели по прежнему меньше порога

//Цикл из 10 поворотов вправо с возможным выходом,

//если до препятствия меньше порога

        for(int i=0; i<10; i++){ 

          PlaySteps(StepRight,RightStepCount);

          delay(400);

          if (CheckSensor()<MinDist)break;

        }      

    }

  }

  else{//Если нет препятствий..

    isReversTimer=false; //Отключение таймера

    PlaySteps(StepForward,ForwardStepCount);//Шагаем вперед

  }

}

Заключение.

Наконец-то статья подходит к концу и очень хочется надеяться, что кому-то она будет полезна. В заключении хочу сообщить некоторую сводную информацию, а так же оставить свои контакты на тот случай если вам потребуется моя помощь, либо возникнуть какие-либо предложения или замечания по статье.

В статье используются следующие компоненты:

Кронштейн Многоцелевой для серво Gekko ASB-04 (пара)

Кронштейн "П" для серво Gekko ASB-09 (пара)

Кронштейн "Г" для серво Gekko ASB-06 (пара)

Кронштейн Швеллер для серво Gekko ASB-53

Кронштейн Стопа робота Gekko ARF-01 (пара)

Сервопривод Feetech FS5103B

Набор из 4 качалок для серво

Контроллер DFRduino Nano v3 на ATmega328 + FT232RL (arduino)

Плата расширения ввода/вывода DFRobot v1 для Arduino Nano

Держатель батареи 4-AA закрытый с выключателем

Датчик дальности Sharp GP2Y0A21YK0F 10-80см (аналоговый)

Держатель сенсора Gekko ASH-01

Кабель 3-жильный 2.54 мм М -> JST (30 см)

Разъем розетка 3-вывода шаг 2.54 мм (10 штук)

Винт DIN7985 М3х20 (10 штук)

Гайка DIN934 М3 (10 штук)


Ссылки на файлы:

3D модель робота

Программа Beepod Controller

Архив соскетчами


Контактная информация:

Гончаров Денис aka execom

e-mail: virusoff@pisem.net или execon@nm.ru

icq: 103-756;   skype: execom5

В завершение, хочу выразить признательность администрации интернет-магазина РОБОТОТЕХНИКА, в лице Геннадия Чернышева за предоставленные материалы.