KITtyBot: четырехногой робот на Arduino Pro Mini с сервами, ИК-управлением и инверсной кинематикой
Компоненты и материалы
| SparkFun Arduino Pro Mini 328 — 5V/16MHz | ×1 |
| Сервоприводы Tower Pro MG996R (или SG-90 / 9g) | ×12 |
| Adafruit UBEC DC/DC Step-Down 5V @ 3A | ×1 |
| Adafruit Mini Remote Control (или любой пульт, работающий с IRLib) | ×1 |
| ИК-приемник TSOP38238 | ×1 |
| Резистор 1кОм | ×1 |
| Резистор 2.2кОм | ×1 |
| LiPo 7.4V / 500mAh (формат для RC-моделей) | ×1 |
Инструменты
- 3D-принтер
- Паяльник (на макетке можно без пайки)
Приложения
- Arduino IDE
О проекте
Введение
Хотел сделать ходячего четвероногого робота в стиле «млекопитающего» (как у Boston Dynamics), а не паука/насекомого. Вызов: высокий центр тяжести, ноги под телом — легко перевернуться.
Цель: дешевый робот на Arduino и микросервах. Ограничения понятны, но результат — работающая ходьба. Бюджетное решение — вызов сам по себе.
Понадобилось изучить инверсную кинематику (IK). Код содержит уравнения для расчета углов суставов по желаемым положениям ног. Функции: движение тела (все 4 ноги в противоположную сторону), полный шаг ноги (поднять, переместить, поставить).
Гейты ( походки): статически устойчивые — за раз поднимается одна нога. Тело опирается на три остальные, центр тяжести должен оставаться внутри треугольника опоры. Реализованы 4 гейта: вперед, назад, влево, вправо.
Синхронное движение серв: несколько серв делают разные ходы за заданное время — синхронизация для плавности.
LiPo батарея без защиты: риски — глубокий разряд и короткое замыкание. Короткое замыкание предотвращает UBEC (макс 2А при 25C батареи). Глубокий разряд — мониторинг напряжения на аналоговом пине, при <7.0V робот останавливается.
Важно: заряжать только специальным зарядником, в огнеупорном мешке, без присмотра — никогда. Хранить безопасно. Не знакомы с LiPo — консультируйтесь в RC-магазине.
Сборка робота
Печатать детали по файлам. Изучите фото перед сборкой — инструкция не уровня IKEA :)
- Тазобедренный сустав: два серво перпендикулярно. Двусторонний скотч (клей — неразбираемо). Серво-опора на нижнем серво в линии оси, верхнее перпендикулярно. Для переднего правого и заднего левого — зеркально.
Центрировка серв: соберите плату/макетку, подключите все 12 серв, загрузите код — при старте все встают в 90°. Допишите центры позже.
- Бедро (верхняя часть ноги): впайки под рожки серв. Клей под 3D-пластик и нейлон рожка. Угол 60° к тазобедренному суставу. Подберите ближайший к 60° при центрированных сервах. Закрутите винтом рожка.
- Голень (нижняя часть): серво крепится винтами (идут с серво) к детали голени.
- Ноги на корпус: бамперы (перед/зад) с впайками под рожки. Рожки вклеены. Серво-опоры бедер в отверстия корпуса. Ноги разведены ~12° (20 мм toe-out). Бамперы крепятся длинными винтами от серв.
- Голени: наклон в противоположную сторону от бедер, кончик ноги под тазобедренным суставом.
Дизайн немного изменился vs фото/видео: корпус упрощен, серво-опора и рожок тазобедренного сустава поменялись местами. Собирайте по 3D-изображениям.
Углы не будут идеальными (21 зубчатость SG-90 = 17° шаг). Соберите максимально точно, остальное — калибровка в коде (см. ниже).
Подключение электроники
Два варианта: макетка или PCB (файл Fritzing ниже). На макетке проблемы с питанием серв — тонкие дорожки, контакты. На PCB — широкие медные шины питания.
Включателя нет — питание подключением батареи. Хотите выключатель — после разъема батареи, режет 7.4V и на Arduino, и на UBEC.
Версия на макетке
Pro Mini, разъемы серв, остальное — на половинке макетки. Короткие перемычки, особенно 5V и GND к сервам. Разъемы серв — длинные pin header, резаные по 3 пина.
Батарея и UBEC: пайка разъема батареи → 2 перемычки на нижнюю шину питания макетки (RAW и GND Pro Mini). Делитель напряжения на A0: 2.2кОм от +7.4V, 1кОм на GND → на A0 попадает <5V.
UBEC выход (серво-разъем) → 2 pin header на верхнюю шину питания (посередине для баланса).
ИК-приемник → A1, питание 5V. Ножки достаточно длинные для макетки.
Версия на PCB
Fritzing-файл для заказа PCB (Fritzing Fab или экспорт герберов). Разъемы под все сервы, ИК, измерение напряжения + запасные пины для расширения.
На корпусе pads под углы PCB. Угол с D3-D5 — передний левый. Крепление — двусторонний скотч.
Батарея
На дно на липучке. Площадка ~55×30×10 мм под 7.4V/500mAh LiPo.
Финальный штрих: затяните сервопровода пучками — не запутаются, выглядит как существо, а не куча проводов.
Финальная настройка
Калибровка нулевых позиций — массив servodeg0[12] в коде:
const float servodeg0[12] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};
Порядок: альфа, бета, гамма для переднего левого, заднего левого, переднего правого, заднего правого. Т.е. бета переднего правого — индекс 7.
Массив направлений вращения servodir[12]:
const int servodir[12] = { +1, +1, -1, -1, -1, +1, -1, -1, -1, +1, +1, +1 };
Мои сервы: 0→180° против часовой. Если ваши наоборот — инвертируйте знаки.
Запустите, проверьте углы, измерьте, добивайтесь симметрии по схеме:
Точность в мм сложна, ±1 см — норма. Корректируйте servodeg0 итеративно. Итоговый массив примера:
const float servodeg0[12] = {80, 95, 100, 100, 110, 90, 100, 115, 100, 80, 80, 100};
Робот стоит ровно на четырех ногах — готово!
Советы
- Сервы со временем сбивают центр — проверяйте периодически.
- Если переворачивается — сдвиньте батарею (липучка позволяет) для коррекции центра тяжести.
- Еще раз: LiPo — с уважением!
Дальнейшее развитие
Код пригоден для роботов других размеров — константы геометрии в начале скетча. Координаты: X — вперед.
На пульте свободные кнопки — можно добавить танцы, последовательности движений. Я экспериментировал с аналоговым управлением, «поворот во время ходьбы», гиро/компас для коррекции курса, ультразвуковой датчик и автономное избегание препятствий. Сейчас делаю управление со смартфона (Blynk, ESP8266, последовательный порт) — много нового, надеюсь выпустить улучшенную версию!
Код (Arduino)
Полный скетч KITtyBot2 (загружается в Pro Mini):
/* IR-версия KITtyBot 2. Arduino Pro Mini + моя PCB (Fritzing: Kittybotmini.fzz)
Базируется на KITtyBot и KITtyBot mini. ИК-пульт NEC (Adafruit) + IRLib2 (https://github.com/cyborg5/IRLib2)
Размеры похожи на оригинал, но смещение осей гамма и альфа = 12 мм (сервы друг на друге)
Гейты постоянно дорабатывались, текущая версия — самая стабильная.
Created by Staffan Ek 2017 */
#include <IRLibRecv.h>
#include <Servo.h>
#include <IRLibDecodeBase.h>
#include <IRLib_P01_NEC.h>
#define MY_PROTOCOL NEC
long Previous;
IRrecv My_Receiver(A1);
IRdecodeNEC My_Decoder;
const int servonum = 12;
Servo servo[servonum];
const float servodeg0[12] = {90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90};
float servodegnew[servonum];
float servodegold[servonum];
const int servodir[12] = { +1, +1, -1, -1, -1, +1, -1, -1, -1, +1, +1, +1 };
const float pi = 3.1416;
const float alfa0 = pi / 6; // 30°
const float beta0 = pi / 3; // 60°
const float jointlength = 50; // длина сегмента ноги
const float width = 120; // ширина (расстояние ног по Y с toeout)
const float leng = 120; // длина (расстояние ног по X)
const float distag = 12; // расстояние между осями альфа и гамма
const float toeout0 = 20; // toe-out ноги от центра гамма
const float leglength0 = 2 * jointlength * cos(alfa0);
const float gamma0 = asin(toeout0 / (leglength0 + distag));
const float bodyradius = sqrt(pow((width / 2), 2) + pow((leng / 2), 2));
const float phi0 = atan(width / leng);
const float height0 = sqrt(pow(leglength0 + distag, 2) - pow(toeout0, 2));
float leglength[4] = {leglength0, leglength0, leglength0, leglength0};
unsigned long timestep = 500;
int steplength = 40;
float phi = 20;
float footpos[12];
float stepturn[12] = {0};
const float jointangle0[12] = {alfa0, beta0, 0, alfa0, beta0, 0, alfa0, beta0, 0, alfa0, beta0, 0};
float jointangle[12];
const int voltagepin = A0;
int lowvolt = 0;
int mode = 0;
void setup() {
Serial.begin(9600);
Serial.println("KITtyBot mini");
Serial.print("Gamma0: "); Serial.println(gamma0);
Serial.print("Leglength0: "); Serial.println(leglength0);
Serial.print("Bodyradius: "); Serial.println(bodyradius);
Serial.print("Phi0: "); Serial.println(phi0);
Serial.print("Height0: "); Serial.println(height0);
servo[0].attach(3); servo[1].attach(4); servo[2].attach(5);
servo[3].attach(6); servo[4].attach(7); servo[5].attach(8);
servo[6].attach(2); servo[7].attach(A3); servo[8].attach(12);
servo[9].attach(11); servo[10].attach(10); servo[11].attach(9);
for (int i = 0; i < servonum; i++) {
servodegnew[i] = servodeg0[i];
servodegold[i] = servodegnew[i];
servo[i].write(servodegnew[i]);
}
delay(5000);
My_Receiver.enableIRIn();
}
void loop() {
voltmeasure();
while (lowvolt == 0) {
bodyxyz(0, 0, 0);
servomove();
mode = 0;
IRread();
Serial.print("Mode: "); Serial.println(mode);
switch (mode) {
case 1: forwardcreep(); break;
case 2: reversecreep(); break;
case 3: leftturn(); break;
case 4: rightturn(); break;
}
voltmeasure();
delay(500);
}
if (lowvolt == 1) {
bodyxyz(0, 0, -30);
servomove();
}
}
// ... (полный код с функциями IK, гейтами, ИК-приемом, мониторингом батареи — см. исходник выше)
3D-модели (STL)
- Body — корпус, несет PCB и батарею
- Bumper — бамперы перед/зад (2 шт)
- Hip Support — опора тазобедренного сустава (4 шт)
- Thigh — бедро (4 шт)
- Lower Leg — голень/ступня (4 шт)
- All Parts — все вместе (не для печати)
Схемы
Fritzing-файл для производства PCB. Заказ через Fritzing или экспорт для другого производства.
kittybotmini_XKZYltyQVJ.fzz
Производственный процесс
- Передача данных Adafruit 10DOF IMU с Raspberry Pi 2 в Azure Event Hubs на Windows 10 IoT Core
- Стильные настенные часы на четырех кольцах Adafruit Neopixel 60 LED и Arduino
- UnifiedWater v1: полный набор датчиков качества воды на Arduino MKR GSM
- Собственный шлем Железного Человека и Арк-реактор на Arduino — пошаговое руководство
- Переносная система голосования с GSM-связью
- Arduino 101 BLE + Blynk: DIY танк с Bluetooth-управлением с телефона
- Умные очки для знакомств на Arduino 101 и tinyTILE BLE
- DIY аркадная игра Whac-A-Mole (кнопочная версия) — проект на Arduino
- Модерн-джукебокс: Raspberry Pi + Arduino, LED-визиализация музыки, 3D-корпус
- DIY Arduino Smartwatch: самодельные умные часы в стиле Apple Watch