Índice:

Usando o Arduino Uno para posicionamento XYZ de 6 braços robóticos DOF: 4 etapas
Usando o Arduino Uno para posicionamento XYZ de 6 braços robóticos DOF: 4 etapas

Vídeo: Usando o Arduino Uno para posicionamento XYZ de 6 braços robóticos DOF: 4 etapas

Vídeo: Usando o Arduino Uno para posicionamento XYZ de 6 braços robóticos DOF: 4 etapas
Vídeo: 6 DOF Robotic Arm Using Arduino Uno for XYZ Positioning (Source code available) 2024, Julho
Anonim
Image
Image

Este projeto é sobre a implementação de um esboço curto e relativamente fácil do Arduino para fornecer posicionamento cinemático inverso XYZ. Eu tinha construído um braço robótico de 6 servo, mas quando se tratava de encontrar software para executá-lo, não havia muito lá fora, exceto para programas personalizados em execução em escudos servo personalizados como o SSC-32 (U) ou outros programas e aplicativos que foram complicado de instalar e comunicar com o braço. Então eu encontrei o mais excelente "Cinemática Inversa do Braço Robótico no Arduino" de Oleg Mazurov, onde ele implementou a cinemática inversa em um esboço simples do Arduino.

Fiz duas modificações para adaptar seu código:

1. Usei a biblioteca VarSpeedServo no lugar de sua biblioteca de escudos de servo customizados porque eu poderia controlar a velocidade dos servos e não teria que usar o escudo de servo que ele usava. Para qualquer um que esteja considerando executar o código fornecido aqui, eu recomendo que você use esta biblioteca VarSpeedServo, em vez da biblioteca servo.h, para que você possa diminuir o movimento do braço robótico durante o desenvolvimento ou você pode descobrir que o braço irá cutucá-lo inesperadamente o rosto ou pior, porque ele estará se movendo a toda velocidade do servo.

2. Eu uso um sensor / servo escudo simples para conectar os servos ao Arduino Uno, mas ele não requer uma biblioteca servo especial, pois usa apenas os pinos do Arduino. Custa apenas alguns dólares, mas não é obrigatório. Isso proporciona uma conexão limpa e agradável dos servos ao Arduino. E eu nunca vou voltar a conectar servos ao Arduino Uno agora. Se você usar este sensor / servo-escudo, será necessário fazer uma pequena modificação que irei delinear abaixo.

O código funciona muito bem e permite que você opere o braço usando uma única função na qual você passa os parâmetros x, y, xe velocidade. Por exemplo:

set_arm (0, 240, 100, 0, 20); // os parâmetros são (x, y, z, ângulo da garra, velocidade do servo)

atraso (3000); // demora é necessário para permitir tempo de armar para mover para este local

Não poderia ser mais simples. Vou incluir o esboço abaixo.

O vídeo de Oleg está aqui: Controlando o braço robótico com Arduino e mouse USB

Programa original, descrições e recursos de Oleg: Cinemática Inversa de Oleg para Arduino Uno

Não entendo toda a matemática por trás da rotina, mas o bom é que você não precisa usar o código. Espero que você tente.

Etapa 1: Modificações de hardware

Modifcações de Hardware
Modifcações de Hardware

1. A única coisa que é necessária é que seu servo gire nas direções esperadas, o que pode exigir que você inverta fisicamente a montagem de seus servos. Vá para esta página para ver a direção esperada do servo para os servos de base, ombro, cotovelo e pulso:

2. Se você usar a blindagem do sensor que estou usando, você precisa fazer uma coisa: entortar o pino que conecta os 5v da blindagem ao Arduino Uno para que não se conecte à placa Uno. Você quer usar a tensão externa na blindagem para alimentar apenas seus servos, não o Arduino Uno ou pode destruir o Uno, eu sei que queimei duas placas Uno quando minha tensão externa era de 6 volts em vez de 5. Isso permite que você para usar mais de 5 V para alimentar seus servos, mas se sua voltagem externa for maior que 5 V, então não conecte nenhum sensor de 5 V à blindagem ou eles serão fritos.

Etapa 2: Baixe a Biblioteca VarSpeedServo

Você precisa usar esta biblioteca que substitui a biblioteca servo arduino padrão porque permite que você passe uma velocidade do servo para a instrução de gravação do servo. A biblioteca está localizada aqui:

Biblioteca VarSpeedServo

Você pode simplesmente usar o botão zip, baixar o arquivo zip e instalá-lo com o IDE do Arduino. Uma vez instalado, o comando em seu programa se parecerá com: servo.write (100, 20);

O primeiro parâmetro é o ângulo e o segundo é a velocidade do servo de 0 a 255 (velocidade total).

Etapa 3: execute este esboço

Aqui está o programa de competição. Você precisa modificar alguns parâmetros para as dimensões do braço robótico:

1. BASE_HGT, HUMERUS, ULNA, GRIPPER comprimentos em milímetros.

2. Insira os números dos pinos do seu servo

3. Insira o servo mínimo e máximo nas instruções de anexação.

4. Em seguida, tente um comando set_arm () simples e as funções zero_x (), line () e circle () para teste. Certifique-se de que a velocidade do servo esteja baixa na primeira vez que executar essas funções para evitar danos ao seu braço e ao seu próprio braço.

Boa sorte.

#include VarSpeedServo.h

/ * Servo controle para braço AL5D * /

/ * Dimensões do braço (mm) * /

# define BASE_HGT 90 // altura da base

# define HUMERUS 100 // ombro a cotovelo "osso"

# define ULNA 135 // "osso" do cotovelo ao pulso

#define GRIPPER 200 // comprimento da garra (incl. mecanismo de rotação do pulso para serviços pesados)"

# definir ftl (x) ((x)> = 0? (longo) ((x) +0,5):(longo) ((x) -0,5)) // flutuar para conversão longa

/ * Nomes / números de servo *

* Base servo HS-485HB * /

# define BAS_SERVO 4

/ * Servo de ombro HS-5745-MG * /

# define SHL_SERVO 5

/ * Elbow Servo HS-5745-MG * /

#define ELB_SERVO 6

/ * Servo de pulso HS-645MG * /

#define WRI_SERVO 7

/ * Servo de rotação de pulso HS-485HB * /

#define WRO_SERVO 8

/ * Gripper servo HS-422 * /

#define GRI_SERVO 9

/ * pré-cálculos * /

float hum_sq = HUMERUS * HUMERUS;

float uln_sq = ULNA * ULNA;

int servoSPeed = 10;

// ServoShield servos; // Objeto ServoShield

VarSpeedServo servo1, servo2, servo3, servo4, servo5, servo6;

int loopCounter = 0;

int pulseWidth = 6,6;

int microsecondsToDegrees;

void setup ()

{

servo1.attach (BAS_SERVO, 544, 2400);

servo2.attach (SHL_SERVO, 544, 2400);

servo3.attach (ELB_SERVO, 544, 2400);

servo4.attach (WRI_SERVO, 544, 2400);

servo5.attach (WRO_SERVO, 544, 2400);

servo6.attach (GRI_SERVO, 544, 2400);

atraso (5500);

//servos.start (); // Inicie o servo escudo

servo_park ();

atraso (4000);

Serial.begin (9600);

Serial.println ("Iniciar");

}

void loop ()

{

loopCounter + = 1;

// set_arm (-300, 0, 100, 0, 10); //

// atraso (7000);

// zero_x ();

//linha();

//círculo();

atraso (4000);

if (loopCounter> 1) {

servo_park ();

// set_arm (0, 0, 0, 0, 10); // Parque

atraso (5000);

saída (0); } // pausa o programa - pressione reset para continuar

// exit (0);

}

/ * rotina de posicionamento do braço utilizando cinemática inversa * /

/ * z é a altura, y é a distância do centro da base, x é um lado a outro. y, z só pode ser positivo * /

// void set_arm (uint16_t x, uint16_t y, uint16_t z, uint16_t grip_angle)

void set_arm (float x, float y, float z, float grip_angle_d, int servoSpeed)

{

float grip_angle_r = radianos (grip_angle_d); // ângulo da garra em radianos para uso em cálculos

/ * Ângulo base e distância radial das coordenadas x, y * /

float bas_angle_r = atan2 (x, y);

float rdist = sqrt ((x * x) + (y * y));

/ * rdist é coordenada y para o braço * /

y = rdist;

/ * Deslocamentos de garra calculados com base no ângulo de garra * /

float grip_off_z = (sin (grip_angle_r)) * GRIPPER;

float grip_off_y = (cos (grip_angle_r)) * GRIPPER;

/ * Posição do pulso * /

flutuar pulso_z = (z - grip_off_z) - BASE_HGT;

flutuar pulso_y = y - grip_off_y;

/ * Distância do ombro ao pulso (AKA sw) * /

float s_w = (pulso_z * pulso_z) + (pulso_y * pulso_y);

float s_w_sqrt = sqrt (s_w);

/ * ângulo s_w ao solo * /

float a1 = atan2 (pulso_z, pulso_y);

/ * ângulo s_w com o úmero * /

float a2 = acos (((hum_sq - uln_sq) + s_w) / (2 * HUMERUS * s_w_sqrt));

/ * ângulo do ombro * /

float shl_angle_r = a1 + a2;

float shl_angle_d = graus (shl_angle_r);

/ * ângulo do cotovelo * /

float elb_angle_r = acos ((hum_sq + uln_sq - s_w) / (2 * HUMERUS * ULNA));

float elb_angle_d = graus (elb_angle_r);

float elb_angle_dn = - (180,0 - elb_angle_d);

/ * ângulo do pulso * /

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/ * Servo pulsos * /

float bas_servopulse = 1500.0 - ((graus (bas_angle_r)) * pulseWidth);

float shl_servopulse = 1500.0 + ((shl_angle_d - 90.0) * pulseWidth);

float elb_servopulse = 1500.0 - ((elb_angle_d - 90.0) * pulseWidth);

// float wri_servopulse = 1500 + (wri_angle_d * pulseWidth);

// float wri_servopulse = 1500 + (wri_angle_d * pulseWidth);

float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); // atualizado em 2018/2/11 por jimrd - mudei o sinal de mais para menos - não tenho certeza de como esse código funcionou para alguém antes. Pode ser que o servo de cotovelo tenha sido montado com 0 graus voltado para baixo em vez de para cima.

/ * Definir servos * /

//servos.setposition(BAS_SERVO, ftl (bas_servopulse));

microsecondsToDegrees = map (ftl (bas_servopulse), 544, 2400, 0, 180);

servo1.write (microsecondsToDegrees, servoSpeed); // use esta função para que você possa definir a velocidade do servo //

//servos.setposition(SHL_SERVO, ftl (shl_servopulse));

microsecondsToDegrees = map (ftl (shl_servopulse), 544, 2400, 0, 180);

servo2.write (microsecondsToDegrees, servoSpeed);

//servos.setposition(ELB_SERVO, ftl (elb_servopulse));

microsecondsToDegrees = map (ftl (elb_servopulse), 544, 2400, 0, 180);

servo3.write (microsecondsToDegrees, servoSpeed);

//servos.setposition(WRI_SERVO, ftl (wri_servopulse));

microsecondsToDegrees = map (ftl (wri_servopulse), 544, 2400, 0, 180);

servo4.write (microsecondsToDegrees, servoSpeed);

}

/ * mover servos para a posição de estacionamento * /

void servo_park ()

{

//servos.setposition(BAS_SERVO, 1500);

servo1.write (90, 10);

//servos.setposition(SHL_SERVO, 2100);

servo2.write (90, 10);

//servos.setposition(ELB_SERVO, 2100);

servo3.write (90, 10);

//servos.setposition(WRI_SERVO, 1800);

servo4.write (90, 10);

//servos.setposition(WRO_SERVO, 600);

servo5.write (90, 10);

//servos.setposition(GRI_SERVO, 900);

servo6.write (80, 10);

Retorna;

}

void zero_x ()

{

para (eixo ya = 250,0; eixo y <400,0; eixo y + = 1) {

Serial.print ("eixo y =:"); Serial.println (eixo y);

set_arm (0, eixo y, 200,0, 0, 10);

atraso (10);

}

para (eixo ya = 400,0; eixo y> 250,0; eixo y - = 1) {

set_arm (0, eixo y, 200,0, 0, 10);

atraso (10);

}

}

/ * move o braço em linha reta * /

linha vazia ()

{

para (eixo duplo = -100,0; eixo x <100,0; eixo x + = 0,5) {

set_arm (eixo x, 250, 120, 0, 10);

atraso (10);

}

para (xeixo flutuante = 100,0; xeixo> -100,0; xeixo - = 0,5) {

set_arm (eixo x, 250, 120, 0, 10);

atraso (10);

}

}

círculo vazio ()

{

# define RADIUS 50.0

// ângulo de flutuação = 0;

float zaxis, yaxis;

para (ângulo de flutuação = 0,0; ângulo <360,0; ângulo + = 1,0) {

eixo y = RAIO * sen (radianos (ângulo)) + 300;

zaxis = RADIUS * cos (radianos (ângulo)) + 200;

set_arm (0, eixo y, eixo z, 0, 50);

atraso (10);

}

}

Etapa 4: fatos, problemas e similares …

Fatos, problemas e coisas semelhantes …
Fatos, problemas e coisas semelhantes …

1. Quando corro a sub-rotina circle (), meu robô se move mais em uma forma elíptica do que em um círculo. Acho que é porque meus servos não estão calibrados. Testei um deles e 1500 microssegundos não era o mesmo que 90 graus. Trabalharemos nisso para tentar encontrar uma solução. Não acredite que haja algo errado com o algoritmo, mas sim com minhas configurações. Atualização de 2018-02-11 - acabei de descobrir que isso ocorre devido a um erro no código original. Não vejo como seu programa funcionava. Corrigido código usando este: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (o código original estava sendo adicionado)

2. Onde posso encontrar mais informações sobre como a função set_arm () funciona: O site de Oleg Mazurov explica tudo ou fornece links para mais informações:

3. Existe alguma verificação de condição de limite? Não. Quando meu braço robótico passa por uma coordenada xyz inválida, ele faz esse tipo engraçado de movimento de arqueamento, como um gato se esticando. Eu acredito que Oleg faz algumas verificações em seu último programa que usa um USB para programar os movimentos do braço. Veja seu vídeo e link para seu código mais recente.

4. O código precisa ser limpo e o código de microssegundos pode ser eliminado.

Recomendado: