Table des matières:

Utilisation d'Arduino Uno pour le positionnement XYZ du bras robotique 6 DOF : 4 étapes
Utilisation d'Arduino Uno pour le positionnement XYZ du bras robotique 6 DOF : 4 étapes

Vidéo: Utilisation d'Arduino Uno pour le positionnement XYZ du bras robotique 6 DOF : 4 étapes

Vidéo: Utilisation d'Arduino Uno pour le positionnement XYZ du bras robotique 6 DOF : 4 étapes
Vidéo: 6 DOF Robotic Arm Using Arduino Uno for XYZ Positioning (Source code available) 2024, Novembre
Anonim
Image
Image

Ce projet consiste à mettre en œuvre une esquisse Arduino courte et relativement simple pour fournir un positionnement cinématique inverse XYZ. J'avais construit un bras robotique à 6 servomoteurs, mais lorsqu'il s'agissait de trouver un logiciel pour l'exécuter, il n'y avait pas grand-chose à part des programmes personnalisés fonctionnant sur des servomoteurs personnalisés comme le SSC-32 (U) ou d'autres programmes et applications qui étaient compliqué à installer et à communiquer avec le bras. Ensuite, j'ai trouvé le plus excellent "Robotic Arm Inverse Kinematics on Arduino" d'Oleg Mazurov, où il a implémenté la cinématique inverse dans un simple croquis Arduino.

J'ai fait deux modifications pour adapter son code:

1. J'ai utilisé la bibliothèque VarSpeedServo à la place de sa bibliothèque personnalisée de boucliers d'asservissement car je pouvais alors contrôler la vitesse des servos et je n'aurais pas à utiliser le bouclier d'asservissement qu'il utilisait. Pour tous ceux qui envisagent d'exécuter le code fourni ici, je vous recommande d'utiliser cette bibliothèque VarSpeedServo, plutôt que la bibliothèque servo.h, afin que vous puissiez ralentir le mouvement de votre bras robotique pendant le développement ou vous pouvez constater que le bras vous poussera de manière inattendue dans le visage ou pire parce qu'il se déplacera à pleine vitesse d'asservissement.

2. J'utilise un simple blindage capteur/servo pour connecter les servos à l'Arduino Uno, mais il ne nécessite aucune bibliothèque de servos spéciale car il utilise simplement les broches de l'Arduino. Cela ne coûte que quelques dollars mais ce n'est pas obligatoire. Cela permet une belle connexion propre des servos à l'Arduino. Et je ne reviendrai plus jamais au câblage des servos sur l'Arduino Uno maintenant. Si vous utilisez ce capteur/servo shield, vous devez apporter une modification mineure que je décrirai ci-dessous.

Le code fonctionne très bien et vous permet de faire fonctionner le bras en utilisant une seule fonction dans laquelle vous passez les paramètres x, y, x et vitesse. Par exemple:

set_arm (0, 240, 100, 0, 20); // les paramètres sont (x, y, z, angle de préhension, vitesse d'asservissement)

retard(3000); // un délai est nécessaire pour permettre à l'armement de se déplacer vers cet emplacement

Rien de plus simple. Je vais inclure le croquis ci-dessous.

La vidéo d'Oleg est ici: Contrôler le bras robotique avec Arduino et souris USB

Programme original, descriptions et ressources d'Oleg: cinématique inverse d'Oleg pour Arduino Uno

Je ne comprends pas tous les calculs derrière la routine, mais la bonne chose est que vous n'êtes pas obligé d'utiliser le code. J'espère que vous allez essayer.

Étape 1: Modifications matérielles

Modifications matérielles
Modifications matérielles

1. La seule chose requise est que votre servo tourne dans les directions attendues, ce qui pourrait vous obliger à inverser physiquement le montage de vos servos. Allez sur cette page pour voir la direction d'asservissement attendue pour les servos de base, d'épaule, de coude et de poignet:

2. Si vous utilisez le blindage du capteur que j'utilise, vous devez faire une chose: pliez la broche qui relie le 5v du blindage à l'Arduino Uno afin qu'elle ne se connecte pas à la carte Uno. Vous voulez utiliser la tension externe sur le blindage pour alimenter uniquement vos servos, pas l'Arduino Uno ou cela peut détruire l'Uno, je sais que j'ai brûlé deux cartes Uno alors que ma tension externe était de 6 volts au lieu de 5. Cela vous permet utiliser plus de 5v pour alimenter vos servos mais si votre tension externe est supérieure à 5 volts, ne connectez aucun capteur de 5 volts au blindage ou ils seront frits.

Étape 2: Téléchargez la bibliothèque VarSpeedServo

Vous devez utiliser cette bibliothèque qui remplace la bibliothèque d'asservissement arduino standard car elle vous permet de passer une vitesse d'asservissement dans l'instruction d'écriture d'asservissement. La bibliothèque se trouve ici:

Bibliothèque VarSpeedServo

Vous pouvez simplement utiliser le bouton zip, télécharger le fichier zip, puis l'installer avec l'IDE Arduino. Une fois installée, la commande dans votre programme ressemblera à: servo.write(100, 20);

Le premier paramètre est l'angle et le second est la vitesse du servo de 0 à 255 (pleine vitesse).

Étape 3: Exécutez cette esquisse

Voici le programme du concours. Vous devez modifier quelques paramètres pour les dimensions de votre bras robotique:

1. Longueurs BASE_HGT, HUMERUS, ULNA, GRIPPER en millimètres.

2. Entrez vos numéros de broche servo

3. Saisissez les valeurs mini et maxi du servo dans les instructions d'attachement.

4. Ensuite, essayez une simple commande set_arm() puis les fonctions zero_x(), line() et circle() pour le test. Assurez-vous que la vitesse de votre servo est faible la première fois que vous exécutez ces fonctions pour éviter d'endommager votre bras et votre propre bras.

Bonne chance.

#include VarSpeedServo.h

/* Servocommande pour bras AL5D */

/* Dimensions bras (mm) */

#define BASE_HGT 90 //hauteur de la base

#define HUMERUS 100 // "os" de l'épaule au coude

#define ULNA 135 // "os" coude-poignet

#define GRIPPER 200 // longueur de la pince (incl.mécanisme de rotation du poignet robuste)"

#define ftl(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) //conversion flottante en longue

/* Noms/numéros des servos *

* Servo de base HS-485HB */

#définir BAS_SERVO 4

/* Servo d'épaule HS-5745-MG */

#définir SHL_SERVO 5

/* Servo coudé HS-5745-MG */

#définir ELB_SERVO 6

/* Servo poignet HS-645MG */

#définir WRI_SERVO 7

/* Servo de rotation du poignet HS-485HB */

#définir WRO_SERVO 8

/* Servo de pince HS-422 */

#définir GRI_SERVO 9

/* pré-calculs */

float hum_sq = HUMERUS*HUMERUS;

float uln_sq = ULNA*ULNA;

int servoSPeed = 10;

// Servos ServoShield; //Objet ServoShield

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

int loopCounter=0;

int largeur d'impulsion = 6,6;

int microsecondesVersDegrés;

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);

retard (5500);

//servos.start(); //Démarrer le bouclier d'asservissement

servo_park();

retard (4000);

Serial.begin(9600);

Serial.println("Démarrer");

}

boucle vide()

{

compteurboucle +=1;

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

//délai (7000);

//zéro_x();

//ligne();

//cercle();

retard (4000);

if (loopCounter > 1) {

servo_park();

//set_arm(0, 0, 0, 0, 10); // se garer

retard (5000);

sortie(0); }//pause programme - appuyez sur reset pour continuer

//exit(0);

}

/* routine de positionnement du bras utilisant la cinématique inverse */

/* z est la hauteur, y est la distance du centre de la base vers l'extérieur, x est d'un côté à l'autre. y, z ne peut être que positif */

//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 = radians(grip_angle_d); //angle de préhension en radians à utiliser dans les calculs

/* Angle de base et distance radiale des coordonnées x, y */

float bas_angle_r = atan2(x, y);

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

/* rdist est la coordonnée y du bras */

y = rdist;

/* Décalages de préhension calculés en fonction de l'angle de préhension */

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

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

/* Position du poignet */

float poignet_z = (z - grip_off_z) - BASE_HGT;

float poignet_y = y - grip_off_y;

/* Distance épaule-poignet (AKA sw) */

float s_w = (poignet_z * poignet_z) + (poignet_y * poignet_y);

float s_w_sqrt = sqrt(s_w);

/* angle s_w par rapport au sol */

float a1 = atan2 (poignet_z, poignet_y);

/* angle s_w par rapport à l'humérus */

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

/* angle d'épaule */

float shl_angle_r = a1 + a2;

float shl_angle_d = degrés(shl_angle_r);

/* angle du coude */

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

float elb_angle_d = degrés(elb_angle_r);

float elb_angle_dn = -(180.0 - elb_angle_d);

/* angle du poignet */

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/* Impulsions servo */

float bas_servopulse = 1500.0 - ((degrés(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); // mis à jour 2018/2/11 par jimrd - j'ai changé le plus en moins - je ne sais pas comment ce code fonctionnait pour quiconque auparavant. Peut-être que le servo de coude a été monté avec 0 degrés vers le bas plutôt que vers le haut.

/* Régler les servos */

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

microsecondesVersDegrés = map(ftl(bas_servopulse), 544, 2400, 0, 180);

servo1.write(microsecondsToDegrees, servoSpeed); // utilisez cette fonction pour pouvoir régler la vitesse du servo //

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

microsecondesVersDegrés = map(ftl(shl_servopulse), 544, 2400, 0, 180);

servo2.write(microsecondsToDegrees, servoSpeed);

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

microsecondesVersDegrés = map(ftl(elb_servopulse), 544, 2400, 0, 180);

servo3.write(microsecondsToDegrees, servoSpeed);

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

microsecondesVersDegrés = map(ftl(wri_servopulse), 544, 2400, 0, 180);

servo4.write(microsecondsToDegrees, servoSpeed);

}

/* déplacer les servos en position de stationnement */

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);

revenir;

}

vide zero_x()

{

for(double axe des y = 250,0; axe des y < 400,0; axe des y += 1) {

Serial.print(" yaxis=: ");Serial.println(yaxis);

set_arm(0, axe y, 200.0, 0, 10);

retard(10);

}

for(double axe des y = 400,0; axe des y > 250,0; axe des y -= 1) {

set_arm(0, axe y, 200.0, 0, 10);

retard(10);

}

}

/* déplace le bras en ligne droite */

ligne vide()

{

for(double axe x = -100,0; axe x < 100,0; axe x += 0,5) {

set_arm(xaxis, 250, 120, 0, 10);

retard(10);

}

for(float xaxis = 100.0; xaxis > -100.0; xaxis -= 0.5) {

set_arm(xaxis, 250, 120, 0, 10);

retard(10);

}

}

cercle vide()

{

#définir le RAYON 50.0

//angle flottant = 0;

float zaxis, yaxis;

for(angle flottant = 0,0; angle < 360,0; angle += 1,0) {

axe y = RAYON * sin(radians(angle)) + 300;

zaxis = RAYON * cos(radians(angle)) + 200;

set_arm(0, yaxis, zaxis, 0, 50);

retard(10);

}

}

Étape 4: Faits, problèmes et autres…

Faits, problèmes et autres…
Faits, problèmes et autres…

1. Lorsque j'exécute le sous-programme circle(), mon robot se déplace plus en forme elliptique qu'en cercle. Je pense que c'est parce que mes servos ne sont pas calibrés. J'ai testé l'un d'entre eux et 1500 microsecondes n'étaient pas identiques à 90 degrés. J'y travaillerai pour essayer de trouver une solution. Ne croyez pas qu'il y ait quelque chose qui ne va pas avec l'algorithme mais plutôt avec mes paramètres. Mise à jour 2018/2/11 - vient de découvrir que cela est dû à une erreur dans le code d'origine. Je ne vois pas comment fonctionnait son programme Code fixe utilisant ceci: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (le code d'origine s'ajoutait)

2. Où puis-je trouver plus d'informations sur le fonctionnement de la fonction set_arm(): Le site Web d'Oleg Mazurov explique tout ou fournit des liens pour plus d'informations:

3. Existe-t-il une vérification des conditions aux limites ? Non. Lorsque mon bras de robot reçoit une coordonnée xyz invalide, il effectue ce drôle de mouvement d'arc comme un chat qui s'étire. Je crois qu'Oleg fait quelques vérifications dans son dernier programme qui utilise une clé USB pour programmer les mouvements des bras. Voir sa vidéo et un lien vers son dernier code.

4. Le code doit être nettoyé et le code en microsecondes peut être supprimé.

Conseillé: