[Прелесть робототехники] Очумелые ручки (robotics edition!)

[Прелесть робототехники] Очумелые ручки (robotics edition!)
Все статьи из цикла "В чем прелесть предмета"
Другие статьи из цикла "В чем прелесть робототехники":
  Такая разная робототехника
  Начало футуристического будущего: как создаются роботы
  Олимпиада по робототехнике: вдоль и поперек
  У роботов нет времени нас убивать
  Как робототехника решает проблемы людей с инвалидностью?

Часто, занимаясь чем-нибудь в качестве увлечения, мы ждем не дождемся, чтобы сделать что-то такое, что имело бы практическое применение. Увлекаясь живописью, мы вешаем свои картины на стену; обрабатывая дерево, мы можем запросто сделать красивую фигурку и подарить ее близкому человеку. Вариантов всегда настолько много, что описывать их можно целую вечность. А можно ли сделать что-то простое, но в то же время интересное и полезное? Ответ прост: не только можно, но и нужно!

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

Интернеты

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

Одним из таких проектов является робот InMoov, созданный французским известным скульптором Gael Langevin. В \(2011\) году человек, который не имел абсолютно никакого опыта в робототехнике, решил сделать полноценного робота-гуманоида. И стоит признать, что это у него получилось. Стал ли он продавать его? Нет! Стал ли он продавать чертежи и программный код от него? Ответ все тот же – нет. Вместо этого он сделал отдельный сайт, на котором опубликовал все чертежи, программный код и инструкцию по сборке в открытом доступе. И тут началась магия, которая чаще всего бывает только в среде робототехников и программистов. Люди стали абсолютно добровольно и бесплатно улучшать проект. Со временем сайт пополнялся новыми инструкциями, появлялись чертежи деталей, к которым можно было подключить альтернативные сервомоторы, новые программные коды. А некоторые энтузиасты даже поработали над тем, чтобы покрыть робота силиконовой кожей!

"InMoov (My Robot Lab), robot open source (Salon Viva Technology, Paris)" by dalbera is licensed under CC BY 2.0

И вот так день за днем, год за годом проект обрастает всё различными улучшениями, которые делают энтузиасты со всего мира на добровольных началах. А это значит, что, во-первых, каждый может приложить свою руку к созданию чего-то глобального и великого; стоит отметить, что InMoov community имеет \(6673\) членов из разных стран мира. Во-вторых, при должных усилиях, желании и везении вполне возможно самому создать подобные open-source проекты, которые будут востребованы и популярны во всем мире.

Сделай сам

Роботы из интернета – это, конечно, круто и интересно. Держу пари, хотя бы одного сделать захотелось каждому, кто читает эту статью. Но что если мы попробуем создать что-то свое? И тут мой читатель спросит меня: «А ЧТО ТАК МОЖНО?». Не только можно, но и нужно.

Поделюсь личной историей. У меня дома есть аквариум с рыбками, которых, конечно же, необходимо кормить раз-два в сутки. И вот для того, чтобы рыбки могли спокойно поесть и не гоняться за кормом, необходимо отключить аэратор буквально на \(10\)-\(15\) минут. И вот тут частенько происходит следующее: выключить его мы выключаем, а вот включить иногда забываем, из-за чего бедные рыбы могут провести весь день без воздуха, а бывали случаи, что рыбы и погибали. Казалось бы, просто не забудь включить аэратор перед тем, как все уйдут из дома! Однако человек не может быть совершенным и склонен делать огромное количество ошибок. Вот и тут полностью исключить такие повторные случаи не получится, как бы мы ни старались. Или можно? А если мы доверим это дело роботу? И тут встает вопрос, что это за робот, где его купить и за какие деньги. Спойлер: Деньги отдать придется, но робота мы сделаем сами.

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

  • Пластик ABS/PLA/PETG
  • \(3\)D-принтер (чаще всего распечатать детали можно на заказ)
  • Arduino Uno
  • Шаговый двигатель \(28\)BYJ-\(48\) с платой управления
  • Кнопка
  • Резистор \(10\) кОм
  • Реле (для тех, кто будет работать с \(220\) В)
  • Коннектор XT60 или аналогичный (для тех, кто будет работать с \(220\) В)
  • Провода
  • Паяльник, олово, канифоль/кислота
  • Винты М\(3\) и гайки М\(3\) х\(12\)

В первую очередь необходимо смоделировать \(3\)D-модель нашей конструкции, которая будет отвечать за кормление рыбок.

Для этого я буду использовать программу Autodesk Fusion \(360\), так как она является одной из самых удобных и функциональных для \(3\)D-моделирования.

Нам необходимо создать чертеж следующих деталей:

  1. Стойка, которая будет крепиться к стеклу аквариума. В ней мы расположим шаговый мотор.
  2. Крышка, которая закроет поверхность стойки, чтобы исключить попадания пыли, мусора и кусочков корма внутрь шагового мотора.
  3. Дозатор корма.
  4. Винт для фиксации стойки на стекле.
  5. Площадка для крепления платы

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

Стойка

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

Стойка

Крышка

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

Крышка. Вид снизу
Крышка, надетая на стойку. Вид снизу

Дозатор

Теперь смоделируем дозатор. Я хочу, чтобы у меня помещалось \(3\) порции. Учитывая отверстие, в которое будет падать корм, необходимо сделать диск с \(4\) отверстиями.

Дозатор

Болт барашковый

Осталось совсем ничего! Делаем барашковый болт, которым затянем, кормушку, надетую на стекло аквариума. В кормушке резьба М\(16\)х\(1\) (диаметром \(16\) миллиметров с шагом резьбы \(1\) миллиметр), а значит, и резьба на болте у нас должна иметь такие же характеристики.

Болт барашковый

Модуль крепления плат

Последний штрих. Помимо самой кормушки, у нас должен быть модуль крепления плат. Всего плат четыре: Arduino Uno, драйвер шагового мотора, реле и кнопка. Все эти компоненты, кроме кнопки, будут крепиться винтами М\(3\), упомянутыми выше. Также для удобства не забываем сделать отверстия для гаек сзади модуля для крепления плат.

Модуль крепления плат
Кормушка в сборе

3D-печать

Отлично! Все компоненты смоделированы и пора перейти к изготовлению деталей для кормушки. Для печати рекомендую пластик PETG, так как он довольно крепкий, температуроустойчивый и не требует тонких настроек для \(3\)D-печати. В качестве альтернативы можно рассмотреть и PLA, он биоразлагаемый, но может деформироваться из-за летней жары. Не рекомендую использовать ABS (хотя это возможно), так как он довольно токсичный и от нагревания издает едкий запах.

Настройки печати следующие:

  • Материал: PLA/PETG
  • Толщина слоя: \(0.35\) мм
  • Периметры: \(3\)
  • Заполнение: \(15\)%
  • Тип заполнения: Gyroid/Honeycomb/Cubic/Grid

Вот так выглядят напечатанные компоненты:

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

Сборка

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

Рис. 1

Теперь собираем саму кормушку. В стойку устанавливаем наш шаговый мотор, накрываем его крышкой и подключаем коннектор мотора в драйвер (рис.2).

Рис. 2
Так как работа с переменным напряжением довольно опасна, настоятельно не рекомендую выполнять данный этап сборки тем, кто никогда до этого не имел опыта с подобными конструкциями. (прим. автора)

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

Полная схема подключения

Также я добавил коннектор XT\(60\) для того, чтобы можно было отключить аэратор от реле, чтобы его помыть отдельно. Важно заметить, что сначала отключаем аэратор из розетки, а потом лишь отсоединяем коннектор, не наоборот!

Поздравляю, этап сборки окончен и теперь остается написать программный код!

Программирование

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

int rel = 3; //Реле
int in1 = 8; //in1-4 драйвер шагового мотора
int in2 = 9;
int in3 = 10;
int in4 = 11;

Далее мы должны прописать конфигурацию портов, так как каждый может как принимать электрический импульс, так и отдавать его.

Сделаем это в функции void setup(), которая выполняется лишь один раз за все время работы системы.

void setup() {
    pinMode(btn, INPUT); //так как кнопка посылает сигнал на плату, ставим аргумент INPUT
    pinMode(rel, OUTPUT); //так как остальные компоненты принимают сигнал из платы, то ставим аргумент OUTPUT
    pinMode(in1, OUTPUT);
    pinMode(in2, OUTPUT);
    pinMode(in3, OUTPUT);
    pinMode(in4, OUTPUT);
}

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

Одна итерация вращения программируется следующим образом:

digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
delay(5);
digitalWrite(in1, HIGH);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
delay(5);
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
delay(5);
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, HIGH);
delay(5);

Однако нам необходимо повернуть мотор на \(90\) градусов, а одной итерации, естественно, не хватит. “Методом тыка” я выяснил, что для поворота на \(90\) градусов необходимо совершить \(128\) итераций подряд. Для этого мы поместим данный код в цикл, а функция будет принимать значение n – количество итераций. Полная функция выглядит так:

void rotate(int n){
    for(int i = 0; i < n; i++){
        digitalWrite(in1, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in4, HIGH);
        delay(5);
        digitalWrite(in1, HIGH);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in4, LOW);
        delay(5);
        digitalWrite(in1, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, LOW);
        delay(5);
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, HIGH);
        delay(5);
    }
}

Дальнейший код, а значит и работа кормушки, зависит лишь от того, какой алгоритм мы хотим реализовать. Лично я хочу, чтобы кормушка при включении в розетку не выполняла никаких функций, ожидая нажатие на кнопку. После того, как на кнопку нажмут в нужное время, шаговый мотор повернет дозатор, отключит аэратор на \(5\) минут и повторит вышеописанные шаги лишь через \(24\) часа.

В первую очередь, необходимо модифицировать функцию void setup(). В ней пропишем бесконечный цикл, выход из которого будет осуществлен только тогда, когда мы нажмем на кнопку. Почему именно в void setup()? Потому что на кнопку нажать необходимо лишь один раз. А как мы уже узнали выше, эта функция срабатывает ровно один раз. Также после этого считаем сколько прошло времени с момента начала работы платы Arduino, в будущем нам это пригодится. И не забудем разомкнуть реле, чтобы наш аэратор работал. В финале вид функции приобретет следующий вид:

void setup() {
    Serial.begin(9600);
    pinMode(btn, INPUT);
    pinMode(rel, OUTPUT);
    pinMode(in1, OUTPUT);
    pinMode(in2, OUTPUT);
    pinMode(in3, OUTPUT);
    pinMode(in4, OUTPUT);
    digitalWrite(rel, 0); //включаем аэратор
    while(!digitalRead(btn)); //ожидание нажатия кнопки
    milin = millis(); //считывание количество времени, которое было потрачено на ожидание нажатия кнопки
}

Теперь осталось самое простое. В Arduino также есть и циклическая функция void loop(), которая бесконечно будет выполнять тот код, который в ней прописан. Именно в ней мы и пропишем кормежку раз в сутки и отключение аэратора на \(5\) минут. Алгоритм следующий: поворачиваем дозатор на \(90\) градусов, отключаем аэратор, ждем \(5\) минут, включаем аэратор и ждем сутки. Для ожидания можно использовать функцию delay(), но тогда работа микроконтроллера будет парализована. Я хочу сделать, чтобы ожидание было реализовано так, что параллельно могли бы выполняться другие функции, хоть их сейчас и не будет. Для этого мы будем использовать функцию millis(), которая возвращает значение в миллисекундах. У нас уже есть переменная milin, которая хранит в себе время с начала работы кормушки. Таким образом, будем использовать следующую формулу для нахождение времени в секундах, прошедшего с начала работы: millis()-milin)/1000. А для того, чтобы проверить, прошло ли определенное время с начала работы кормушки, найдем остаток от деления прошедшего времени на необходимое время X в секундах. Формула выглядит следующим образом: (millis()-milin)/1000) mod X. Если остаток равен нулю, то необходимое время прошло. Используем эти формулы ожидания в нашей циклической функции.

void loop() {
    rotate(128); //поворот дозатора на 90 градусов
    digitalWrite(rel, 1); //отключение аэратора
    while(((millis()-milin)/1000)%300 != 0 && ((millis()-milin)>1000));//пауза 5 минут
    digitalWrite(rel, 0); //включение аэратора
    while(((millis()-milin)/1000)%86400 != 0 && ((millis()-milin)>1000)); //пауза сутки
}

Полный код выглядит следующим образом:

int btn = 2;
int rel = 3;
int in1 = 8;
int in2 = 9;
int in3 = 10;
int in4 = 11;
int milin = 0;
int milfin = 0;

void rotate(int n){
    for(int i = 0; i < n; i++){
        digitalWrite(in1, HIGH);
        digitalWrite(in2, LOW);
        digitalWrite(in3, LOW);
        digitalWrite(in4, HIGH);
        delay(5);
        digitalWrite(in1, HIGH);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, LOW);
        digitalWrite(in4, LOW);
        delay(5);
        digitalWrite(in1, LOW);
        digitalWrite(in2, HIGH);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, LOW);
        delay(5);
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
        digitalWrite(in3, HIGH);
        digitalWrite(in4, HIGH);
        delay(5);
    }
}

void setup() {
    Serial.begin(9600);
    pinMode(btn, INPUT);
    pinMode(rel, OUTPUT);
    pinMode(in1, OUTPUT);
    pinMode(in2, OUTPUT);
    pinMode(in3, OUTPUT);
    pinMode(in4, OUTPUT);
    digitalWrite(rel, 0);
    while(!digitalRead(btn));
    milin = millis();
}

void loop() {
    rotate(128);
    digitalWrite(rel, 1);
    while(((millis()-milin)/1000)%300 != 0 && ((millis()-milin)>1000));
    digitalWrite(rel, 0);
    while(((millis()-milin)/1000)%86400 != 0 && ((millis()-milin)>1000));
}

Итог

На этом все! Мы успешно придумали, смоделировали, собрали и запрограммировали проект, который немного улучшит если не вашу жизнь, то уж точно жизнь братьев наших меньших. Стоит отметить, что данная кормушка может иметь сотни недочетов и потенциальных исправлений. К примеру, я бы сделал так, чтобы при дополнительном нажатии на кнопку выдавалась еще одна доза корма, без изменения расписания кормежки. А так как мы первую часть посвятили open-source проектам, то все чертежи я оставлю на Thingiverse.

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

Фонд «Beyond Curriculum» публикует цикл материалов «В чем прелесть предмета» в партнерстве с проектом «Караван знаний» при поддержке компании «Шеврон». Караван знаний – инициатива по исследованию и обсуждению передовых образовательных практик с участием ведущих казахстанских и международных экспертов.