Как сделать робота для сборки кубика Рубика

Как сделать робота для сборки кубика Рубика

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

Я не первый, кто реализовал эту идею. Есть, например, робот из набора Lego Mindstorms или конструкция с сайта Otvinta.com.

Мне не хотелось повторять уже готовое изделие. Чтобы лучше понимать, как функционирует робот, и научиться чему-то новому, я решил делать все сам.

Подробно о том, как начать свою карьеру в электротехнике, читайте в статье «Как научиться электронике и схемотехнике».

Выбор платформы

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

Для механической составляющей я решил использовать проект с сайта Otvinta.com и взяли за основу их конструкцию. Ее детали можно легко распечатать на 3D-принтере. Конструкторы Lego, например, удобны в сборке, но они очень дорогие, да и пристроить к ним нестандартные части и блоки очень сложно.

Для электронного блока управления, в качестве платформы мы решили остановиться на смартфоне на Android и микроконтроллере Arduino, связанные через USB. На наш взгляд, это оптимальная платформа для создания простых и дешевых роботов.

Камера, Bluetooth, Wi-Fi, USB, GPS-датчик, сенсорный дисплей для управления, достаточно мощный процессор и большой объем памяти — это то что нам необходимо и имеется у всех современных бюджетных смартфонов. И это значительно уменьшает стоимость проекта!

Чтобы управлять сервоприводами, считывать информацию с внешних датчиков, получать управляющие команды со смартфона по USB и отправлять на него нужные данные, т.е.отвечать за процессы реального времени нам нужен — Микроконтроллер Arduino.

Учитывая все эти требования мы выбрали смартфон Motorola Moto G и микроконтроллер Arduino Mega 2560.

Смартфон Motorola Moto G
Смартфон Motorola Moto G
Микроконтроллер Arduino Mega 2560
Микроконтроллер Arduino Mega 2560

Создание платы и сборка корпуса

Модели всех деталей для корпуса робота можно скачать и распечатать на 3D-принтере (ZIP). Лучше печатать с максимальной точностью. Я этот момент не учел, поэтому детали потом пришлось подправлять с помощью наждачной бумаги.

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

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

Крепеж я купил на строительном рынке. Корпус собирал по инструкции, это оказалось несложно.

Также роботу нужны два блока питания: на 12 В для Arduino и на 5 В для питания сервоприводов.

Механическая часть робота для сборки кубика Рубика
Механическая часть робота для сборки кубика Рубика

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

Робот собственной персоной для сборки кубика Рубика
Робот собственной персоной для сборки кубика Рубика собственной персоной

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

Управление сервоприводами

Управлять сервоприводами у нас будет микроконтроллер Arduino Mega 2560. Чтобы написать для него программу, понадобится средство разработки. Arduino IDE свободно распространяется в интернете и работает на любой современной ОС. После ее установки создаем новый скетч для написания исходного кода. Язык программирования похож на C, что сильно облегчит нашу работу.

Для работы с сервоприводами нам нужно подключить соответствующую библиотеку:

Затем объявить глобальные переменные, представляющие все наши восемь приводов:

Названия переменным даны по расположению устройств: например, servo_RS относится к приводу, который расположен справа и вращает держатель вокруг своей оси, а servo_RG также расположен справа и двигает держатель внутрь и наружу.

Также нужно объявить пины, к которым физически подключены наши моторчики:

Значения портов у тебя могут отличаться, все зависит от того, куда подключены провода.

Далее в функции setup() нам надо подключить пины к соответствующим переменным сервоприводов:

Теперь, если мы хотим установить какой-нибудь сервопривод на необходимый угол, нам надо вызвать функцию writeMicroseconds у соответствующей Servo. Аргумент, который передается в эту функцию, задает угол поворота сервопривода и может принимать значение от 1000 до 2000 для стандартного привода, но в нашем случае этот диапазон гораздо шире, подбирать конкретные значения для положения моторчиков нужно экспериментально.

Главной функцией нашей программы должно быть выполнение команд из формул для сборки кубика Рубика. Например, команда R означает повернуть правую грань кубика по часовой стрелке на 90 градусов, R' — повернуть эту же грань против часовой стрелки. Такие же команды существуют для каждой грани и имеют соответствующие названия: L — левая грань, U — верхняя, D — нижняя, B — задняя, F — передняя.

Вот функция, которая выполняет команду R:

Здесь функция move_RS_up() вращает правый держатель вверх по часовой стрелке, move_RG_right() двигает правый держатель вправо, move_RS_cent() вращает правый держатель против часовой стрелки в исходное положение, move_RG_left() двигает держатель влево. Функция delay(1000) создает задержку исполнения кода на одну секунду.

Вот, например, как выглядит функция move_RS_up():

А вот как выглядит функция move_RG_right():

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

ПО для смартфона

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

Программировать будем в Android Studio на Java.

Для отправки данных по USB существует много библиотек, но я выбрал библиотеку Омара Афлака.

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

Должен сказать, что это старая библиотека, но работает она неплохо.

Нам понадобится также возможность сохранять снимки в файл. Для этого добавляем в файл AndroidManifest.xml следующие строки:

Дальше в главном классе нашей программы в функцию onCreate() надо добавить следующий код:

Так мы спрашиваем у пользователя разрешение на использование камеры и на сохранение снимков в постоянную память.

Теперь нам надо объявить глобальные переменные:

И инициализировать их:

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

Все готово, чтобы делать фотографии граней кубика. Для этого нужно каждый раз вызывать вот этот код:

Обрати внимание на комментарии с номерами. Так мне будет проще рассказать, что же происходит.

  1. Начинаем делать снимок.
  2. Здесь arduino — это переменная для отправки команд на микроконтроллер. Мы отправляем три числа: 33 — символ начала посылки, 1 — число команд, которые мы отправляем, 21 — код команды повернуть кубик к камере необходимой гранью, эту команду нужно добавить в программу на Arduino.
  3. Делаем паузу выполнения программы на три секунды, чтобы подождать, пока сервоприводы повернут кубик.
  4. Делаем снимок и вызываем процедуру для его обработки.
  5. Сохраняем фотографию в файл.
  6. В последнем пункте мы должны написать код, который будет определять цвет каждого квадратика и сохранять его в массив.

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

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

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

Со сканированием кубика покончено, и нам остается только его собрать.

Сборка кубика Рубика

Для сборки кубика Рубика вручную существуют разные методики. Одна из самых распространенных — метод Джессики Фридрих. Он предполагает знание большого числа формул, но позволяет достичь цели за минимальное число ходов. Этот метод, конечно, можно было реализовать программно для нашего робота, но это была бы очень громоздкая реализация. Для численного решения кубика Рубика есть свои алгоритмы, и они позволяют найти решение с гораздо меньшим числом ходов.

Кубик Рубика всегда может быть решен не более чем в двадцать ходов, считая за один ход поворот любой из шести граней на 90 или 180 градусов. Известны конфигурации, требующие для сборки не менее двадцати ходов. Таким образом, «число Бога» кубика Рубика равно двадцати.

Я выбрал алгоритм Косимбы, потому что у него есть уже готовые реализации на Java, которые могут быть легко встроены в наш проект на Android Studio. Одну из таких реализаций можно найти на GitHub. Из этого проекта нам понадобятся только три файла: Search.java, Tools.java, Util.java. Скачиваем их и добавляем в свой проект в Android Studio. Теперь в каждом из этих файлов в самом верху после слова package нужно указать путь пакета, который соответствует твоему проекту.

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

Если все хорошо, она должна вернуть 0. Здесь facelet — это строковая переменная, содержащая цветовую конфигурацию кубика Рубика. Сейчас я расскажу, как ее правильно записать.

Цветовая карта кубика имеет следующий вид:

|            |
| U1  U2  U3 |
|            |
| U4  U5  U6 |
|            |
| U7  U8  U9 |
|            |            |            |            |
| L1  L2  L3 | F1  F2  F3 | R1  R2  F3 | B1  B2  B3 |
|            |            |            |            |
| L4  L5  L6 | F4  F5  F6 | R4  R5  R6 | B4  B5  B6 |
|            |            |            |            |
| L7  L8  L9 | F7  F8  F9 | R7  R8  R9 | B7  B8  B9 |
|            |            |            |            |
| D1  D2  D3 |
|            |
| D4  D5  D6 |
|            |
| D7  D8  D9 |
|            |

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

U1U2U3U4U5U6U7U8U9R1R2R3R4R5R6R7R8R9F1F2F3F4F5F6F7F8F9D1D2D3D4D5D6D7D8D9L1L2L3L4L5L6L7L8L9B1B2B3B4B5B6B7B8B9

Здесь вместо U1 надо писать код цвета квадратика по адресу U1. И так далее для всех адресов.

Как же определяется код цвета? Мы берем верхнюю грань U и смотрим, какого цвета ее центральный квадратик. Например, он красный, значит, все красные квадратики будут иметь код U. А если на нижней грани центральный квадрат имеет оранжевый цвет, значит, все оранжевые цвета имеют код D. Таким образом составляется строка состояния кубика.

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

В функцию solution передаются следующие параметры: facelet — строка состояния кубика, 25 — максимальное число команд, которое может быть в решении. Остальные параметры я оставил в исходном состоянии.

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

Замечу, что в решении среди команд могут быть варианты, например R2, что означает «повернуть правую грань два раза». Для каждой грани — отдельная команда. Ты без труда реализуешь их в Arduino IDE.

Запуск и тестирование робота для сборки кубика Рубика

Теперь у нас все готово, чтобы запустить нашего робота и как следует протестировать его. У меня он заработал с первого раза: кубик Рубика был собран. После многих повторений я обнаружил некоторые недостатки.

  1. Требовательность к освещению. Освещение должно быть не сильно ярким и не прямым. На кубике Рубика не должно быть бликов, иначе наш робот некорректно распознает цвета и не найдет решение.
  2. Кубик Рубика иногда застревает в нижнем держателе. Приходится останавливать сборку и начинать сначала. Чем вызвана эта неприятная особенность, пока неясно, возможно, надо подточить держатель, увеличив его ширину.
  3. Время сборки составляет примерно пять минут. Долго! Но можно еще поэкспериментировать с параметрами задержек в программе и попробовать за счет этого сократить время сборки.

Специалист по робототехнике Бен Кац (Ben Katz) и разработчик программного обеспечения Джаред Ди Карло (Jared Di Carlo) создали робота, который способен собрать кубик Рубика за 0,38 секунды.

На видео — робот в действии.

Робот кубика Рубика готов!

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

Скачать все исходники можно тут и тут.

Комплектующие обошлись мне примерно в 400 долларов США. Наверное, эту сумму стоит тоже отнести к недостаткам, робот получился недешевым. Главные затраты — на распечатку деталей на 3D-принтере. Но в конце концов, для любимого хобби ничего не жалко!

Понравилась статья? Поделиться с друзьями:
Добавить комментарий