Inhaltsverzeichnis:

Verwenden von Arduino Uno für die XYZ-Positionierung des 6-DOF-Roboterarms - Gunook
Verwenden von Arduino Uno für die XYZ-Positionierung des 6-DOF-Roboterarms - Gunook

Video: Verwenden von Arduino Uno für die XYZ-Positionierung des 6-DOF-Roboterarms - Gunook

Video: Verwenden von Arduino Uno für die XYZ-Positionierung des 6-DOF-Roboterarms - Gunook
Video: #14 Position speichern und anfahren mit einen Schrittmotor + Arduino Uno + Taster + Inkrementalgeber 2024, November
Anonim
Image
Image

In diesem Projekt geht es darum, eine kurze und relativ einfache Arduino-Skizze zu implementieren, um eine inverse kinematische XYZ-Positionierung bereitzustellen. Ich hatte einen 6-Servo-Roboterarm gebaut, aber als es darum ging, Software zu finden, um ihn auszuführen, gab es nicht viel außer benutzerdefinierten Programmen, die auf benutzerdefinierten Servoschilden wie dem SSC-32 (U) oder anderen Programmen und Apps ausgeführt wurden kompliziert zu installieren und mit dem Arm zu kommunizieren. Dann fand ich Oleg Mazurovs hervorragendste "Robotic Arm Inverse Kinematics on Arduino", wo er inverse Kinematiken in einer einfachen Arduino-Skizze implementierte.

Ich habe zwei Änderungen vorgenommen, um seinen Code anzupassen:

1. Ich habe die VarSpeedServo-Bibliothek anstelle seiner benutzerdefinierten Servo-Schild-Bibliothek verwendet, da ich dann die Geschwindigkeit der Servos steuern konnte und ich den von ihm verwendeten Servo-Schild nicht verwenden musste. Für jeden, der in Betracht zieht, den hier bereitgestellten Code auszuführen, empfehle ich, dass Sie diese VarSpeedServo-Bibliothek anstelle der servo.h-Bibliothek verwenden, damit Sie Ihre Roboterarmbewegung während der Entwicklung verlangsamen können oder feststellen, dass der Arm Sie unerwartet einstößt das Gesicht oder schlimmer, weil es sich mit voller Servogeschwindigkeit bewegt.

2. Ich verwende ein einfaches Sensor- / Servoschild, um die Servos mit dem Arduino Uno zu verbinden, aber es erfordert keine spezielle Servobibliothek, da nur die Pins des Arduino verwendet werden. Es kostet nur ein paar Dollar, ist aber nicht erforderlich. Es sorgt für eine schöne saubere Verbindung der Servos zum Arduino. Und ich werde jetzt nie wieder Servos mit dem Arduino Uno festverdrahten. Wenn Sie dieses Sensor-/Servoschild verwenden, müssen Sie eine geringfügige Änderung vornehmen, die ich unten skizzieren werde.

Der Code funktioniert hervorragend und ermöglicht es Ihnen, den Arm mit einer einzigen Funktion zu bedienen, in der Sie die Parameter x, y, x und Geschwindigkeit übergeben. Zum Beispiel:

set_arm(0, 240, 100, 0, 20); // Parameter sind (x, y, z, Greiferwinkel, Servogeschwindigkeit)

Verzögerung (3000); // Es ist eine Verzögerung erforderlich, damit sich die Scharfschaltung an diesen Ort bewegen kann

Könnte nicht einfacher sein. Ich werde die Skizze unten einfügen.

Olegs Video ist hier: Roboterarm mit Arduino und USB-Maus steuern

Olegs Originalprogramm, Beschreibungen und Ressourcen:Olegs Inverse Kinematics for Arduino Uno

Ich verstehe nicht die ganze Mathematik hinter der Routine, aber das Schöne ist, dass Sie den Code nicht verwenden müssen. Ich hoffe, Sie werden es versuchen.

Schritt 1: Hardware-Änderungen

Hardware-Änderungen
Hardware-Änderungen

1. Das einzige, was erforderlich ist, ist, dass sich Ihr Servo in die erwarteten Richtungen dreht, was dazu führen kann, dass Sie die Montage Ihrer Servos physisch umkehren. Gehen Sie auf diese Seite, um die erwartete Servorichtung für Basis-, Schulter-, Ellbogen- und Handgelenk-Servos anzuzeigen:

2. Wenn Sie das Sensorschild verwenden, das ich verwende, müssen Sie eines tun: Biegen Sie den Stift, der die 5 V vom Schild mit dem Arduino Uno verbindet, aus dem Weg, damit er nicht mit der Uno-Platine verbunden ist. Sie möchten die externe Spannung auf dem Schild verwenden, um nur Ihre Servos mit Strom zu versorgen, nicht das Arduino Uno, oder es kann das Uno zerstören, ich weiß, dass ich zwei Uno-Boards verbrannt habe, als meine externe Spannung 6 Volt statt 5 betrug Um Ihre Servos mit mehr als 5 V zu versorgen, aber wenn Ihre externe Spannung höher als 5 Volt ist, schließen Sie keine 5-Volt-Sensoren an die Abschirmung an, da sie sonst gebraten werden.

Schritt 2: Laden Sie die VarSpeedServo-Bibliothek herunter

Sie müssen diese Bibliothek verwenden, die die Standard-Arduino-Servobibliothek ersetzt, da Sie eine Servogeschwindigkeit an die Servo-Schreibanweisung übergeben können. Die Bibliothek befindet sich hier:

VarSpeedServo-Bibliothek

Sie können einfach den Zip-Button verwenden, die Zip-Datei herunterladen und dann mit der Arduino IDE installieren. Nach der Installation sieht der Befehl in Ihrem Programm so aus: servo.write(100, 20);

Der erste Parameter ist der Winkel und der zweite die Geschwindigkeit des Servos von 0 bis 255 (volle Geschwindigkeit).

Schritt 3: Führen Sie diese Skizze aus

Hier ist das Wettkampfprogramm. Sie müssen einige Parameter für die Abmessungen Ihres Roboterarms ändern:

1. BASE_HGT, HUMERUS, ULNA, GRIPPER Längen in Millimeter.

2. Geben Sie Ihre Servo-Pin-Nummern ein

3. Geben Sie die Servomin und -max in die Attach-Anweisungen ein.

4. Versuchen Sie dann einen einfachen set_arm()-Befehl und dann die Funktionen zero_x(), line() und circle() zum Testen. Stellen Sie sicher, dass Ihre Servogeschwindigkeit beim ersten Ausführen dieser Funktionen niedrig ist, um eine Beschädigung Ihres Arms und Ihres eigenen Arms zu vermeiden.

Viel Glück.

#include VarSpeedServo.h

/* Servosteuerung für AL5D-Arm */

/* Armabmessungen (mm) */

#define BASE_HGT 90 //Basishöhe

#define HUMERUS 100 //Schulter-an-Ellenbogen "Knochen"

#define ULNA 135 //Ellenbogen-zu-Handgelenk "Knochen"

#define GRIPPER 200 //Greifer (inkl. Heavy Duty Handgelenk-Drehmechanismus) Länge"

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

/* Servonamen/Nummern *

* Basisservo HS-485HB */

#define BAS_SERVO 4

/* Schulterservo HS-5745-MG */

#define SHL_SERVO 5

/* Ellbogenservo HS-5745-MG */

#define ELB_SERVO 6

/* Handgelenkservo HS-645MG */

#define WRI_SERVO 7

/* Handgelenksdrehservo HS-485HB */

#define WRO_SERVO 8

/* Greiferservo HS-422 */

#define GRI_SERVO 9

/* Vorberechnungen */

float hum_sq = HUMERUS*HUMERUS;

float uln_sq = ULNA*ULNA;

int servoSPeed = 10;

// ServoShield-Servos; //ServoShield-Objekt

VarSpeedServo Servo1, Servo2, Servo3, Servo4, Servo5, Servo6;

int loopCounter=0;

int Impulsbreite = 6,6;

int MikrosekundenToDegrees;

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

Verzögerung (5500);

//servos.start(); // Starten Sie den Servoschild

servo_park();

Verzögerung (4000);

Serial.begin (9600);

Serial.println ("Start");

}

Leere Schleife ()

{

Schleifenzähler +=1;

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

// Verzögerung (7000);

//null_x();

//Leitung();

//Kreis();

Verzögerung (4000);

if (Schleifenzähler > 1) {

servo_park();

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

Verzögerung (5000);

Ausgang (0); } // Programm pausieren - drücke auf Reset, um fortzufahren

//beenden (0);

}

/* Armpositionierungsroutine mit inverser Kinematik */

/* z ist die Höhe, y ist der Abstand von der Basismitte nach außen, x ist seitlich. y, z kann nur positiv sein */

//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 = Radiant (grip_angle_d); //Griffwinkel im Bogenmaß zur Verwendung in Berechnungen

/* Basiswinkel und radialer Abstand von den x-, y-Koordinaten */

float bas_angle_r = atan2(x, y);

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

/* rdist ist die y-Koordinate für den Arm */

y = rdist;

/* Grip-Offsets berechnet basierend auf dem Grip-Winkel */

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

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

/* Handgelenkposition */

float handgelenk_z = (z – grip_off_z) – BASE_HGT;

float Handgelenk_y = y - grip_off_y;

/* Schulter-zu-Handgelenk-Abstand (AKA sw) */

float s_w = (handgelenk_z * handgelenk_z) + (handgelenk_y * handgelenk_y);

float s_w_sqrt = sqrt(s_w);

/* s_w-Winkel zum Boden */

float a1 = atan2(wrist_z, wrist_y);

/* s_w-Winkel zum Humerus */

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

/* Schulterwinkel */

float shl_angle_r = a1 + a2;

float shl_angle_d = Grad(shl_angle_r);

/* Ellbogenwinkel */

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

float elb_angle_d = Grad (elb_angle_r);

float elb_angle_dn = -(180.0 - elb_angle_d);

/* Handgelenkwinkel */

float wri_angle_d = (grip_angle_d - elb_angle_dn) - shl_angle_d;

/* Servoimpulse */

float bas_servopulse = 1500.0 - ((Grad (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); // aktualisiert 2018/2/11 von jimrd - Ich habe das Plus in ein Minus geändert - ich bin mir nicht sicher, wie dieser Code zuvor für jemanden funktioniert hat. Könnte sein, dass das Ellbogenservo mit 0 Grad nach unten statt nach oben montiert wurde.

/* Servos einstellen */

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

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

servo1.write (MikrosekundenToDegrees, servoSpeed); // Verwenden Sie diese Funktion, damit Sie die Servogeschwindigkeit einstellen können //

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

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

servo2.write (MikrosekundenToDegrees, servoSpeed);

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

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

servo3.write (MikrosekundenToDegrees, servoSpeed);

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

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

servo4.write (MikrosekundenToDegrees, servoSpeed);

}

/* Servos in Parkposition bringen */

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

Rückkehr;

}

Leere null_x()

{

for(doppelte Y-Achse = 250,0; Y-Achse < 400,0; Y-Achse += 1) {

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

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

Verzögerung(10);

}

for(doppelte Y-Achse = 400,0; Y-Achse > 250,0; Y-Achse -= 1) {

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

Verzögerung(10);

}

}

/* bewegt den Arm in einer geraden Linie */

Leere Zeile ()

{

for(doppelte x-Achse = -100,0; x-Achse < 100,0; x-Achse += 0,5) {

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

Verzögerung(10);

}

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

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

Verzögerung(10);

}

}

Leerer Kreis ()

{

#define RADIUS 50.0

// Schwimmwinkel = 0;

Float-Z-Achse, Y-Achse;

for(Schwimmwinkel = 0,0; Winkel < 360,0; Winkel += 1,0) {

y-Achse = RADIUS * sin(Radiant(Winkel)) + 300;

zaxis = RADIUS * cos(Radiant(Winkel)) + 200;

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

Verzögerung(10);

}

}

Schritt 4: Fakten, Probleme und dergleichen…

Fakten, Probleme und dergleichen…
Fakten, Probleme und dergleichen…

1. Wenn ich die Unterroutine circle () ausführe, bewegt sich mein Roboter mehr in einer elliptischen Form als in einem Kreis. Ich denke, das liegt daran, dass meine Servos nicht kalibriert sind. Ich habe einen von ihnen getestet und 1500 Mikrosekunden waren nicht dasselbe wie 90 Grad. Werde daran arbeiten um eine Lösung zu finden. Glaube nicht, dass am Algorithmus etwas nicht stimmt, sondern an meinen Einstellungen. Update 2018/2/11 - gerade entdeckt, dass dies auf einen Fehler im Originalcode zurückzuführen ist. Ich sehe nicht, wie sein Programm funktionierte Fester Code mit diesem: float wri_servopulse = 1500 - (wri_angle_d * pulseWidth); (Originalcode wurde hinzugefügt)

2. Wo finde ich weitere Informationen zur Funktionsweise der Funktion set_arm(): Die Website von Oleg Mazurov erklärt alles oder bietet Links für weitere Informationen:

3. Gibt es eine Überprüfung der Randbedingungen? Nein. Wenn meinem Roboterarm eine ungültige xyz-Koordinate übergeben wird, macht er diese komische Art von Wölbungsbewegung wie eine Katze, die sich streckt. Ich glaube, Oleg überprüft sein neuestes Programm, das einen USB verwendet, um die Armbewegungen zu programmieren. Sehen Sie sich sein Video an und verlinken Sie zu seinem neuesten Code.

4. Code muss bereinigt werden und Mikrosekunden-Code kann abgeschafft werden.

Empfohlen: