This is an old revision of the document!
G-Code Sender mit Beispielen: https://gitlab.com/Romanizer/gcode-py/-/tree/master/gcode
Die Datei GCodeSender.py
ist wie eine normale Library geschrieben.
Zuerst muss man sie importieren und ein Objekt instanziieren (Achtung: Es wird mit dem Roboterarm verbunden und eine Nullpunktfahrt ausgeführt!).
Um GCodeSender.py
zu importieren :
from gcodesender import * gcsender = GCodeSender('COMX') # oder '/dev/ttyUSBX' -> X = Port der Roboterarmes
Es gibt folgende Funktionen:
Funktion | Erklärung | Parameter | Rückgabewert |
---|---|---|---|
gcsender.send(x,y,z,f) | sendet den Arm an die gegebene Position | x,y,z: absolute Position, f: feedrate | Zeit in Sekunden bis der Move abgeschlossen ist |
gcsender.enablePump() | sendet M106 S255 und die Pumpe geht an | - | - |
gcsender.disablePump() | sendet M106 S0 und die Pumpe geht aus | - | - |
gcsender.cleanup() | schliesst die serielle Verbindung zum Arm | - | - |
Die Zeit in Sekunden bis der Arm von Punkt A nach Punkt B fährt ergibt sich wie folgt:
rel_x = x - self.last_x # calc relative change in position from last position rel_y = y - self.last_y rel_z = z - self.last_z t = math.sqrt(rel_x * rel_x + rel_y * rel_y + rel_z * rel_z) * (60 / f) * 0.9 # 3D Pythagoras of x,y,z * feedrate in sec/mm * calibration self.last_x = x # update last position to current position self.last_y = y self.last_z = z
Der Code behält immer die letzte Position des Armes im Speicher, um die Zeit auszurechnen.
Indem gewartet wird bis der Arm den aktuellen Move abgeschlossen hat, und erst dann ein neuer Move gesendet wird, wird verhindert, dass sich der serielle Buffer im Arduino füllt.
So wird immer erst ein Move gesendet, wenn der Arm diesen direkt ausführen kann. Der aktuelle Move basiert so immer auf den aller neusten Daten aus der ObjectßRecognition mit YOLOv5.
Um den Delta Arm mit Objekterkennung zu testen, wurde OpenCV verwendet. Das Skript erkennt grüne Objekte und weist den Drucker an, die Position des Objektes anzufahren. Es funktioniert wie folgt:
Für die Entwicklung der Objekterkennung wird OpenCV verwendet, eine Bibliothek für Bildverarbeitung / Bildanalyse.
Der Kommando G1 wird verwendet, um die Koordinaten für die lineare Bewegung zu senden.
Parameter | Bereich | Erklärung |
---|---|---|
X | -100, +100 | Links und Rechts |
Y | -100, +100 | Vorne und Hinten |
Z | 0, +245 | Höhe (+ is up) |
F | <4200 (firmware limit) | Feedrate in mm/min |
noch mal kurze Erklärung
import cv2 import serial import time import imutils import math from gcodesender import * # detect only green obj greenLower = (29, 86, 6) greenUpper = (64, 255, 255) feedrate = 4200 # mm/min # 4300 mm/min is too fast, and the robot arm cant keep up z_pos = 170 nextCommandTime = 0 camera = cv2.VideoCapture(0) gcsender = GCodeSender('COM7') while True: ret, frame = camera.read() # frame = imutils.resize(frame, width=600, height=300) hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, greenLower, greenUpper) mask = cv2.erode(mask, None, iterations=2) mask = cv2.dilate(mask, None, iterations=2) cnt, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2:] if nextCommandTime < time.time(): for c in range(len(cnt)): # determine positions + bounding box x, y, w, h = cv2.boundingRect(cnt[c]) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) # center positions x2 = int(x + w / 2) y2 = int(y + h / 2) # send G-Code and capture time needed for operation timeToWait = gcsender.send(x2, y2, z_pos, feedrate) # calculate next time a command can be issued nextCommandTime = time.time() + timeToWait print('timetowait: ' + str(timeToWait) + '\n') # draw center in bounding box cv2.circle(frame, (x2, y2), 4, (0, 255, 0), -1) cv2.imshow("Frame", frame) cv2.imshow("Mask", mask) if cv2.waitKey(1) & 0xFF == ord('q'): break gcsender.cleanup() camera.release() cv2.destroyAllWindows()