Роботизированные руки – это одно из самых потрясающих изобретений современности, они могут выполнять движения, аналогичные движениям руки человека. В настоящее время они широко используются в промышленности и выполняют там множество разнообразных механических работ: сварка, покраска, сверление, перемещение чего либо и т.д. Совсем недавно созданы роботизированные руки, которые могут выполнять сложные хирургические операции с высокой точностью.
Ранее на нашем сайте мы уже рассматривали проект простейшей роботизированной руки, сделанной из картона, и проект уже более совершенной роботизированной руки, напечатанной на 3D принтере. В этой же статье мы рассмотрим создание управляемой жестами роботизированной руки на основе платы Arduino Nano, гироскопа MPU6050 и датчика изгиба. Остов руки будет напечатан на 3D принтере.
Позиция рассматриваемой в этом проекте роботизированной руки будет управляться с помощью перчатки, на которой будут закреплены гироскоп MPU6050 и гибкий датчик. С помощью гибкого датчика будет управляться захват (gripper) роботизированной руки, а гироскоп MPU6050 будет управлять местоположением руки по осям X и Y. Если у вас нет 3D принтера, то простейший макет этой руки вы можете изготовить из картона как в проекте простейшей роботизированной руки.
Датчик MPU6050
Датчик MPU6050 построен по технологии микроэлектромеханических систем (MEMS - Micro-Mechanical Systems) и имеет в своем составе 3-осевой акселерометр, 3-осевой гироскоп и датчик температуры. Он может измерять такие параметры как ускорение, скорость, направление (ориентация), смещение и т.д. Ранее на нашем сайте мы уже рассматривали его подключение к плате Arduino, а также рассматривали создание на его основе самобалансирующегося робота и измерителя уровня (уклономера).
Основные особенности датчика MPU6050:
- связь по протоколу I2C с конфигурируемым (настраиваемым) адресом I2C;
- питающее напряжение: 3-5V;
- встроенный 16 битный АЦП (аналого-цифровой преобразователь);
- возможность подключения по протоколу I2C к другим устройствам, например, магнитометру;
- встроенный датчик температуры.
Назначение контактов (распиновка) датчика MPU6050 показано на следующем рисунке.
Распиновка MPU6050:
Vcc – контакт для подачи питающего напряжения постоянного тока;
GND – земля модуля;
SDA – это контакт используется для передачи данных между модулем mpu6050 и микроконтроллером;
SCL – вход синхронизации;
XDA – линия передачи данных (опциональная) по протоколу I2C для конфигурирования и считывания данных с внешних датчиков (не используется в нашем проекте);
XCL – вход синхронизации протокола I2C для конфигурирования и считывания данных с внешних датчиков (не используется в нашем проекте);
ADO – I2C Slave Address LSB (не используется в нашем проекте);
INT – контакт прерывания для индикации готовности данных.
Гибкий датчик (датчик изгиба, Flex Sensor)
Гибкий датчик, по сути, представляет собой резистор с изменяющимся сопротивлением – его сопротивление изменяется когда его сгибают. Обычно гибкие датчики изготавливаются двух типоразмеров: 2.2 и 4.5 дюйма. Зависимость сопротивления датчика от степени его изгиба показана на следующем рисунке.
В нашем проекте роботизированной руки датчик изгиба будет использоваться для управления ее захватом – сгибая и разгибая перчатку, мы будем сжимать и разжимать захват роботизированной руки.
Также на нашем сайте вы можете посмотреть все проекты, в которых был использован датчик изгиба.
Изготовление остова роботизированной руки
Используемый нами остов (макет) роботизированной руки разработан пользователем EEZYbotARM и доступен к скачиванию на Thingiverse. Детализированная инструкция по сборке данной руки и печати ее компонентов на 3D принтере также доступна по приведенной ссылке.
Внешний вид собранной нами по этой инструкции роботизированной руки с установленными 4 сервомоторами показан на следующем рисунке.
Необходимые компоненты
- Плата Arduino Nano (купить на AliExpress).
- Гибкий датчик (Flex Sensor) (купить на AliExpress).
- Гироскоп MPU6050 (купить на AliExpress).
- Сервомотор SG90 (купить на AliExpress) или MG-995 (купить на AliExpress) – 4 шт.
- Резистор 10 кОм (купить на AliExpress).
- Перчатка на руку.
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Схема проекта
Схема управляемой жестами роботизированной руки на основе платы Arduino представлена на следующем рисунке.
В следующей таблице представлены соединения между датчиком MPU6050 и платой Arduino Nano.
Датчик MPU6050 | Плата Arduino Nano |
VCC | +5V |
GND | GND |
SDA | A4 |
SCL | A5 |
В следующей таблице представлены соединения между сервомоторами и платой Arduino Nano.
Плата Arduino Nano | Сервомоторы | Адаптер питания |
D2 | Servo 1 Orange (PWM Pin) | - |
D3 | Servo 2 Orange (PWM Pin) | - |
D4 | Servo 3 Orange (PWM Pin) | - |
D5 | Servo 4 Orange (PWM Pin) | - |
GND | Servo 1,2,3,4 Brown (GND Pin) | GND |
- | Servo 1,2,3,4 Red (+5V Pin) | +5V |
Гибкий датчик имеет 2 контакта – они не имеют полярности. Поэтому один контакт датчика подключен через подтягивающий резистор 10 кОм к контакту A0 платы Arduino, а другой – к контакту земли платы Arduino.
Сборка проекта роботизированной руки
Мы смонтировали гироскоп MPU6050 и гибкий датчик на перчатке для руки и соединили их проводами с роботизированной рукой, хотя, при желании, для этой цели можно использовать радиочастотное или Bluetooth соединение.
Окончательный вид проекта после сборки показан на следующем рисунке.
Объяснение программы для Arduino
Полный код программы и видео, демонстрирующее работу проекта, приведены в конце статьи, здесь же мы кратко рассмотрим основные фрагменты кода программы.
Первым делом в программе нам необходимо подключить используемые библиотеки. Библиотека Wire.h используется для связи по протоколу I2C между платой Arduino Nano и датчиком MPU6050, а библиотека servo.h используется для работы с сервомоторами.
1 2 |
#include<Wire.h> #include<Servo.h> |
Далее объявим объекты для работы с нашими 4 серводвигателями - servo_1, servo_2, servo_3, servo_4.
1 2 3 4 |
Servo servo_1; Servo servo_2; Servo servo_3; Servo servo_4; |
Затем зададим адрес I2C для датчика MPU6050 и объявим необходимые переменные.
1 2 3 4 5 6 7 |
const int MPU_addr=0x68; //MPU6050 I2C Address int16_t axis_X,axis_Y,axis_Z; int minVal=265; int maxVal=402; double x; double y; double z; |
Далее в функции void setup мы инициализируем последовательную связь со скоростью 9600 бод.
1 |
Serial.begin(9600); |
Затем установим связь по протоколу I2C между Arduino Nano и датчиком MPU6050.
1 2 3 4 5 |
Wire.begin(); //Initilize I2C Communication Wire.beginTransmission(MPU_addr); //Start communication with MPU6050 Wire.write(0x6B); //Writes to Register 6B Wire.write(0); //Writes 0 into 6B Register to Reset Wire.endTransmission(true); //Ends I2C transmission |
Далее прикрепим наши сервомоторы к соответствующим ШИМ контактам.
1 2 3 4 |
servo_1.attach(2); // Forward/Reverse_Motor servo_2.attach(3); // Up/Down_Motor servo_3.attach(4); // Gripper_Motor servo_4.attach(5); // Left/Right_Motor |
Затем, в функции void loop снова установим связь по протоколу I2C между Arduino Nano и датчиком MPU6050 и начнем считывать значения осей X, Y, Z с датчика MPU6050. Считанные даты будем сохранять в соответствующих переменных.
1 2 3 4 5 6 7 |
Wire.beginTransmission(MPU_addr); Wire.write(0x3B); //Start with regsiter 0x3B Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); //Read 14 Registers axis_X=Wire.read()<<8|Wire.read(); axis_Y=Wire.read()<<8|Wire.read(); axis_Z=Wire.read()<<8|Wire.read(); |
Затем конвертируем считанные значения осей в диапазон от -90 до 90.
1 2 3 |
int xAng = map(axis_X,minVal,maxVal,-90,90); int yAng = map(axis_Y,minVal,maxVal,-90,90); int zAng = map(axis_Z,minVal,maxVal,-90,90); |
Затем используем следующие формулы чтобы преобразовать значения осей x, y, z в диапазон от 0 до 360.
1 2 3 |
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI); z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI); |
Затем считаем данные с гибкого датчика и в соответствии с ними установим угол поворота сервомотора, отвечающего за захват (gripper) нашей роботизированной руки. Соответственно, если значение с гибкого датчика будет больше 750, то угол поворота сервомотора, отвечающего за захват, будет равен 0, а если значение с гибкого датчика будет меньше 750, то угол поворота сервомотора будет равен 180 градусов.
1 2 3 4 5 6 7 8 9 10 11 |
int gripper; int flex_sensorip = analogRead(A0); if(flex_sensorip > 750) { gripper = 0; } else { gripper = 180; } servo_3.write(gripper); |
После этого движения MPU6050 по оси X в диапазоне от 0 до 60 преобразуются в диапазон от 0 до 90 градусов – это значение используется для управления сервомотором, отвечающим за движение руки вперед/назад (Forward/Reverse).
1 2 3 4 5 6 7 8 |
if(x >=0 && x <= 60) { int mov1 = map(x,0,60,0,90); Serial.print("Movement in F/R = "); Serial.print(mov1); Serial.println((char)176); servo_1.write(mov1); } |
А движения по оси X от 250 до 360 преобразуются в диапазон от 0 до 90 градусов и используются для управления сервомотором, отвечающим за движение руки вверх/вниз.
1 2 3 4 5 6 7 8 |
else if(x >=300 && x <= 360) { int mov2 = map(x,360,250,0,90); Serial.print("Movement in Up/Down = "); Serial.print(mov2); Serial.println((char)176); servo_2.write(mov2); } |
Движения MPU6050 по оси Y в диапазоне от 0 до 60 преобразуются в диапазон от 90 до 180 градусов и используются для управления сервомотором, отвечающим за движение руки влево.
1 2 3 4 5 6 7 8 |
if(y >=0 && y <= 60) { int mov3 = map(y,0,60,90,180); Serial.print("Movement in Left = "); Serial.print(mov3); Serial.println((char)176); servo_4.write(mov3); } |
Движения MPU6050 по оси Y в диапазоне от 300 до 360 преобразуются в диапазон от 0 до 90 градусов и используются для управления сервомотором, отвечающим за движение руки вправо.
1 2 3 4 5 6 7 8 |
else if(y >=300 && y <= 360) { int mov3 = map(y,360,300,90,0); Serial.print("Movement in Right = "); Serial.print(mov3); Serial.println((char)176); servo_4.write(mov3); } |
Тестирование работы проекта
После сборки конструкции проекта загрузите код программы в Arduino Nano и наденьте перчатку с укрепленными на ней датчиком MPU6050 и гибким датчиком на руку.
1. После этого опускайте руку вниз чтобы заставить роботизированную руку двигаться вперед, и поднимайте свою руку вверх чтобы заставить роботизированную руку двигаться назад.
2. Наклоняйте свою руку вправо или влево чтобы заставить роботизированную руку двигаться вправо или влево.
3. Сгинайте гибкий датчик, закрепленный на перчатке, чтобы открыть захват руки и распрямляйте кисть своей руки чтобы закрыть захват руки.
Более подробно все эти процессы можно посмотреть на видео, приведенном в конце статьи.
Исходный код программы (скетча)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
#include<Wire.h> //библиотека для работы с I2C #include<Servo.h> //библиотека для работы с сервомоторами Servo servo_1; Servo servo_2; Servo servo_3; Servo servo_4; const int MPU_addr=0x68; //MPU6050 I2C Address int16_t axis_X,axis_Y,axis_Z; int minVal=265; int maxVal=402; double x; double y; double z; void setup() { Serial.begin(9600); Wire.begin(); //инициализируем I2C связь Wire.beginTransmission(MPU_addr); //начнем обмен данными с MPU6050 Wire.write(0x6B); //Writes to Register 6B Wire.write(0); //Writes 0 into 6B Register to Reset Wire.endTransmission(true); //окончание I2C связи servo_1.attach(2); // Forward/Reverse_Motor (вперед/назад) servo_2.attach(3); // Up/Down_Motor (вверх/вниз) servo_3.attach(4); // Gripper_Motor (захват руки) servo_4.attach(5); // Left/Right_Motor (влево/вправо) } void loop() { Wire.beginTransmission(MPU_addr); Wire.write(0x3B); //Start with regsiter 0x3B Wire.endTransmission(false); Wire.requestFrom(MPU_addr,14,true); //считываем 14 регистров axis_X=Wire.read()<<8|Wire.read(); //считываем значения осей X,Y,Z с MPU6050 axis_Y=Wire.read()<<8|Wire.read(); axis_Z=Wire.read()<<8|Wire.read(); int xAng = map(axis_X,minVal,maxVal,-90,90); // конвертируем значения осей в диапазон от -90 до +90 int yAng = map(axis_Y,minVal,maxVal,-90,90); int zAng = map(axis_Z,minVal,maxVal,-90,90); x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); //конвертируем в градусы y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI); z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI); int gripper; int flex_sensorip = analogRead(A0); //считываем показания с гибкого датчика if(flex_sensorip > 750) { gripper = 0; } else { gripper = 180; } servo_3.write(gripper); //передаем значение захвата на 3-й сервомотор if(x >=0 && x <= 60) { int mov1 = map(x,0,60,0,90); Serial.print("Movement in F/R = "); Serial.print(mov1); Serial.println((char)176); servo_1.write(mov1); } else if(x >=300 && x <= 360) { int mov2 = map(x,360,250,0,180); Serial.print("Movement in Up/Down = "); Serial.print(mov2); Serial.println((char)176); servo_2.write(mov2); } if(y >=0 && y <= 60) { int mov3 = map(y,0,60,90,180); Serial.print("Movement in Left = "); Serial.print(mov3); Serial.println((char)176); servo_4.write(mov3); } else if(y >=300 && y <= 360) { int mov3 = map(y,360,300,90,0); Serial.print("Movement in Right = "); Serial.print(mov3); Serial.println((char)176); servo_4.write(mov3); } } |
У меня все собрано, но робот не реагирует
Ну тогда нужно пробовать более простые варианты чтобы найти ошибку. Попробуйте просто поуправлять одним сервомотором, подключенным к плате Ардуино. И при движениях перчатки с датчиком у вас печатаются соответствующие сообщения в окне монитора последовательной связи?