Innehållsförteckning:

Använda Arduino Uno för XYZ Positionering av 6 DOF robotarm: 4 steg
Använda Arduino Uno för XYZ Positionering av 6 DOF robotarm: 4 steg

Video: Använda Arduino Uno för XYZ Positionering av 6 DOF robotarm: 4 steg

Video: Använda Arduino Uno för XYZ Positionering av 6 DOF robotarm: 4 steg
Video: 6 DOF Robotic Arm Using Arduino Uno for XYZ Positioning (Source code available) 2024, December
Anonim
Image
Image

Detta projekt handlar om att implementera en kort och relativt enkel Arduino -skiss för att ge XYZ invers kinematisk positionering. Jag hade byggt en 6 servo robotarm men när det gällde att hitta programvara för att köra den fanns det inte mycket där ute förutom anpassade program som körs på anpassade servosköldar som SSC-32 (U) eller andra program och appar som var komplicerat att installera och kommunicera med armen. Sedan hittade jag Oleg Mazurovs mest utmärkta "Robotic Arm Inverse Kinematics on Arduino" där han implementerade invers kinematik i en enkel Arduino -skiss.

Jag gjorde två ändringar för att anpassa hans kod:

1. Jag använde VarSpeedServo -biblioteket istället för sitt anpassade servosköldbibliotek eftersom jag då kunde styra hastigheten på servon och jag skulle inte behöva använda servoskölden han använde. För alla som överväger att köra koden här rekommenderar jag att du använder detta VarSpeedServo -bibliotek, snarare än servo.h -biblioteket, så att du kan bromsa din robotarms rörelse under utvecklingen eller så kan du upptäcka att armen oväntat kommer att peta in dig ansiktet eller värre eftersom det kommer att röra sig med full servohastighet.

2. Jag använder en enkel sensor/servosköld för att ansluta servon till Arduino Uno men det kräver inget speciellt servobibliotek eftersom det bara använder Arduino -stiften. Det kostar bara några spänn men det krävs inte. Det ger en fin ren anslutning av servon till Arduino. Och jag kommer aldrig att gå tillbaka till hårdkopplade servon till Arduino Uno nu. Om du använder denna sensor/servosköld måste du göra en mindre ändring som jag kommer att beskriva nedan.

Koden fungerar utmärkt och låter dig styra armen med en enda funktion där du passerar parametrarna x, y, x och hastighet. Till exempel:

set_arm (0, 240, 100, 0, 20); // parametrar är (x, y, z, gripvinkel, servohastighet)

fördröjning (3000); // fördröjning krävs för att armtiden ska kunna flyttas till den här platsen

Kan inte vara enklare. Jag kommer att inkludera skissen nedan.

Olegs video är här: Kontroll av robotarm med Arduino och USB -mus

Olegs ursprungliga program, beskrivningar och resurser: Oleg's Inverse Kinematics for Arduino Uno

Jag förstår inte all matematik bakom rutinen men det fina är att du inte behöver använda koden. Hoppas du kommer att prova.

Steg 1: Modifieringar av hårdvara

Modifieringar av hårdvara
Modifieringar av hårdvara

1. Det enda som krävs är att din servo vänder sig i de förväntade riktningarna, vilket kan kräva att du fysiskt vänder montering av dina servon. Gå till denna sida för att se den förväntade servoriktningen för bas-, axel-, armbågs- och handledsservos:

2. Om du använder sensorskärmen som jag använder måste du göra en sak mot den: böj stiftet som ansluter 5v från skärmen till Arduino Uno ur vägen så att den inte ansluter till Uno -kortet. Du vill använda den externa spänningen på skärmen för att bara driva dina servon, inte Arduino Uno eller det kan förstöra Uno, jag vet när jag brände upp två Uno -kort när min externa spänning var 6 volt istället för 5. Detta låter dig att använda högre än 5v för att driva dina servon men om din externa spänning är högre än 5 volt ska du inte ansluta några 5 volt sensorer till skölden annars stekas de.

Steg 2: Ladda ner VarSpeedServo -biblioteket

Du måste använda det här biblioteket som ersätter det vanliga arduino -servobiblioteket eftersom det låter dig överföra en servohastighet till servoskrivningsuttalandet. Biblioteket finns här:

VarSpeedServo bibliotek

Du kan bara använda zip -knappen, ladda ner zip -filen och installera den sedan med Arduino IDE. Efter installationen kommer kommandot i ditt program att se ut: servo.write (100, 20);

Den första parametern är vinkeln och den andra är servos hastighet från 0 till 255 (full hastighet).

Steg 3: Kör den här skissen

Här är tävlingsprogrammet. Du måste ändra några parametrar för dina robotarmdimensioner:

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

2. Ange dina servostiftnummer

3. Mata in min och max för servo i bifogade uttalanden.

4. Försök sedan med ett enkelt kommando set_arm () och sedan funktionerna zero_x (), line () och circle () för testning. Se till att din servohastighet är låg första gången du kör dessa funktioner för att förhindra att din arm och din egen arm skadas.

Lycka till.

#inkludera VarSpeedServo.h

/ * Servokontroll för AL5D -arm */

/ * Armmått (mm) */

#define BASE_HGT 90 // bashöjd

#define HUMERUS 100 // axel-till-armbåge "ben"

#define ULNA 135 // armbåge-till-handled "ben"

#define GRIPPER 200 // gripare (inkl. kraftig handledsrotationsmekanism) längd"

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

/ * Servonamn/nummer *

* Bas servo HS-485HB */

#define BAS_SERVO 4

/ * Axel Servo HS-5745-MG */

#define SHL_SERVO 5

/ * Elbow Servo HS-5745-MG */

#define ELB_SERVO 6

/ * Handledservo HS-645MG */

#define WRI_SERVO 7

/ * Handledsroterande servo HS-485HB */

#define WRO_SERVO 8

/ * Grippservo HS-422 */

#define GRI_SERVO 9

/ * förberäkningar */

float hum_sq = HUMERUS*HUMERUS;

float uln_sq = ULNA*ULNA;

int servoSPeed = 10;

// ServoShield -servon; // ServoShield -objekt

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

int loopCounter = 0;

int pulsbredd = 6,6;

int microsecondsToDegrees;

void setup ()

{

servo1. bifoga (BAS_SERVO, 544, 2400);

servo2.attach (SHL_SERVO, 544, 2400);

servo3. bifoga (ELB_SERVO, 544, 2400);

servo4.attach (WRI_SERVO, 544, 2400);

servo5.attach (WRO_SERVO, 544, 2400);

servo6. bifoga (GRI_SERVO, 544, 2400);

fördröjning (5500);

//servos.start (); // Starta servoskölden

servo_park ();

fördröjning (4000);

Serial.begin (9600);

Serial.println ("Start");

}

void loop ()

{

loopCounter += 1;

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

// fördröjning (7000);

// zero_x ();

//linje();

//cirkel();

fördröjning (4000);

if (loopCounter> 1) {

servo_park ();

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

fördröjning (5000);

utgång (0); } // pausa programmet - tryck på reset för att fortsätta

// exit (0);

}

/ * armpositioneringsrutin med invers kinematik */

/* z är höjd, y är avståndet från basens mitt ut, x är från sida till sida. y, z kan bara vara 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); // greppvinkel i radianer för användning i beräkningar

/ * Basvinkel och radiellt avstånd från x, y -koordinater */

float bas_angle_r = atan2 (x, y);

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

/ * rdist är y koordinat för armen */

y = rdist;

/ * Greppförskjutningar beräknade baserat på greppvinkel */

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

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

/ * Handledsställning */

float wrist_z = (z - grip_off_z) - BASE_HGT;

float wrist_y = y - grip_off_y;

/ * Avstånd mellan axel och handled (AKA sw) */

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

float s_w_sqrt = sqrt (s_w);

/ * s_w vinkel mot mark */

float a1 = atan2 (wrist_z, wrist_y);

/ * s_w vinkel mot humerus */

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

/ * axelvinkel */

float shl_angle_r = a1 + a2;

float shl_angle_d = grader (shl_angle_r);

/ * armbågsvinkel */

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

/ * handledens vinkel */

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/ * Servopulser */

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

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

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

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

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

float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); // uppdaterad 2018/2/11 av jimrd - jag ändrade plus till minus - inte säker på hur den här koden fungerade för någon tidigare. Kan vara att armbågsservon var monterad med 0 grader nedåt snarare än uppåt.

/ * Ställ in servon */

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

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

servo1.write (microsecondsToDegrees, servoSpeed); // använd den här funktionen så att du kan ställa in servohastighet //

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

}

/ * flytta servon till parkeringsläge */

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

lämna tillbaka;

}

ogiltigt zero_x ()

{

för (dubbel yaxis = 250,0; yaxis <400,0; yaxis += 1) {

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

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

fördröjning (10);

}

för (dubbel yaxis = 400,0; yaxis> 250,0; yaxis -= 1) {

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

fördröjning (10);

}

}

/ * rör armen i en rak linje */

void line ()

{

för (dubbel xaxis = -100,0; xaxis <100,0; xaxis += 0,5) {

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

fördröjning (10);

}

för (float xaxis = 100,0; xaxis> -100,0; xaxis -= 0,5) {

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

fördröjning (10);

}

}

tomrum ()

{

#define RADIUS 50.0

// flottörvinkel = 0;

flyta zaxis, yaxis;

för (flottörvinkel = 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);

fördröjning (10);

}

}

Steg 4: Fakta, frågor och liknande …

Fakta, frågor och liknande …
Fakta, frågor och liknande …

1. När jag kör cirkel () underrutan rör mig min robot mer i en elliptisk form än en cirkel. Jag tror att det beror på att mina servon inte är kalibrerade. Jag testade en av dem och 1500 mikrosekunder var inte samma sak som 90 grader. Ska jobba på detta för att försöka hitta en lösning. Tro inte att det är något fel med algoritmen utan snarare med mina inställningar. Uppdatering 2018/2/11 - upptäckte just att detta beror på fel i den ursprungliga koden. Jag ser inte hur hans program fungerade Fixad kod med detta: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (ursprunglig kod lades till)

2. Var hittar jag mer information om hur funktionen set_arm () fungerar: Oleg Mazurovs webbplats förklarar allt eller ger länkar för mer info:

3. Finns det någon gränskontrollskontroll? Nej. När min robotarm passeras kommer en ogiltig xyz -koordinat att göra den här roliga välvningsrörelsen som en katt som sträcker sig. Jag tror att Oleg gör några kontroller i sitt senaste program som använder en USB för att programmera armrörelserna. Se hans video och länk till hans senaste kod.

4. Koden måste rensas upp och mikrosekundkoden kan tas bort.

Rekommenderad: