Статьи

Создайте свой собственный манипулятор – пульт дистанционного управления

В предыдущей части этой серии микросхем я обсуждал способ управления всеми сервоприводами одновременно. Программно без какого-либо внешнего взаимодействия. Это просто не будет делать. Последним шагом в этом проекте, очевидно, является дистанционное управление, которое добавит еще один уровень сложности, а также веселья. Присоединяйтесь ко мне и давайте посмотрим, что нужно, чтобы подключить эту манипулятор робота MeArm к контроллеру PlayStation 4. Если вы пропустили введение в программирование этой руки, ознакомьтесь с моим предыдущим постом Постройте свою собственную руку робота — программирование .

Что вам нужно

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

  • USB Host shield 2.0 (доступно здесь — примерно 23 €)
  • Адаптер Bluetooth (как этот — примерно 8 €, но его можно купить в Китае дешевле)
  • Контроллер PlayStation 4 (доступно на Amazon — примерно 50 €, но, вероятно, это уже часть вашей игровой системы :))
  • Arduino IDE

USB Host щит

USB Host щит является неотъемлемой частью на данном этапе. Отличительной особенностью этого щита является его универсальность. Вы можете использовать проводной режим и подключить контроллер к экрану с помощью зарядного USB-кабеля или подключить адаптер Bluetooth и использовать его в беспроводном режиме. Еще одна замечательная вещь — вы можете использовать контроллер Xbox таким же образом. Учитывая архитектуру этих щитов, вы собираетесь сложить эти щиты. Во-первых, этот щит идет сверху вашей доски Arduino.

usb_host_shield_2

В зависимости от типа вашего соединения вы должны подключить адаптер Bluetooth прямо сейчас. Теперь установите серво щит сверху и подключите к нему все сервоприводы. В основании есть отверстия, которые используются для крепления платы Arduino на тот случай, если вы захотите получить дополнительную стабильность со своей сборкой. Как только все подключено и правильно подключено, вы можете перейти к следующему шагу — программированию.

блютус

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

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

PS4-FrontView

  • левая палочка
    • движение по оси Y
      • открывает и закрывает захват
  • правая палка
    • движение по оси X
      • поворачивает руку влево или вправо
    • движение по оси Y
      • расширяет и убирает руку
  • Кнопка X
    • сбрасывает руку в исходное положение
  • громыхание

PS4-Topview

И следующие элементы управления видны спереди:

  • триггеры
    • левый триггер
      • опускает руку
    • правый триггер
      • поднимает руку
  • Светодиодный
    • Потому что мы все знаем, что если он не мигает как сумасшедший, он не достаточно крутой 🙂
    • Синий мигающий свет
      • контроллер ищет соединение / соединение
    • Синий постоянный свет
      • контроллер подключен и готов к работе
    • Зеленый постоянный свет
      • рука робота находится в исходном положении и готова к работе
    • Красный мигающий свет

Собираем все вместе

Еще раз, все тяжелые работы сделаны для нас библиотекой. Нам потребуется версия 2.0 хост-библиотеки USB для Arduino от Circuits @ Home . Особая благодарность Kristian Sloth Lauszus и команде вокруг него, а также всем участникам проекта за создание и поддержку действительно милой библиотеки для использования этого щита. Проверьте GitHub-репозиторий для этой библиотеки, загрузите ее и добавьте в свою библиотечную коллекцию в Arduino IDE. Как обычно, пример раздела — ваш лучший друг, чтобы познакомиться с новой библиотекой или фреймворком.

Эскиз, который у меня получился, больше, поэтому давайте разберем его. Нам нужны 4 переменные, чтобы точно отслеживать текущее положение каждого сервопривода и их положение по умолчанию для отдыха. Прежде всего, я решил использовать USB как способ подключения моего контроллера во время разработки, чтобы метод установки инициировал подключение и установил начальные значения. Затем я определил специальный метод для каждого сервопривода, чтобы контролировать его движение и обрабатывать проверки при достижении физических пределов. Я знаю, что этот код можно уменьшить, но для ясности и облегчения обслуживания / читабельности я выбрал 4 специальных метода (на моей плате достаточно памяти, чтобы справиться с этим, чтобы не было проблем с размером).

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

Управление манипулятором с помощью контроллера PS4 через USB-эскиз

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include <Wire.h>
#include <PS4USB.h>
#include <Adafruit_PWMServoDriver.h>
 
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
USB Usb;
PS4USB PS4(&Usb);
 
#define BASE 0
#define HEIGHT 1
#define LENGTH 2
#define GRIP 3
 
float base_init = 1440;
float height_init = 1675;
float length_init = 1440;
float grip_init = 2155;
 
float base_current = base_init;
float height_current = height_init;
float length_current = length_init;
float grip_current = grip_init;
 
float SERVOFREQ = 50;
float pulseconstant;
boolean limit_reached = false;
 
void setup() {
    Serial.begin(9600);
 
    if (Usb.Init() == -1) {
        while (1);
    }
 
    pulseconstant = (1000000/SERVOFREQ)/4096;
 
    pwm.begin();
    pwm.setPWMFreq(SERVOFREQ);
 
    servoWrite(BASE, base_init);
    servoWrite(HEIGHT, height_init);
    servoWrite(LENGTH, length_init);
    servoWrite(GRIP, grip_init);
 
    PS4.setLed(Green);
}
 
void handleBase() {
    // check to stop the servo
    if (base_current - 10 <= 525 && PS4.getAnalogHat(RightHatX) > 220) {
        limit_reached = true;
        return;
    } else if (base_current + 10 >= 2355 && PS4.getAnalogHat(RightHatX) < 35) {
        limit_reached = true;
        return;
    } else {
        // handle movement
        if (PS4.getAnalogHat(RightHatX) < 35) {
            base_current += 10;
        }
        if (PS4.getAnalogHat(RightHatX) > 220) {
            base_current -= 10;
        }
    }
}
 
void handleReach() {
    // check to stop the servo
    if (length_current - 10 <= 525 && PS4.getAnalogHat(LeftHatY) > 220) {
        limit_reached = true;
        return;
    } else if (length_current + 10 >= 2355 && PS4.getAnalogHat(LeftHatY) < 35) {
        limit_reached = true;
        return;
    } else {
        // handle movement
        if (PS4.getAnalogHat(LeftHatY) < 35) {
            length_current += 10;
        }
        if (PS4.getAnalogHat(LeftHatY) > 220) {
            length_current -= 10;
        }
    }
}
 
void handleHeight() {
    // check to stop the servo
    if (height_current - 10 <= 1100 && PS4.getAnalogButton(L2) > 220) {
        limit_reached = true;
        return;
    } else if (height_current + 10 >= 2250 && PS4.getAnalogButton(R2) > 220) {
        limit_reached = true;
        return;
    } else {
        // handle movement
        if (PS4.getAnalogButton(L2) > 220) {
            height_current -= 10;
        }
        if (PS4.getAnalogButton(R2) > 220) {
            height_current += 10;
        }
    }
}
 
void handleGripper() {
    // check to stop the servo
    if (grip_current - 10 < 1800 && PS4.getAnalogHat(RightHatY) < 220) {
        return;
    } else if (grip_current + 10 > 2155 && PS4.getAnalogHat(RightHatY) > 35) {
        return;
    } else {
        // handle movement
        if (PS4.getAnalogHat(RightHatY) < 35) {
            grip_current -= 10;
        }
        if (PS4.getAnalogHat(RightHatY) > 220) {
            grip_current += 10;
        }
    }
}
 
void loop() {
    Usb.Task();
 
    if (PS4.connected()) {
        limit_reached = false;
 
        if (PS4.getButtonClick(CROSS)) {
            resetMeArm();
        }
 
        handleBase();
        handleReach();
        handleHeight();
        handleGripper();
 
        if (!limit_reached) {
            PS4.setLed(Green);
            PS4.setRumbleOff();
            PS4.setLedFlash(0, 0);
        } else {
            PS4.setLed(Red);
            PS4.setRumbleOn(RumbleHigh);
            PS4.setLedFlash(10, 10);
        }
    }
 
    delay(5);
    servoWrite(BASE, base_current);
    servoWrite(LENGTH, length_current);
    servoWrite(HEIGHT, height_current);
    servoWrite(GRIP, grip_current);
}
 
void resetMeArm() {
    servoWrite(BASE, base_init);
    servoWrite(HEIGHT, height_init);
    servoWrite(LENGTH, length_init);
    servoWrite(GRIP, grip_init);
 
    base_current = base_init;
    height_current = height_init;
    length_current = length_init;
    grip_current = grip_init;
}
 
void servoWrite(uint8_t n, float pulse) {
    float pulsetick = pulse/pulseconstant;
    pwm.setPWM(n, 0, pulsetick);
}

Независимый источник питания

Последнее, что следует учитывать в этом проекте, это блок питания. Если у вас нет проблем с подключением к какой-либо проводной вилке для питания сервоэкрана, я бы предложил использовать батареи. Здесь не нужно делать что-то необычное, и подойдет простой держатель батареи. Я использовал 4 батарейки АА с держателем, как показано ниже. Я смог завершить этот проект, используя только 4 батареи, не истощая весь сок из них. А поскольку на сервоэкране имеется блок винтовых клемм, подключение и отключение комплекта аккумуляторов чрезвычайно просты. Это в сочетании с беспроводным джойстиком делает эту ручку робота хорошей портативной (я взял ее в кафе, чтобы показать ее своим друзьям — вы должны были видеть лица людей, сидящих возле нашего стола :)).

4aa_battery_holder

Конечный результат

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

Сложи это!

mearm_final_step_1

Подключите это!

mearm_final_step_2

Используй это!

mearm_final_step_3

Вывод

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

Если у вас есть дети, и вы хотите, чтобы они играли с чем-то менее распространенным и даже образовательным, то это проект, на который можно пойти. Многому и пожилой аудитории можно многому научиться. Так как использование может использовать Raspberry Pi для управления рукой, легко настроить Scratch, чтобы даже ребенок мог программировать его или ее и посмотреть, как это влияет на машину. И как только вы закончите с этим проектом, вы сможете продать / отдать его кому-то другому, как я, так что удовольствие от такого рода обучения можно поделиться с другими.

Если вы решите пойти и начать этот проект, дайте мне знать, как он прошел в разделе комментариев.