Сборка беспроводного манипулятора Arduino, управляемого со смартфона
Обзор проекта
Роботизированная рука 5 степеней свободы, управляется через Bluetooth (HC-05) с Android-приложения (MIT App Inventor). Режимы: ручное (слайдеры) и автоматическое (запись/воспроизведение последовательности поз).

3D-модель и печать
- Конструировано в SolidWorks. 5 осей: основание (яв), плечо, локоть, запястье (ролл/питч), захват.
- Оси 1-3: MG996R (металлические шестерни, высокий момент); оси 4-5 и захват: SG90.
- STL-файлы и сборка доступны на Thangs (ссылки в исходнике).


Печаталось на Creality CR-10 (90% предсборка). Качество отличное за цену.



Механическая сборка
- База: серво MG996R → круглый рог → верхняя часть (2 болта).
- Плечо: серво → рог → следующее звено. Важно: на оси плеча резинка/пружина для компенсации веса.
- Локоть: аналогично.
- Запястье ролл/питч и захват: SG90, мелкая сборка на болтах M4.






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

- 6 сервоприводов → Arduino D5–D10 (сигнальные);
- HC-05: VCC→5V, GND→GND, TX→D3 (RX Arduino), RX→D4 (TX Arduino через делитель 1:2!);
- Питание серв: внешний 5V ≥2A (общий GND с Arduino). Arduino не тянет 6 серв.
Компоненты
- 3× MG996R, 3× SG90;
- HC-05 Bluetooth модуль;
- Arduino Uno/Nano;
- БП 5V 2A;
- Перемычки, макетка.
Прошивка Arduino
Библиотеки: SoftwareSerial (Bluetooth), Servo.h. Массивы для хранения до 50 поз.
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servo01, servo02, servo03, servo04, servo05, servo06;
SoftwareSerial Bluetooth(3, 4); // RX, TX (Arduino←HC05_TX, Arduino→HC05_RX через делитель!)
int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos;
int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos;
int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50];
int speedDelay = 20, index = 0;
String dataIn = "";
void setup() {
servo01.attach(5); servo02.attach(6); servo03.attach(7);
servo04.attach(8); servo05.attach(9); servo06.attach(10);
Bluetooth.begin(38400); Bluetooth.setTimeout(1); delay(20);
// Начальная поза
servo1PPos=90; servo01.write(servo1PPos);
servo2PPos=150; servo02.write(servo2PPos);
servo3PPos=35; servo03.write(servo3PPos);
servo4PPos=140; servo04.write(servo4PPos);
servo5PPos=85; servo05.write(servo5PPos);
servo6PPos=80; servo06.write(servo6PPos);
}
Основной цикл: парсинг команд от приложения
void loop() {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString(); // Читаем строку
// Серво 1 (основа) - префикс "s1"
if (dataIn.startsWith("s1")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo01, servo1PPos, pos, 20);
servo1PPos = pos;
}
// Серво 2 (плечо) - "s2"
if (dataIn.startsWith("s2")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo02, servo2PPos, pos, 50);
servo2PPos = pos;
}
// Серво 3 (локоть) - "s3"
if (dataIn.startsWith("s3")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo03, servo3PPos, pos, 30);
servo3PPos = pos;
}
// Серво 4 (запястье ролл) - "s4"
if (dataIn.startsWith("s4")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo04, servo4PPos, pos, 30);
servo4PPos = pos;
}
// Серво 5 (запястье питч) - "s5"
if (dataIn.startsWith("s5")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo05, servo5PPos, pos, 30);
servo5PPos = pos;
}
// Серво 6 (захват) - "s6"
if (dataIn.startsWith("s6")) {
int pos = dataIn.substring(2).toInt();
moveServoSlow(servo06, servo6PPos, pos, 30);
servo6PPos = pos;
}
// Кнопка SAVE - запомнить текущую позу
if (dataIn.startsWith("SAVE")) {
servo01SP[index] = servo1PPos;
servo02SP[index] = servo2PPos;
servo03SP[index] = servo3PPos;
servo04SP[index] = servo4PPos;
servo05SP[index] = servo5PPos;
servo06SP[index] = servo6PPos;
index++;
}
// Кнопка RUN - автоматический режим
if (dataIn.startsWith("RUN")) {
runServoSequence();
}
// Кнопка RESET - очистить запись
if (dataIn == "RESET") {
memset(servo01SP, 0, sizeof(servo01SP));
memset(servo02SP, 0, sizeof(servo02SP));
memset(servo03SP, 0, sizeof(servo03SP));
memset(servo04SP, 0, sizeof(servo04SP));
memset(servo05SP, 0, sizeof(servo05SP));
memset(servo06SP, 0, sizeof(servo06SP));
index = 0;
}
// Скорость - префикс "ss"
if (dataIn.startsWith("ss")) {
speedDelay = dataIn.substring(2).toInt();
}
}
}
Функция плавного движения сервы
void moveServoSlow(Servo &s, int from, int to, int stepDelay) {
if (from > to) {
for (int j = from; j >= to; j--) { s.write(j); delay(stepDelay); }
} else if (from < to) {
for (int j = from; j <= to; j++) { s.write(j); delay(stepDelay); }
}
}
Автоматическое воспроизведение последовательности
void runServoSequence() {
while (dataIn != "RESET") {
for (int i = 0; i <= index - 2; i++) {
// Проверка команд во время движения
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn == "PAUSE") {
while (dataIn != "RUN") {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn == "RESET") break;
}
}
}
if (dataIn.startsWith("ss")) {
speedDelay = dataIn.substring(2).toInt();
}
}
// Движение каждой сервы к следующей сохранённой позиции
moveServoSlow(servo01, servo01SP[i], servo01SP[i+1], speedDelay);
moveServoSlow(servo02, servo02SP[i], servo02SP[i+1], speedDelay);
moveServoSlow(servo03, servo03SP[i], servo03SP[i+1], speedDelay);
moveServoSlow(servo04, servo04SP[i], servo04SP[i+1], speedDelay);
moveServoSlow(servo05, servo05SP[i], servo05SP[i+1], speedDelay);
moveServoSlow(servo06, servo06SP[i], servo06SP[i+1], speedDelay);
}
}
}
Android-приложение (MIT App Inventor)


- Верх: кнопки Connect/Disconnect Bluetooth;
- Лево: изображение руки; Право: 6 слайдеров (по осям) + слайдер скорости;
- Слайдеры шлют префиксы
s1..s6+ значение (0-180); Скорость —ss+ задержка; - Кнопки: SAVE, RUN/PAUSE, RESET шлют соответствующие строки.
Файлы для скачивания: .aia (проект App Inventor) и .apk (готовое приложение).
Полный код Arduino (для копирования)
/* DIY Arduino Robot Arm Smartphone Control by Dejan, www.HowToMechatronics.com */
#include <SoftwareSerial.h>
#include <Servo.h>
Servo servo01, servo02, servo03, servo04, servo05, servo06;
SoftwareSerial Bluetooth(3, 4); // Arduino RX=3, TX=4 → HC-05 TX, RX
int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos;
int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos;
int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50];
int speedDelay = 20, index = 0;
String dataIn = "";
void setup() {
servo01.attach(5); servo02.attach(6); servo03.attach(7);
servo04.attach(8); servo05.attach(9); servo06.attach(10);
Bluetooth.begin(38400); Bluetooth.setTimeout(1); delay(20);
servo1PPos=90; servo01.write(servo1PPos);
servo2PPos=150; servo02.write(servo2PPos);
servo3PPos=35; servo03.write(servo3PPos);
servo4PPos=140; servo04.write(servo4PPos);
servo5PPos=85; servo05.write(servo5PPos);
servo6PPos=80; servo06.write(servo6PPos);
}
void loop() {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn.startsWith("s1")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo01, servo1PPos, pos, 20); servo1PPos=pos; }
if (dataIn.startsWith("s2")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo02, servo2PPos, pos, 50); servo2PPos=pos; }
if (dataIn.startsWith("s3")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo03, servo3PPos, pos, 30); servo3PPos=pos; }
if (dataIn.startsWith("s4")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo04, servo4PPos, pos, 30); servo4PPos=pos; }
if (dataIn.startsWith("s5")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo05, servo5PPos, pos, 30); servo5PPos=pos; }
if (dataIn.startsWith("s6")) { int pos=dataIn.substring(2).toInt(); moveServoSlow(servo06, servo6PPos, pos, 30); servo6PPos=pos; }
if (dataIn.startsWith("SAVE")) { servo01SP[index]=servo1PPos; servo02SP[index]=servo2PPos; servo03SP[index]=servo3PPos; servo04SP[index]=servo4PPos; servo05SP[index]=servo5PPos; servo06SP[index]=servo6PPos; index++; }
if (dataIn.startsWith("RUN")) { runServoSequence(); }
if (dataIn == "RESET") { memset(servo01SP,0,sizeof(servo01SP)); memset(servo02SP,0,sizeof(servo02SP)); memset(servo03SP,0,sizeof(servo03SP)); memset(servo04SP,0,sizeof(servo04SP)); memset(servo05SP,0,sizeof(servo05SP)); memset(servo06SP,0,sizeof(servo06SP)); index=0; }
if (dataIn.startsWith("ss")) { speedDelay = dataIn.substring(2).toInt(); }
}
}
void moveServoSlow(Servo &s, int from, int to, int stepDelay) {
if (from > to) for (int j=from; j>=to; j--) { s.write(j); delay(stepDelay); }
else if (from < to) for (int j=from; j<=to; j++) { s.write(j); delay(stepDelay); }
}
void runServoSequence() {
while (dataIn != "RESET") {
for (int i=0; i<=index-2; i++) {
if (Bluetooth.available() > 0) {
dataIn = Bluetooth.readString();
if (dataIn == "PAUSE") {
while (dataIn != "RUN") {
if (Bluetooth.available() > 0) { dataIn = Bluetooth.readString(); if (dataIn == "RESET") break; }
}
}
if (dataIn.startsWith("ss")) speedDelay = dataIn.substring(2).toInt();
}
moveServoSlow(servo01, servo01SP[i], servo01SP[i+1], speedDelay);
moveServoSlow(servo02, servo02SP[i], servo02SP[i+1], speedDelay);
moveServoSlow(servo03, servo03SP[i], servo03SP[i+1], speedDelay);
moveServoSlow(servo04, servo04SP[i], servo04SP[i+1], speedDelay);
moveServoSlow(servo05, servo05SP[i], servo05SP[i+1], speedDelay);
moveServoSlow(servo06, servo06SP[i], servo06SP[i+1], speedDelay);
}
}
}
Заключение
Полный цикл: 3D-печать, механика, электроника, прошивка, Android-приложение. Проект демонстрирует интеграцию механики, встраиваемых систем и мобильной разработки. Можно расширить: добавить датчики силы, обратную связь по положению, запись траекторий по обучению (teaching pendant).
Производственный процесс
- Умная копилка: управление монетоприёмником на Arduino Nano
- Умный вольтметр на Arduino и смартфоне — простое DIY-проект
- Удаленное IoT-управление самодельной манипулятором
- Робот-ускользатор на сервоприводе: сборка на Arduino и HC-SR04
- Управление светодиодом по Bluetooth с Arduino: простой DIY-гид
- Роботизированная рука 6 степеней свободы на Arduino Mega с управлением через Nunchuk
- Управление двумя шаговыми двигателями через джойстик на Arduino Nano — простой урок (Visuino)
- MobBob: Самостоятельная сборка Arduino-робота под управлением Android-смартфона
- LittleArm 2C: 3D-печатаемый робот-манипулятор на Arduino для STEM-обучения
- Yama Seiki GA-2000CR: компактный токарный центр с роботом-манипулятором и паллетной системой