Картонный робот с управлением со смартфона

В этой статье мы соберём картонного робота на трёх сервоприводах, управляемых Arduino. Робот будет двигать руками и поворачивать голову. Для разработки интерфейса управления мы воспользуемся сервисом RemoteXY, который позволяет управлять роботом со смартфона через Bluetooth.

Картонный робот с управлением со смартфона

Корпус робота

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

Конструкция картонного робота

На голове робота вырезаны два отверстия, в которые вставляются два светодиода. Это будут глаза. Глаза тоже будут управляться дистанционно.

Электрическая схема

Для стабильной работы робота сервоприводы должны питаться от отдельного источника питания 5 В. Стабилизатор напряжения Arduino не может обеспечить необходимый ток для всех трёх сервоприводов. Последовательно со светодиодами необходимо включить резистор 680 Ом.

Электрическая схема картонного робота

Подключение:

  • PIN_LED_LEFT — пин 6 (левый светодиод-глаз)

  • PIN_LED_RIGHT — пин 7 (правый светодиод-глаз)

  • PIN_LEFT_SERVO — пин 8 (сервопривод левой руки)

  • PIN_RIGHT_SERVO — пин 9 (сервопривод правой руки)

  • PIN_HEAD_SERVO — пин 10 (сервопривод головы)

Интерфейс управления

Откройте редактор интерфейсов на сайте RemoteXY.com и создайте интерфейс управления, показанный на рисунке ниже. Интерфейс включает правый и левый слайдер для управления правой и левой рукой, а также слайдер для поворота головы. Добавьте две кнопки для управления глазами. И добавьте переключатель — мы будем использовать его для запуска автоматического мигания глаз.

Интерфейс управления RemoteXY

Переименуйте слайдеры, назовите их slider_left, slider_right и slider_head соответственно. Переименуйте кнопки — назовите их button_left и button_right соответственно.

Поскольку наш проект предполагает использование библиотеки servo.h, выберите в настройках проекта генерацию исходного кода для Arduino (Serial), library version. Библиотека servo.h конфликтует с библиотекой SoftwareSerial.h, поэтому мы не будем её использовать.

Сгенерируйте и скачайте исходный код проекта графического интерфейса на свой компьютер. Не забудьте скачать и установить библиотеку RemoteXY для Arduino IDE. Скомпилируйте и загрузите скетч в плату Arduino. С помощью мобильного приложения RemoteXY убедитесь, что ваш смартфон может подключиться к новому проекту. Не забывайте, что модуль Bluetooth должен быть подключён к аппаратному последовательному порту на пинах 0 (RX) и 1 (TX). Если смартфон успешно подключился — двигаемся дальше.

Структура данных RemoteXY:

/* эта структура определяет все переменные вашего интерфейса управления */
struct {
    /* входные переменные */
    unsigned char slider_left;      /* =0..100 положение слайдера */
    unsigned char slider_right;     /* =0..100 положение слайдера */
    unsigned char slider_head;      /* =0..100 положение слайдера */
    unsigned char button_left;      /* =1 если кнопка нажата, иначе =0 */
    unsigned char button_right;     /* =1 если кнопка нажата, иначе =0 */
    unsigned char switch_1;         /* =1 если переключатель ВКЛ, =0 если ВЫКЛ */
    /* другие переменные */
    unsigned char connect_flag;     /* =1 если соединение установлено, иначе =0 */
} RemoteXY;

Программа управления

Программа управления должна выполнять следующие задачи:

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

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

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

Также очень важно отметить, что программа должна выполняться непрерывно. Именно поэтому в функции loop — главном цикле программы — нельзя использовать паузы. Например, пауза часто используется при мигании двух светодиодов для ожидания времени между переключениями светодиода. В нашем случае такой подход привёл бы к ошибкам. В каждом цикле loop вызывается функция RemoteXY_Handler(), которая отвечает за обмен данными со смартфоном через модуль Bluetooth. Если эта функция не вызывается длительное время, она не сможет корректно осуществлять обмен данными. Как решить проблему отсчёта времени между переключениями светодиодов? Очень просто — с помощью встроенного таймера. Ниже приведён исходный код управления.

/////////////////////////////////////////////
//        RemoteXY include library         //
/////////////////////////////////////////////

/* RemoteXY select connection mode and include library */
#define REMOTEXY_MODE__SERIAL
#include <RemoteXY.h>

/* RemoteXY connection settings */
#define REMOTEXY_SERIAL Serial
#define REMOTEXY_SERIAL_SPEED 9600

/* RemoteXY configurate */
unsigned char RemoteXY_CONF[] = {
    6,0,79,0,1,5,4,0,5,7
    ,11,56,2,4,0,84,7,11,56,2
    ,4,128,20,13,60,11,2,129,0,26
    ,3,49,6,0,208,161,97,114,100,98
    ,111,97,114,100,32,82,111,98,111,116
    ,0,1,0,25,29,16,16,1,76,0
    ,1,0,60,29,16,16,1,82,0,2
    ,0,38,51,24,10,2,79,78,0,79
    ,70,70,0
};

/* эта структура определяет все переменные вашего интерфейса управления */
struct {
    /* входные переменные */
    unsigned char slider_left;      /* =0..100 положение слайдера */
    unsigned char slider_right;     /* =0..100 положение слайдера */
    unsigned char slider_head;      /* =0..100 положение слайдера */
    unsigned char button_left;      /* =1 если кнопка нажата, иначе =0 */
    unsigned char button_right;     /* =1 если кнопка нажата, иначе =0 */
    unsigned char switch_1;         /* =1 если переключатель ВКЛ, =0 если ВЫКЛ */
    /* другие переменные */
    unsigned char connect_flag;     /* =1 если соединение установлено, иначе =0 */
} RemoteXY;

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////

#include <Servo.h>

#define PIN_LED_LEFT 6
#define PIN_LED_RIGHT 7
#define PIN_LEFT_SERVO 8
#define PIN_RIGHT_SERVO 9
#define PIN_HEAD_SERVO 10

Servo left_servo;
Servo right_servo;
Servo head_servo;

unsigned char led_state = 0;
unsigned long led_time = 0;
unsigned long prev_time = 0;

void setup() {
    RemoteXY_Init();
    // TODO you setup code

    pinMode(PIN_LED_LEFT, OUTPUT);
    pinMode(PIN_LED_RIGHT, OUTPUT);

    left_servo.attach(PIN_LEFT_SERVO);
    right_servo.attach(PIN_RIGHT_SERVO);
    head_servo.attach(PIN_HEAD_SERVO);

    RemoteXY.slider_left = 50;
    RemoteXY.slider_right = 50;
    RemoteXY.slider_head = 50;
}

void loop() {
    RemoteXY_Handler();
    // TODO you loop code
    // use the RemoteXY structure for data transfer

    unsigned long time = millis();
    unsigned long d_time = time - prev_time;
    prev_time = time;

    if (RemoteXY.switch_1 == 0) {
        digitalWrite(PIN_LED_LEFT, (RemoteXY.button_left == 0) ? LOW : HIGH);
        digitalWrite(PIN_LED_RIGHT, (RemoteXY.button_right == 0) ? LOW : HIGH);
    } else {
        led_time += d_time;
        if (led_time > 500) {
            if (led_state == 0) led_state = 1;
            else led_state = 0;
            led_time -= 500;
        }
        digitalWrite(PIN_LED_LEFT, (led_state == 0) ? LOW : HIGH);
        digitalWrite(PIN_LED_RIGHT, (led_state == 1) ? LOW : HIGH);
    }

    left_servo.writeMicroseconds(RemoteXY.slider_left * 20 + 500);
    right_servo.writeMicroseconds(2500 - RemoteXY.slider_right * 20);
    head_servo.writeMicroseconds(RemoteXY.slider_head * 20 + 500);
}

Описание программы

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

В функции loop первым делом вызывается RemoteXY_Handler. Затем вычисляется количество времени, прошедшего с начала предыдущего цикла функции loop, в миллисекундах. Этот временной интервал используется для расчёта времени мигания светодиодов. Если переключатель switch_1 выключен, состояние кнопок button_left и button_right напрямую передаётся на управляющие пины светодиодов-глаз. Если switch_1 включён, реализуется алгоритм мигания глаз. Длительность свечения одного глаза составляет 500 миллисекунд.

Далее положения слайдеров управления руками и головой преобразуются в длительность импульса для управления сервоприводами. Слайдер изменяет своё состояние от 0 до 100, тогда как длительность управляющего импульса сервопривода должна варьироваться от 500 до 2500 мкс. Обратите внимание, что сервопривод правой руки вращается в противоположном направлении, и это отражено в формуле преобразования.

Необходимые компоненты

  • Плата Arduino

  • 3 сервопривода

  • 2 светодиода

  • 1 резистор (680 Ом)

  • Листы картона

  • Клеевой пистолет

  • Модуль Bluetooth (HC-05 или аналогичный)

  • Внешний источник питания 5 В для сервоприводов

  • Смартфон с установленным приложением RemoteXY