Sommario:

Utilizzo di Arduino Uno per il posizionamento XYZ del braccio robotico 6 DOF: 4 passaggi
Utilizzo di Arduino Uno per il posizionamento XYZ del braccio robotico 6 DOF: 4 passaggi

Video: Utilizzo di Arduino Uno per il posizionamento XYZ del braccio robotico 6 DOF: 4 passaggi

Video: Utilizzo di Arduino Uno per il posizionamento XYZ del braccio robotico 6 DOF: 4 passaggi
Video: Introduction to MoveIt with Rviz 2024, Novembre
Anonim
Image
Image

Questo progetto riguarda l'implementazione di uno schizzo Arduino breve e relativamente semplice per fornire il posizionamento cinematico inverso XYZ. Avevo costruito un braccio robotico con 6 servocomandi, ma quando si trattava di trovare un software per eseguirlo, non c'era molto là fuori tranne che per programmi personalizzati in esecuzione su schermi servo personalizzati come l'SSC-32 (U) o altri programmi e app che erano complicato da installare e comunicare con il braccio. Poi ho trovato l'eccellente "Robotic Arm Inverse Kinematics on Arduino" di Oleg Mazurov, dove ha implementato la cinematica inversa in un semplice sketch Arduino.

Ho apportato due modifiche per adattare il suo codice:

1. Ho usato la libreria VarSpeedServo al posto della sua libreria servo shield personalizzata perché potrei quindi controllare la velocità dei servi e non avrei dovuto usare la servo shield che ha usato. Per chiunque stia pensando di eseguire il codice fornito qui, consiglio di utilizzare questa libreria VarSpeedServo, piuttosto che la libreria servo.h, in modo da poter rallentare il movimento del braccio robotico durante lo sviluppo o potresti scoprire che il braccio ti colpirà inaspettatamente la faccia o peggio perché si muoverà alla massima velocità del servo.

2. Uso un semplice sensore/servo shield per collegare i servi all'Arduino Uno, ma non richiede una libreria servo speciale poiché utilizza solo i pin di Arduino. Costa solo pochi euro ma non è obbligatorio. Fa una bella connessione pulita dei servi all'Arduino. E non tornerò mai più ai servi cablati su Arduino Uno ora. Se utilizzi questo scudo sensore/servo, devi apportare una piccola modifica che illustrerò di seguito.

Il codice funziona alla grande e permette di azionare il braccio utilizzando un'unica funzione in cui si passano i parametri x, y, x e velocità. Per esempio:

set_arm(0, 240, 100, 0, 20); // i parametri sono (x, y, z, angolo di presa, velocità del servo)

ritardo (3000); // è necessario un ritardo per consentire il tempo di attivazione per spostarsi in questa posizione

Non potrebbe essere più semplice. Includerò lo schizzo qui sotto.

Il video di Oleg è qui: Controllo del braccio robotico con Arduino e mouse USB

Il programma, le descrizioni e le risorse originali di Oleg: la cinematica inversa di Oleg per Arduino Uno

Non capisco tutta la matematica dietro la routine, ma la cosa bella è che non devi usare il codice. Spero che ci proverai.

Passaggio 1: modifiche hardware

Modifiche hardware
Modifiche hardware

1. L'unica cosa che è richiesta è che il tuo servo giri nelle direzioni previste, il che potrebbe richiedere di invertire fisicamente il montaggio dei tuoi servi. Vai a questa pagina per vedere la direzione del servo prevista per i servi di base, spalla, gomito e polso:

2. Se usi lo scudo del sensore che sto usando, devi fare una cosa: piegare il pin che collega il 5v dallo scudo all'Arduino Uno in modo che non si colleghi alla scheda Uno. Vuoi usare la tensione esterna sullo scudo per alimentare solo i tuoi servi, non l'Arduino Uno o potrebbe distruggere l'Uno, so che ho bruciato due schede Uno quando la mia tensione esterna era di 6 volt anziché 5. Questo ti consente usare più di 5 V per alimentare i tuoi servi, ma se la tua tensione esterna è superiore a 5 volt, non collegare alcun sensore da 5 volt allo scudo o saranno fritti.

Passaggio 2: scarica la libreria VarSpeedServo

Devi usare questa libreria che sostituisce la libreria servo standard di arduino perché ti consente di passare una velocità del servo nell'istruzione di scrittura del servo. La biblioteca si trova qui:

Libreria VarSpeedServo

Puoi semplicemente usare il pulsante zip, scaricare il file zip e quindi installarlo con l'IDE di Arduino. Una volta installato il comando nel tuo programma sarà simile a: servo.write(100, 20);

Il primo parametro è l'angolo e il secondo è la velocità del servo da 0 a 255 (piena velocità).

Passaggio 3: esegui questo schizzo

Ecco il programma del concorso. Devi modificare alcuni parametri per le dimensioni del tuo braccio robotico:

1. Lunghezze BASE_HGT, HUMERUS, ULNA, PINZA in millimetri.

2. Inserisci i numeri dei pin del tuo servo

3. Immettere il servo min e max nelle istruzioni allegate.

4. Quindi prova un semplice comando set_arm() e poi le funzioni zero_x(), line() e circle() per il test. Assicurati che la velocità del tuo servo sia bassa la prima volta che esegui queste funzioni per evitare di danneggiare il tuo braccio e il tuo braccio.

Buona fortuna.

#include VarSpeedServo.h

/* Servocomando per braccio AL5D */

/* Dimensioni braccio (mm) */

#define BASE_HGT 90 //altezza della base

#define HUMERUS 100 //"osso" da spalla a gomito

#define ULNA 135 //"osso" dal gomito al polso

#define GRIPPER 200 //pinza (incl. meccanismo di rotazione del polso per impieghi gravosi) lunghezza"

#define ftl(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) //float alla conversione lunga

/* Nomi/numeri servo *

* Servo di base HS-485HB */

#define BAS_SERVO 4

/* Servo a spalla HS-5745-MG */

#define SHL_SERVO 5

/* Servo a gomito HS-5745-MG */

#define ELB_SERVO 6

/* Servo da polso HS-645MG */

#define WRI_SERVO 7

/* Servo rotazione polso HS-485HB */

#define WRO_SERVO 8

/* Servo pinza HS-422 */

#define GRI_SERVO 9

/* calcoli preliminari */

float hum_sq = OMERO*OMERO;

float uln_sq = ULNA*ULNA;

int servoVelocità = 10;

//servi ServoShield; //Oggetto ServoShield

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

int loopCounter=0;

int PulseWidth = 6.6;

int microsecondiToDegrees;

configurazione nulla()

{

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

ritardo (5500);

//servo.start(); //Avvia lo scudo del servo

servo_park();

ritardo (4000);

Serial.begin(9600);

Serial.println("Avvio");

}

ciclo vuoto()

{

contatoreciclo +=1;

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

//ritardo(7000);

//zero_x();

//linea();

//cerchio();

ritardo (4000);

if (contaloop > 1) {

servo_park();

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

ritardo (5000);

uscita (0); }//pausa programma - premi reset per continuare

//uscita(0);

}

/* routine di posizionamento del braccio che utilizza la cinematica inversa */

/* z è l'altezza, y è la distanza dal centro della base verso l'esterno, x è da un lato all'altro. y, z possono essere solo positivi */

//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 = radianti(grip_angle_d); //angolo di presa in radianti per l'uso nei calcoli

/* Angolo base e distanza radiale dalle coordinate x, y */

float bas_angle_r = atan2(x, y);

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

/* rdist è la coordinata y per il braccio */

y = rdist;

/* Scostamenti grip calcolati in base all'angolo grip */

galleggiante grip_off_z = (sin(grip_angle_r)) * PINZA;

galleggiante grip_off_y = (cos(grip_angle_r)) * PINZA;

/* Posizione del polso */

float wrist_z = (z - grip_off_z) - BASE_HGT;

float wrist_y = y - grip_off_y;

/* Distanza spalla-polso (AKA sw) */

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

float s_w_sqrt = sqrt(s_w);

/* s_w angolo rispetto al suolo */

float a1 = atan2(wrist_z, wrist_y);

/* s_w angolo rispetto all'omero */

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

/* angolo della spalla */

float shl_angle_r = a1 + a2;

float shl_angle_d = gradi(shl_angle_r);

/* angolo del gomito */

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

float elb_angle_d = gradi(elb_angle_r);

float elb_angle_dn = -(180.0 - elb_angle_d);

/* angolo del polso */

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/* Servo impulsi */

float bas_servopulse = 1500.0 - ((degrees(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); // aggiornato 2018/2/11 da jimrd - ho cambiato il più in un meno - non sono sicuro di come funzionasse questo codice per chiunque prima. Potrebbe essere che il servo del gomito sia stato montato con 0 gradi rivolto verso il basso anziché verso l'alto.

/* Imposta i servi */

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

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

servo1.write(microsecondsToDegrees, servoSpeed); // usa questa funzione in modo da poter impostare la velocità del servo //

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

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

servo2.write(microsecondsToDegrees, servoSpeed);

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

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

servo3.write(microsecondsToDegrees, servoSpeed);

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

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

servo4.write(microsecondsToDegrees, servoSpeed);

}

/* sposta i servi in posizione di parcheggio */

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

Restituzione;

}

vuoto zero_x()

{

for(asse y doppio = 250.0; asse y < 400.0; asse y += 1) {

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

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

ritardo(10);

}

for(doppio asse y = 400,0; asse y > 250,0; asse y -= 1) {

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

ritardo(10);

}

}

/* muove il braccio in linea retta */

riga vuota()

{

for(asse x doppio = -100,0; asse x < 100,0; asse x += 0,5) {

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

ritardo(10);

}

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

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

ritardo(10);

}

}

cerchio vuoto()

{

#define RAGGIO 50.0

//angolo flottante = 0;

galleggiante zaxis, yaxis;

for(angolo flottante = 0.0; angolo < 360.0; angolo += 1.0) {

yaxis = RAGGIO * sin(radianti(angolo)) + 300;

zaxis = RAGGIO * cos(radianti(angolo)) + 200;

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

ritardo(10);

}

}

Passaggio 4: fatti, problemi e simili…

Fatti, problemi e simili…
Fatti, problemi e simili…

1. Quando eseguo la subroutine circle(), il mio robot si muove più in una forma ellittica che in un cerchio. Penso che sia perché i miei servi non sono calibrati. Ne ho testato uno e 1500 microsecondi non erano gli stessi di 90 gradi. Lavorerà su questo per cercare di trovare una soluzione. Non credo che ci sia qualcosa di sbagliato nell'algoritmo ma piuttosto nelle mie impostazioni. Aggiornamento 2018/2/11: ho appena scoperto che ciò è dovuto a un errore nel codice originale. Non vedo come funzionava il suo programma Codice fisso usando questo: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (il codice originale stava aggiungendo)

2. Dove posso trovare maggiori informazioni su come funziona la funzione set_arm(): il sito Web di Oleg Mazurov spiega tutto o fornisce collegamenti per maggiori informazioni:

3. Esiste un controllo delle condizioni al contorno? No. Quando al mio braccio robotico viene passata una coordinata xyz non valida, fa questo strano tipo di movimento inarcato come un gatto che si stira. Credo che Oleg controlli il suo ultimo programma che usa una USB per programmare i movimenti del braccio. Guarda il suo video e collegalo al suo ultimo codice.

4. Il codice deve essere ripulito e il codice in microsecondi può essere eliminato.

Consigliato: