Сегодня в нашем клубе технического творчества стояла задача сборки и программирования робота-манипулятора. После непродолжительных поисков уже существующей конструкции, которой можно воспользоваться, наш выбор упал на открытый проект MeArm.
Он включает в себя несколько деталей, соединяющихся по определённой схеме винтиками. В результате получается робот-рука, с приводящими её в движение четырьмя моторами. Мы купили набор на ближайшем радиорынке. Детали в нём сделаны в Китае из фанеры, нарезанной лазером.
В механизме используется серводвигатель «Tower Pro Mikro Servo 9G SG90».
Серводвигатель – это специальный электродвигатель с отрицательной обратной связью, который предназначен для применения в станках с ЧПУ (числовым программным управлением). Они обладают высокой точностью позиционирования, миниатюрными размерами, большими скоростями.
От мотора отходят три провода.
Красный провод — питание.
Коричневый — земля.
Желтый — сигнальный или информационный провод.
По желтому проводу мы подаём команды, на какой угол совершить оборот двигателю.
Робот приводится в движение четырьмя моторами. Один — круговое вращение, второй — движение вверх-вниз, третий — вперед-назад, четвёртый — открывает-закрывает клешню.
После сборки робота, нужно сделать систему управления и написать для неё программу. В качестве управляющего элемента мы выбрали миниатюрную плату Arduino NANO.
Она удобна в использовании благодаря небольшому размеру, но её контактные ножки направлены вниз, поэтому для удобства подключения проводов требуется сделать вспомогательный переходник.
Мы воспользовались макетной платой.
С верхней стороны припаяли к ней разъемы для подключения всех контактов Arduino, а также штырьки (по 3 шт в ряду), для подключения сервомоторов робота. Еще припаяли конденсатор для уменьшения помех по питанию от работающих моторов.
С обратной стороны соединили проводками определённые контакты от моторов с контактами на Arduino.
К самому первому ряду должны подключаться коричневые провода от моторов, то есть «минуса». От этих объединённых контактов тянется провод к контакту Arduino «GND» - «земля». Ко второму ряду присоединяются красные провода «+». Их нужно объединить вместе, соединить с ножкой конденсатора и вывести на контакт Arduino 5V. То есть, на них будет подаваться питание в 5V. Третий ряд — это желтые провода. Каждый из них соединяется с цифровыми контактами Arduino с D4 по D7 — это для моторов, и с аналоговыми контактами с A1 по А4 — для управляющих моторами элементов.
Все соединение с Arduino должно осуществляться по схеме:
Затем, устанавливаем плату Arduino NANO на своё место.
Подключаем к устройству провода от четырёх моторов, так, чтобы жёлтые провода соединялись с цифровыми контактами с D4 по D7.
Три мотора у нас подключились нормально, а провод от верхнего мотора не дотягивался. Мы удлинили его, воспользовавшись вот таким набором проводочков с разъёмами на концах.
Собранное устройство уже можно программировать.
Первое, что нужно было выяснить — это максимальный и минимальный угол поворота каждого из моторов в данной конструкции.
Напишем небольшую программу, которая просто посылает определённому мотору команду повернуться на такой-то угол.
/*Программа для робота-манипулятора MeArm. Задаёт для четырёх моторов определённый угол поворота*/
//подключаем библиотеку servo /*создаём четыре объекта класса servo, для каждого мотора*/ /*стандартная функция с начальной инициализацией всех компонентов //задаём углы поворота для моторов (от 0 до 180) /*стандартная функция с реализацией программы, в которой все действия циклически повторяются*/ |
С помощью этой программы определяем возможные границы вращения для каждого из моторов.
Мы установили следующие:
для мотора, поворачивающего руку - от 0 до 180 градусов,
двигающего вверх-вниз - от 60 до 160 градусов,
двигающего вперё-назад - от 90 до 160 градусов,
открывающего-закрывающего клешню от 0 до 40 градусов.
Зная границы — можно написать программу посложнее, которая задает определённое поведение всей конструкции.
В новой программе нам сразу нужно определить ключевые слова (INI — начальное положение мотора, MAX — максимальное положение мотора, MIN — минимальное положение мотора, CUR — текущее положение мотора). Эти переменные будут индексами, дающими доступ к цифрам, разным для каждого из четырёх моторов.
Информацию о каждом моторе удобнее хранить в структуре, которую мы назвали SERVO_MOTOR.
В ней хранится объект класса servo, массив positions_data, содержащий установки мотора: его 0-й элемент (соответствует INI) — это начальное положение мотора, 1-й (MAX) — максимально возможное положение мотора, 2-й (MIN) — минимально возможное, 3й (CUR) — текущее положение.
Еще структура будет содержать целочисленный массив steps, задающий поведение мотора за определённое количество шагов, у нас это — 16.
Каждый его элемент ссылается на одну из трёх установок positions_data (INI, MAX или MIN), то есть ссылается на угол поворота, к которому плавно, продвигаясь на 1 градус мотор перейдёт из текущего положения.
Создаём четыре объекта структуры SERVO_MOTOR.
Инициируем объекты в функции InitServoObjects(), присваивая каждому мотору, по примеру предыдущей программы номер контакта Arduino, границы вращения и программу поведения.
Программа сделана для детей таким образом, чтобы им легко было вносить изменения.
Достаточно переставить местами или поменять переменные MIN, MAX и INI в инициализации, как рука будет вести себя по-другому.
В цикле loop() реализуем вращение всех моторов.
Ниже полный код программы с подробными пояснениями.
/*Программа для робота-манипулятора MeArm. Задаёт определённое, циклически повторяющееся поведение робота*/ //подключаем библиотеку servo #include <Servo.h> /*определяем ключевые слова (INI — начальное положение мотора, MAX — максимальное положение мотора, MIN — минимальное положение мотора, CUR — текущее положение мотора), которые будут использоваться как индексы для доступа к цифрам, своим для каждого мотора*/ /*константная глобальная переменная, хранящая количество шагов в задаваемой программе, по достижению последнего шага, программа воспроизводится с начала*/ /*глобальная переменная, хранящая количество шагов уже совершенных программой (всё время меняется)*/ /*константные глобальные переменные хранящие время задержки в мс*/ /*Структура, хранящая всю необходимую информацию о моторе*/ //создаём четыре объекта структуры SERVO_MOTOR /*функция InitServoObjects содержит начальную инициализацию всех четырёх моторов*/ //Инициируем объект servo_round servo_round.positions_data[INI] = 90; //начальный угол поворота /*присваиваем массиву объекта steps данные из заданного в начале функции локального массива*/ //задержка //Инициируем объект servo_up /*присваиваем массиву объекта steps данные из заданного в начале функции локального массива*/ //задержка //Инициируем объект servo_front /*присваиваем массиву объекта steps данные из заданного в начале функции локального массива*/ //задержка //Инициируем объект servo_hand /*присваиваем массиву объекта steps данные из заданного в начале функции локального массива*/ //задержка /*функция поворачивает мотор в нужном направлении на 1 градус. Принимает ссылку на объект структуры SERVO_MOTOR, возвращает true, если мотор повёрнут на заданный в массиве steps градус, false, если еще не дошёл*/ /*стандартная функция с начальной инициализацией всех компонентов /*стандартная функция с реализацией программы, в которой все действия циклически повторяются*/ /*если все моторы завершили поворот, переходим к следующему шагу — увеличиваем переменную current_prog_step на 1 и проверяем на выход за предел максимально возможного количества шагов*/ //задержка |
Следующая задача — сделать так, чтобы ребенок мог использовать блок управления моторами.
В качестве рукоятки мы использовали переменный резистор.
Мы припаяли к ему три провода, помня, что информационный (у нас жёлтый провод) должен быть центральным.
Всего у нас должно быть 4 таких рукоятки, каждая отвечает за работу своего мотора.
Чтобы объединить их вместе в один блок, мы разработали и напечатали на 3D принтере такой элемент.
В его ячейки мы продеваем все 4 рукоятки и подключаем к нашему устройству так, чтобы провода-заземления шли по первому ряду контактов на печатной плате, красные провода-питания по второму ряду, а желтые провода, подключались к третьему ряду, где они соединяются с
аналоговыми контактами Arduino с A1 по А4.
Затем надеваем на переменные резисторы красивые колпачки и устройство готово.
Программа для него сходна с предыдущей, но в ней исключается массив, задающий поведение моторов, зато в цикле loop() включается обработка информации от аналоговых контактов, регистрирующих в каком положении находятся рукоятки-переменные резисторы, и на основании этих данных рассчитывается положение мотора в рамках установленных для него границ вращения.
Ниже полный код программы с подробными пояснениями.
/*Программа для робота-манипулятора MeArm. Получает данные от четырёх переменных резисторов и устанавливает моторы робота в положения, соответствующие этим данным*/
//подключаем библиотеку servo /*определяем ключевые слова (INI — начальное положение мотора, MAX — максимальное положение мотора, MIN — минимальное положение мотора, STP — сколько единиц, полученных с аналоговых контактов переменных резисторов соответствуют 1 градусу поворота мотора, CUR — текущее положение мотора), которые будут использоваться как индексы для доступа к цифрам, своим для каждого мотора*/ /*константные глобальные переменные хранящие время задержки в мс*/ /*назначаем константным переменным номера аналоговых контактов, к которым подключены переменные резисторы*/ //переменная, хранящая считаный результат аналогового контакта /*Структура, хранящая всю необходимую информацию о моторе*/ //создаём четыре объекта структуры SERVO_MOTOR /*функция InitServoObjects содержит начальную инициализацию всех четырёх моторов*/ //Инициируем объект servo_up //Инициируем объект servo_front //Инициируем объект servo_hand /*стандартная функция с начальной инициализацией всех компонентов /*стандартная функция с реализацией программы, в которой все действия циклически повторяются*/ /*осуществляем проверку, если значение превысило максимально возможное, либо если оно не изменилось по сравнению с предыдущим, то ничего делать не нужно*/ //считываем данные со второй рукоятки (переменного резистора) //считываем данные с третьей рукоятки (переменного резистора) //считываем данные с четвёртой рукоятки (переменного резистора) //задержка |