Indholdsfortegnelse:

Brug af Arduino Uno til XYZ Positionering af 6 DOF robotarm: 4 trin
Brug af Arduino Uno til XYZ Positionering af 6 DOF robotarm: 4 trin

Video: Brug af Arduino Uno til XYZ Positionering af 6 DOF robotarm: 4 trin

Video: Brug af Arduino Uno til XYZ Positionering af 6 DOF robotarm: 4 trin
Video: MKS Gen L - внешний драйвер 2024, November
Anonim
Image
Image

Dette projekt handler om at implementere en kort og relativt let Arduino -skitse til at give XYZ invers kinematisk positionering. Jeg havde bygget en 6 servo robotarm, men da det kom til at finde software til at køre den, var der ikke meget derude bortset fra brugerdefinerede programmer, der kørte på brugerdefinerede servoskærme som SSC-32 (U) eller andre programmer og apps, der var kompliceret at installere og kommunikere med armen. Derefter fandt jeg Oleg Mazurovs mest fremragende "Robotic Arm Inverse Kinematics on Arduino", hvor han implementerede invers kinematik i en simpel Arduino -skitse.

Jeg lavede to ændringer for at tilpasse hans kode:

1. Jeg brugte VarSpeedServo -biblioteket i stedet for hans brugerdefinerede servoskærmbibliotek, fordi jeg derefter kunne kontrollere servoernes hastighed, og jeg ikke skulle bruge det servoskærm, han brugte. For alle, der overvejer at køre koden her, anbefaler jeg, at du bruger dette VarSpeedServo -bibliotek frem for servo.h -biblioteket, så du kan bremse din robotarmbevægelse under udviklingen, eller du kan opleve, at armen uventet vil stikke dig ind ansigtet eller værre, fordi det vil bevæge sig ved fuld servohastighed.

2. Jeg bruger en simpel sensor/servoskærm til at forbinde servoerne til Arduino Uno, men det kræver ikke noget specielt servobibliotek, da det bare bruger Arduino's pins. Det koster kun et par kroner, men det er ikke påkrævet. Det giver en dejlig ren forbindelse af servoerne til Arduino. Og jeg vil aldrig gå tilbage til hardwiring servoer til Arduino Uno nu. Hvis du bruger denne sensor/servoskærm, skal du foretage en mindre ændring, som jeg vil skitsere nedenfor.

Koden fungerer godt og giver dig mulighed for at betjene armen ved hjælp af en enkelt funktion, hvor du sender parametrene x, y, x og hastighed. For eksempel:

set_arm (0, 240, 100, 0, 20); // parametre er (x, y, z, gribervinkel, servohastighed)

forsinkelse (3000); // forsinkelse er påkrævet for at tillade armtid at flytte til dette sted

Kunne ikke være enklere. Jeg vil inkludere skitsen herunder.

Olegs video er her: Styring af robotarm med Arduino og USB -mus

Olegs originale program, beskrivelser og ressourcer: Oleg's Inverse Kinematics for Arduino Uno

Jeg forstår ikke al matematik bag rutinen, men det gode er, at du ikke behøver at bruge koden. Håber du vil prøve det.

Trin 1: Hardwaremodifikationer

Hardware ændringer
Hardware ændringer

1. Det eneste, der kræves, er, at din servo drejer i de forventede retninger, hvilket kan kræve, at du fysisk vender monteringen af dine servoer tilbage. Gå til denne side for at se den forventede servoretning for baser, skuldre, albuer og håndledsservoer:

2. Hvis du bruger det sensorskjold, som jeg bruger, skal du gøre en ting ved det: bøj stiften, der forbinder 5v fra skjoldet til Arduino Uno, så den ikke kan tilsluttes Uno -kortet. Du vil bruge den eksterne spænding på skjoldet til kun at drive dine servoer, ikke Arduino Uno, eller det kan ødelægge Uno, jeg ved, da jeg brændte to Uno -kort op, da min eksterne spænding var 6 volt i stedet for 5. Dette giver dig mulighed for at bruge højere end 5v til at drive dine servoer, men hvis din eksterne spænding er højere end 5 volt, skal du ikke tilslutte nogen 5 volt sensorer til skjoldet, ellers bliver de stegt.

Trin 2: Download VarSpeedServo -biblioteket

Du skal bruge dette bibliotek, der erstatter det normale arduino servobibliotek, fordi det giver dig mulighed for at videregive en servohastighed til servoskrivningssætningen. Biblioteket ligger her:

VarSpeedServo -bibliotek

Du kan bare bruge zip -knappen, downloade zip -filen og derefter installere den med Arduino IDE. Når den er installeret, ser kommandoen i dit program ud: servo.write (100, 20);

Den første parameter er vinklen, og den anden er servoens hastighed fra 0 til 255 (fuld hastighed).

Trin 3: Kør denne skitse

Her er konkurrenceprogrammet. Du skal ændre et par parametre for dine robotarmdimensioner:

1. BASE_HGT, HUMERUS, ULNA, GRIPPER længder i millimeter.

2. Indtast dine servopindnumre

3. Indtast servo min og max i vedhæftede udsagn.

4. Prøv derefter en simpel kommando set_arm () og derefter funktionerne zero_x (), line () og circle () til test. Sørg for, at din servohastighed er lav første gang du kører disse funktioner for at forhindre skade på din arm og din egen arm.

Held og lykke.

#omfatter VarSpeedServo.h

/ * Servokontrol til AL5D -arm */

/ * Armmål (mm) */

#define BASE_HGT 90 // basishøjde

#define HUMERUS 100 // skulder-til-albue "knogle"

#define ULNA 135 // albue-til-håndled "knogle"

#define GRIPPER 200 // griber (inkl. kraftig håndledsrotationsmekanisme) længde"

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

/ * Servo navne/numre *

* Base servo HS-485HB */

#define BAS_SERVO 4

/ * Skulder Servo HS-5745-MG */

#define SHL_SERVO 5

/ * Albue Servo HS-5745-MG */

#define ELB_SERVO 6

/ * Håndledsservo HS-645MG */

#define WRI_SERVO 7

/ * Håndled roter servo HS-485HB */

#define WRO_SERVO 8

/ * Gripper servo HS-422 */

#define GRI_SERVO 9

/ * forberegninger */

float hum_sq = HUMERUS*HUMERUS;

float uln_sq = ULNA*ULNA;

int servoSPeed = 10;

// ServoShield servoer; // ServoShield -objekt

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

int loopCounter = 0;

int pulsbredde = 6,6;

int microsecondsToDegrees;

ugyldig opsætning ()

{

servo1. vedhæfte (BAS_SERVO, 544, 2400);

servo2.attach (SHL_SERVO, 544, 2400);

servo3. vedhæfte (ELB_SERVO, 544, 2400);

servo4.attach (WRI_SERVO, 544, 2400);

servo5.attach (WRO_SERVO, 544, 2400);

servo6. vedhæfte (GRI_SERVO, 544, 2400);

forsinkelse (5500);

//servos.start (); // Start servoskjoldet

servo_park ();

forsinkelse (4000);

Serial.begin (9600);

Serial.println ("Start");

}

hulrum ()

{

loopCounter += 1;

// sæt_arm (-300, 0, 100, 0, 10); //

// forsinkelse (7000);

// zero_x ();

// linje ();

//cirkel();

forsinkelse (4000);

hvis (loopCounter> 1) {

servo_park ();

// sæt_arm (0, 0, 0, 0, 10); // park

forsinkelse (5000);

exit (0); } // pause program - tryk på nulstil for at fortsætte

// exit (0);

}

/ * armpositioneringsrutine ved hjælp af omvendt kinematik */

/* z er højden, y er afstanden fra basen midt ud, x er side til side. y, z kan kun være positiv */

// 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 = radianer (grip_angle_d); // grebsvinkel i radianer til brug i beregninger

/ * Grundvinkel og radial afstand fra x, y koordinater */

float bas_angle_r = atan2 (x, y);

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

/ * rdist er y -koordinat for armen */

y = rdist;

/ * Grebsforskydninger beregnet ud fra grebsvinklen */

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

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

/ * Håndledsstilling */

float wrist_z = (z - grip_off_z) - BASE_HGT;

float wrist_y = y - grip_off_y;

/ * Skulder til håndled afstand (AKA sw) */

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

float s_w_sqrt = sqrt (s_w);

/ * s_w vinkel til jorden */

float a1 = atan2 (wrist_z, wrist_y);

/ * s_w vinkel til humerus */

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

/ * skuldervinkel */

float shl_angle_r = a1 + a2;

float shl_angle_d = grader (shl_angle_r);

/ * albue vinkel */

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

float elb_angle_d = grader (elb_angle_r);

float elb_angle_dn = - (180.0 - elb_angle_d);

/ * håndledsvinkel */

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/ * Servopulser */

float bas_servopulse = 1500,0 - ((grader (bas_angle_r)) * pulsbredde);

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

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

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

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

float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); // opdateret 2018/2/11 af jimrd - jeg ændrede pluset til et minus - ved ikke hvordan denne kode fungerede for nogen før. Kan være, at albueservoen var monteret med 0 grader nedad frem for opad.

/ * Sæt servoer */

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

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

servo1.write (microsecondsToDegrees, servoSpeed); // brug denne funktion, så du kan indstille servohastighed //

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

}

/ * flyt servoer til parkeringsposition */

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.skriv (90, 10);

//servos.setposition(GRI_SERVO, 900);

servo6.write (80, 10);

Vend tilbage;

}

ugyldig zero_x ()

{

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

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

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

forsinkelse (10);

}

for (dobbelt yaxis = 400,0; yaxis> 250,0; yaxis -= 1) {

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

forsinkelse (10);

}

}

/ * bevæger armen i en lige linje */

tom linje ()

{

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

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

forsinkelse (10);

}

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

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

forsinkelse (10);

}

}

hulrum ()

{

#define RADIUS 50.0

// flydevinkel = 0;

float zaxis, yaxis;

for (flydevinkel = 0,0; vinkel <360,0; vinkel += 1,0) {

yaxis = RADIUS * sin (radianer (vinkel)) + 300;

zaxis = RADIUS * cos (radianer (vinkel)) + 200;

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

forsinkelse (10);

}

}

Trin 4: Fakta, spørgsmål og lignende …

Fakta, spørgsmål og lignende …
Fakta, spørgsmål og lignende …

1. Når jeg kører cirklen () underrutine, bevæger min robot sig mere i en elliptisk form end en cirkel. Jeg tror, det er fordi mine servoer ikke er kalibreret. Jeg testede en af dem, og 1500 mikrosekunder var ikke det samme som 90 grader. Vil arbejde på dette for at forsøge at finde en løsning. Tro ikke, at der er noget galt med algoritmen, men derimod med mine indstillinger. Opdatering 2018/2/11 - opdagede lige, at dette skyldes fejl i den originale kode. Jeg kan ikke se, hvordan hans program fungerede Fixed code using this: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (den originale kode tilføjede)

2. Hvor kan jeg finde mere information om, hvordan funktionen set_arm () fungerer: Oleg Mazurovs websted forklarer alt eller giver links til mere info:

3. Er der nogen grænsetilstandskontrol? Nej. Når min robotarm passeres, får en ugyldig xyz -koordinat denne sjove slags buebevægelse som en kat, der strækker sig. Jeg tror, at Oleg tjekker noget i sit seneste program, der bruger en USB til at programmere armbevægelserne. Se hans video og link til hans seneste kode.

4. Koden skal ryddes op, og mikrosekundskoden kan fjernes.

Anbefalede: