Cuprins:

Utilizarea Arduino Uno pentru poziționarea XYZ a brațului robot 6 DOF: 4 pași
Utilizarea Arduino Uno pentru poziționarea XYZ a brațului robot 6 DOF: 4 pași

Video: Utilizarea Arduino Uno pentru poziționarea XYZ a brațului robot 6 DOF: 4 pași

Video: Utilizarea Arduino Uno pentru poziționarea XYZ a brațului robot 6 DOF: 4 pași
Video: Noaptea albă a experimentului ştiinţific 2024, Iulie
Anonim
Image
Image

Acest proiect este despre implementarea unei schițe Arduino scurte și relativ ușoare pentru a oferi poziționare cinematică inversă XYZ. Am construit un braț robotizat cu 6 servo, dar când a venit să găsesc software pentru a-l rula, nu erau prea multe, cu excepția programelor personalizate care rulează pe servo-scuturi personalizate precum SSC-32 (U) sau alte programe și aplicații care erau complicat de instalat și de comunicat cu brațul. Apoi am găsit cea mai excelentă „Cinematică inversă a brațului robotic pe Arduino” a lui Oleg Mazurov, unde a implementat cinematica inversă într-o schiță simplă Arduino.

Am făcut două modificări pentru a-i adapta codul:

1. Am folosit biblioteca VarSpeedServo în locul bibliotecii sale personalizate de scuturi servo, deoarece aș putea apoi controla viteza servo-urilor și nu ar trebui să folosesc scutul servo folosit de el. Pentru oricine are în vedere să ruleze codul furnizat aici, vă recomand să utilizați această bibliotecă VarSpeedServo, mai degrabă decât biblioteca servo.h, astfel încât să puteți încetini mișcarea brațului robotizat în timpul dezvoltării sau puteți constata că brațul vă va băga neașteptat în față sau mai rău, deoarece se va deplasa la viteza servo maximă.

2. Folosesc un senzor / scut servo simplu pentru a conecta servo-urile la Arduino Uno, dar nu necesită nicio bibliotecă servo specială, deoarece folosește doar pinii Arduino. Costă doar câțiva dolari, dar nu este necesar. Se asigură o conexiune frumoasă și curată a servos-urilor la Arduino. Și nu mă voi mai întoarce niciodată la servomotoarele cablate la Arduino Uno acum. Dacă utilizați acest senzor / servo scut, trebuie să faceți o modificare minoră pe care o voi prezenta mai jos.

Codul funcționează excelent și vă permite să acționați brațul utilizând o singură funcție în care treceți parametrii x, y, x și viteză. De exemplu:

set_arm (0, 240, 100, 0, 20); // parametrii sunt (x, y, z, unghiul de prindere, viteza servo)

întârziere (3000); // este necesară întârzierea pentru a permite timpul de armare să se mute în această locație

Nu ar putea fi mai simplu. Voi include schița de mai jos.

Videoclipul lui Oleg este aici: Controlul brațului robotizat cu Arduino și mouse USB

Programul original, descrierile și resursele lui Oleg: Cinematica inversă a lui Oleg pentru Arduino Uno

Nu înțeleg toate matematica din spatele rutinei, dar lucrul drăguț este că nu trebuie să folosiți codul. Sper că veți încerca.

Pasul 1: Modificări hardware

Modificări hardware
Modificări hardware

1. Singurul lucru care este necesar este ca servo-ul dvs. să se întoarcă în direcțiile așteptate, ceea ce ar putea să necesite inversarea fizică a montării servo-urilor. Accesați această pagină pentru a vedea direcția servo așteptată pentru servozele de bază, umăr, cot și încheietura mâinii:

2. Dacă utilizați ecranul senzorului pe care îl folosesc, trebuie să faceți un lucru: îndoiți pinul care conectează 5v de la ecran la Arduino Uno pentru a nu se conecta la placa Uno. Vrei să folosești tensiunea externă de pe scut pentru a alimenta numai servo-urile, nu Arduino Uno sau poate distruge Uno, știu că am ars două plăci Uno când tensiunea mea externă era de 6 volți, mai degrabă decât 5. Acest lucru îți permite să utilizați mai mult de 5v pentru a vă alimenta servomotoarele, dar dacă tensiunea dvs. externă este mai mare de 5 volți, atunci nu conectați senzori de 5 volți la ecran sau vor fi prăjiți.

Pasul 2: Descărcați biblioteca VarSpeedServo

Trebuie să utilizați această bibliotecă care înlocuiește servo biblioteca arduino standard, deoarece vă permite să treceți o viteză servo în instrucțiunea servo write. Biblioteca se află aici:

Biblioteca VarSpeedServo

Puteți folosi doar butonul zip, descărca fișierul zip și apoi instalați-l cu ID-ul Arduino. Odată instalată comanda în programul dvs. va arăta astfel: servo.write (100, 20);

Primul parametru este unghiul, iar al doilea este viteza servo de la 0 la 255 (viteză maximă).

Pasul 3: Rulați această schiță

Iată programul de concurs. Trebuie să modificați câțiva parametri pentru dimensiunile robotice ale brațelor:

1. Lungimi BASE_HGT, HUMERUS, ULNA, GRIPPER în milimetri.

2. Introduceți numerele de pin servo

3. Introduceți servo min și max în declarațiile atașate.

4. Apoi încercați o comandă simplă set_arm () și apoi funcțiile zero_x (), line () și circle () pentru testare. Asigurați-vă că viteza servo este scăzută prima dată când executați aceste funcții pentru a preveni deteriorarea brațului și a propriului braț.

Noroc.

#include VarSpeedServo.h

/ * Servo control pentru brațul AL5D * /

/ * Dimensiuni braț (mm) * /

#define BASE_HGT 90 // înălțimea bazei

#define HUMERUS 100 // "os" de la umăr la cot

#define ULNA 135 // cot-la-încheietura mâinii "os"

#define GRIPPER 200 // prindere (incl. lungimea mecanismului rotativ pentru încheietura mâinii)"

#define ftl (x) ((x)> = 0? (long) ((x) +0.5):(long) ((x) -0.5)) // conversie float to long

/ * Numele / numerele servo *

* Servo de bază HS-485HB * /

#define BAS_SERVO 4

/ * Servomotor pentru umeri HS-5745-MG * /

#define SHL_SERVO 5

/ * Elbow Servo HS-5745-MG * /

#define ELB_SERVO 6

/ * Servo încheietura mâinii HS-645MG * /

#define WRI_SERVO 7

/ * Servo rotire încheietură HS-485HB * /

#define WRO_SERVO 8

/ * Gripper servo HS-422 * /

#define GRI_SERVO 9

/ * pre-calcule * /

plutitor hum_sq = HUMERUS * HUMERUS;

float uln_sq = ULNA * ULNA;

int servoSPeed = 10;

// ServoShield servos; // Obiect ServoShield

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

int loopCounter = 0;

int pulseWidth = 6,6;

int microsecundeToDegrees;

configurare nulă ()

{

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

întârziere (5500);

//servos.start (); // Porniți scutul servo

servo_park ();

întârziere (4000);

Serial.begin (9600);

Serial.println ("Start");

}

bucla nulă ()

{

loopCounter + = 1;

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

// întârziere (7000);

// zero_x ();

//linia();

//cerc();

întârziere (4000);

if (loopCounter> 1) {

servo_park ();

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

întârziere (5000);

ieșire (0); } // pauză program - apăsați reset pentru a continua

// ieșire (0);

}

/ * rutină de poziționare a brațelor utilizând cinematică inversă * /

/ * z este înălțime, y este distanța de la centrul bazei în afară, x este lateral. y, z nu poate fi decât pozitiv * /

// 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 = radiani (grip_angle_d); // unghiul de prindere în radiani pentru utilizare în calcule

/ * Unghiul de bază și distanța radială de la coordonatele x, y * /

float bas_angle_r = atan2 (x, y);

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

/ * rdist este coordonata y pentru braț * /

y = rdist;

/ * Decalaje de prindere calculate pe baza unghiului de prindere * /

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

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

/ * Poziția încheieturii mâinii * /

float wrist_z = (z - grip_off_z) - BASE_HGT;

float wrist_y = y - grip_off_y;

/ * Distanța de la umăr la încheietura mâinii (AKA sw) * /

float s_w = (wrist_z * wrist_z) + (wrist_y * wrist_y);

float s_w_sqrt = sqrt (s_w);

/ * s_w unghi față de sol * /

float a1 = atan2 (wrist_z, wrist_y);

/ * s_w unghi față de humerus * /

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

/ * unghi de umăr * /

float shl_angle_r = a1 + a2;

float shl_angle_d = grade (shl_angle_r);

/ * unghiul cotului / /

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

float elb_angle_d = grade (elb_angle_r);

float elb_angle_dn = - (180.0 - elb_angle_d);

/ * unghiul încheieturii mâinii * /

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/ * Impulsuri servo * /

float bas_servopulse = 1500.0 - ((grade (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); // actualizat 2018/2/11 de jimrd - Am schimbat plusul în minus - nu sunt sigur cum a funcționat acest cod pentru nimeni înainte. S-ar putea ca servo cotul să fie montat cu 0 grade orientate în jos, mai degrabă decât în sus.

/ * Setați servere * /

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

microsecundeToDegrees = hartă (ftl (bas_servopulse), 544, 2400, 0, 180);

servo1.write (microsecundeToDegrees, servoSpeed); // utilizați această funcție astfel încât să puteți seta viteza servo //

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

microsecundeToDegrees = hartă (ftl (shl_servopulse), 544, 2400, 0, 180);

servo2.write (microsecundeToDegrees, servoSpeed);

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

microsecundeToDegrees = hartă (ftl (elb_servopulse), 544, 2400, 0, 180);

servo3.write (microsecundeToDegrees, servoSpeed);

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

microsecundeToDegrees = hartă (ftl (wri_servopulse), 544, 2400, 0, 180);

servo4.write (microsecundeToDegrees, servoSpeed);

}

/ * mutați servomotoarele în poziția de parcare * /

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

întoarcere;

}

nul zero_x ()

{

for (yaxis dublu = 250,0; yaxis <400,0; yaxis + = 1) {

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

set_arm (0, yaxis, 200.0, 0, 10);

întârziere (10);

}

pentru (yaxis dublu = 400,0; yaxis> 250,0; yaxis - = 1) {

set_arm (0, yaxis, 200.0, 0, 10);

întârziere (10);

}

}

/ * mișcă brațul în linie dreaptă * /

linie nulă ()

{

for (xaxis dublu = -100,0; xaxis <100,0; xaxis + = 0,5) {

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

întârziere (10);

}

for (floare xaxis = 100,0; xaxis> -100,0; xaxis - = 0,5) {

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

întârziere (10);

}

}

cerc gol ()

{

#define RADIUS 50.0

// unghi de plutire = 0;

floare zaxis, yaxis;

for (unghi float = 0,0; unghi <360,0; unghi + = 1,0) {

yaxis = RADIUS * sin (radiani (unghi)) + 300;

zaxis = RADIUS * cos (radiani (unghi)) + 200;

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

întârziere (10);

}

}

Pasul 4: Fapte, probleme și altele asemenea …

Fapte, probleme și altele asemenea …
Fapte, probleme și altele asemenea …

1. Când rulez subrutina cercului () robotul meu se mișcă mai mult într-o formă eliptică decât un cerc. Cred că acest lucru se datorează faptului că servoanele mele nu sunt calibrate. Am testat una dintre ele și 1500 de microsecunde nu au fost la fel ca 90 de grade. Vom lucra la acest lucru pentru a încerca să găsesc o soluție. Nu credeți că este ceva în neregulă cu algoritmul, ci mai degrabă cu setările mele. Actualizare 2018/2/11 - tocmai am descoperit că acest lucru se datorează unei erori în codul original. Nu văd cum a funcționat programul său Cod fix folosind acest lucru: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (codul original a fost adăugat)

2. Unde pot găsi mai multe informații despre cum funcționează funcția set_arm (): site-ul web al lui Oleg Mazurov explică totul sau oferă linkuri pentru mai multe informații:

3. Există o verificare a stării la graniță? Nu. Când brațul robotului meu este trecut de o coordonată xyz nevalidă, face acest tip amuzant de mișcare de arcuire ca o pisică care se întinde. Cred că Oleg face unele verificări în cel mai recent program al său care folosește un USB pentru a programa mișcările brațului. Vedeți videoclipul său și conectați-l la ultimul său cod.

4. Codul trebuie curățat și codul de microsecundă poate fi eliminat.

Recomandat: