mirror of
https://github.com/BKLronin/touchCNC.git
synced 2024-11-21 16:14:01 +01:00
Initial implementation of gerbil
This commit is contained in:
parent
0c771a96e5
commit
c70d2d7b58
144
cnc.py
144
cnc.py
@ -5,10 +5,14 @@ import serial.tools.list_ports
|
|||||||
from tkinter import filedialog as fd
|
from tkinter import filedialog as fd
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
|
import grbl_gcode_send
|
||||||
|
import grbl_stream
|
||||||
|
|
||||||
grbl = 0
|
grbl = 0
|
||||||
|
port = None
|
||||||
i = 10
|
i = 10
|
||||||
GCODE = 0
|
GCODE = 0
|
||||||
|
gcode_to_stream = []
|
||||||
countbuf = 0
|
countbuf = 0
|
||||||
writebuffer_byPass = []
|
writebuffer_byPass = []
|
||||||
writebuffer = []
|
writebuffer = []
|
||||||
@ -41,6 +45,7 @@ feed = '#283B67'
|
|||||||
|
|
||||||
def grblConnect2():
|
def grblConnect2():
|
||||||
global grbl
|
global grbl
|
||||||
|
global port
|
||||||
|
|
||||||
#Serial Connection
|
#Serial Connection
|
||||||
locations=['/dev/ttyACM0','/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyACM1','/dev/ttyACM2','/dev/ttyACM3',
|
locations=['/dev/ttyACM0','/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyACM1','/dev/ttyACM2','/dev/ttyACM3',
|
||||||
@ -51,6 +56,7 @@ def grblConnect2():
|
|||||||
#print([comport.device for comport in serial.tools.list_ports.comports()])
|
#print([comport.device for comport in serial.tools.list_ports.comports()])
|
||||||
print ("Trying...",device)
|
print ("Trying...",device)
|
||||||
grbl = serial.Serial(port= device, baudrate= 115200, timeout =.5) #dsrdtr= True)
|
grbl = serial.Serial(port= device, baudrate= 115200, timeout =.5) #dsrdtr= True)
|
||||||
|
port = device
|
||||||
#grbl.open()
|
#grbl.open()
|
||||||
#print(grbl.readline())
|
#print(grbl.readline())
|
||||||
grbl.write(str.encode("\r\n\r\n"))
|
grbl.write(str.encode("\r\n\r\n"))
|
||||||
@ -75,11 +81,7 @@ def jogWrite(AXIS, CMD, scale): #Schreiben von manuellen Positionierungsbefehlen
|
|||||||
MOVE = int(CMD) * DECIMAL[scale -1]
|
MOVE = int(CMD) * DECIMAL[scale -1]
|
||||||
grbl_command = ('$J=G91' + 'G21' + AXIS + str(MOVE)+ 'F1000')
|
grbl_command = ('$J=G91' + 'G21' + AXIS + str(MOVE)+ 'F1000')
|
||||||
#print(grbl_command) $J=G91G21X10F185
|
#print(grbl_command) $J=G91G21X10F185
|
||||||
if freetosend == 1:
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
byPass(grbl_command+'\n')
|
|
||||||
else:
|
|
||||||
for button in blkbuttons:
|
|
||||||
switchButtonState(button)
|
|
||||||
|
|
||||||
def switchButtonState(button): #Umschalter für Knopfstatus
|
def switchButtonState(button): #Umschalter für Knopfstatus
|
||||||
if button["state"] == DISABLED:
|
if button["state"] == DISABLED:
|
||||||
@ -91,10 +93,9 @@ def directWrite(CMD): #Direktes schreiben eines Befehls
|
|||||||
global freetosend
|
global freetosend
|
||||||
#print(freetosend)
|
#print(freetosend)
|
||||||
grbl_command = CMD
|
grbl_command = CMD
|
||||||
if freetosend == 0:
|
|
||||||
now_bufferGRBL(grbl_command + '\n')
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
else:
|
|
||||||
byPass(grbl_command + '\n')
|
|
||||||
|
|
||||||
def latchWrite(CMD):
|
def latchWrite(CMD):
|
||||||
global states
|
global states
|
||||||
@ -141,19 +142,16 @@ def latchWrite(CMD):
|
|||||||
#print(grbl_command)
|
#print(grbl_command)
|
||||||
#print(states)
|
#print(states)
|
||||||
|
|
||||||
if freetosend == 0:
|
|
||||||
now_bufferGRBL(grbl_command + '\n')
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
else:
|
|
||||||
byPass(grbl_command + '\n')
|
|
||||||
print(grbl_command)
|
|
||||||
|
|
||||||
def terminalWrite(): #Holt Zeichenstring von Editfeld und sendet es
|
def terminalWrite(): #Holt Zeichenstring von Editfeld und sendet es
|
||||||
grbl_command = terminal.get()
|
grbl_command = terminal.get()
|
||||||
#print(grbl_command)
|
#print(grbl_command)
|
||||||
if freetosend == 0:
|
|
||||||
now_bufferGRBL(grbl_command + '\n')
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
else:
|
|
||||||
byPass(grbl_command+'\n')
|
|
||||||
|
|
||||||
def infoScreen(data): #Anzeigecanvas für GRBL Rückmeldungen
|
def infoScreen(data): #Anzeigecanvas für GRBL Rückmeldungen
|
||||||
global i
|
global i
|
||||||
@ -166,14 +164,16 @@ def infoScreen(data): #Anzeigecanvas für GRBL Rückmeldungen
|
|||||||
terminal_recv.delete("all")
|
terminal_recv.delete("all")
|
||||||
|
|
||||||
def openGCODE(): #Dialog zur Gcode Auswahl und öffnen der Datei als GCODE Objekt
|
def openGCODE(): #Dialog zur Gcode Auswahl und öffnen der Datei als GCODE Objekt
|
||||||
global GCODE
|
global gcode_to_stream
|
||||||
|
|
||||||
filetypes = (('GCODE', '*.nc'),('All files', '*.*'))
|
filetypes = (('GCODE', '*.nc'),('All files', '*.*'))
|
||||||
GCODE = fd.askopenfile(title='Open a file', initialdir='/home/thomas/Nextcloud/CAM/', filetypes=filetypes)
|
GCODE = fd.askopenfile(title='Open a file', initialdir='/home/thomas/Nextcloud/CAM/', filetypes=filetypes)
|
||||||
|
|
||||||
if GCODE != 0:
|
if GCODE != 0:
|
||||||
fopen.config(bg= loaded)
|
fopen.config(bg= loaded)
|
||||||
draw_GCODE(extract_GCODE())
|
extracted = extract_GCODE(GCODE)
|
||||||
|
draw_GCODE(extracted)
|
||||||
|
gcode_to_stream = GCODE
|
||||||
|
|
||||||
else:
|
else:
|
||||||
fopen.config(bg = 'grey')
|
fopen.config(bg = 'grey')
|
||||||
|
|
||||||
@ -181,10 +181,10 @@ def openGCODE(): #Dialog zur Gcode Auswahl und öffnen der Datei als GCODE Objek
|
|||||||
#build_xy = findEnvelope() #Aufruf PLatz im Bauraum
|
#build_xy = findEnvelope() #Aufruf PLatz im Bauraum
|
||||||
#mill_table.create_rectangle(build_xy[0],build_xy[1], fill = 'blue', stipple = 'gray75') # Zeichnen des Objekts im Bauraum
|
#mill_table.create_rectangle(build_xy[0],build_xy[1], fill = 'blue', stipple = 'gray75') # Zeichnen des Objekts im Bauraum
|
||||||
|
|
||||||
def extract_GCODE(): #Aufschlüsseln der enthaltenen Koordinaten in ein per Schlüssel zugängiges Dictionary
|
def extract_GCODE(gcode: list): #Aufschlüsseln der enthaltenen Koordinaten in ein per Schlüssel zugängiges Dictionary
|
||||||
global dict_GCODE
|
|
||||||
list_dict_GCODE = []
|
list_dict_GCODE = []
|
||||||
for line in GCODE:
|
for line in gcode:
|
||||||
l = line.split() #Elemente trennen und in Liste konvertieren
|
l = line.split() #Elemente trennen und in Liste konvertieren
|
||||||
for i in range(0,len(l)):
|
for i in range(0,len(l)):
|
||||||
#print (l)
|
#print (l)
|
||||||
@ -218,86 +218,6 @@ def draw_GCODE(glist): #Zeichnen des GCodes zur Beurteilung des Bauraums
|
|||||||
|
|
||||||
mill_table.create_line(x_y_current, x_y_next)
|
mill_table.create_line(x_y_current, x_y_next)
|
||||||
|
|
||||||
def grblWrite():
|
|
||||||
#print("write1")
|
|
||||||
global writebuffer
|
|
||||||
|
|
||||||
GCODE.seek(0)
|
|
||||||
|
|
||||||
for line in GCODE:
|
|
||||||
#print("write")
|
|
||||||
l = line.strip() # Strip all EOL characters for streaming
|
|
||||||
grbl_command = l
|
|
||||||
#print("GCODE",grbl_command)
|
|
||||||
bufferGRBL(grbl_command + '\n')
|
|
||||||
sendGRBL()
|
|
||||||
GCODE.close()
|
|
||||||
for button in blkbuttons: #Ausgrauen blockierter Knöpfe während Fräsen. "Umschalter"
|
|
||||||
switchButtonState(button)
|
|
||||||
fopen.config(bg = 'grey')
|
|
||||||
|
|
||||||
def timedPositionRequest():# >Im Falle das kein GCODE gestreamed wird abfragen der momentanen Position nach 1000ms sendet über den "byPass" channel der den GCode Stream nicht beeinflusst
|
|
||||||
if grbl != 0 and freetosend == 1:
|
|
||||||
grbl_command = '?'
|
|
||||||
byPass(grbl_command)
|
|
||||||
root.after(1000, timedPositionRequest)
|
|
||||||
|
|
||||||
def bufferGRBL(grbl_command):
|
|
||||||
global writebuffer
|
|
||||||
writebuffer.append(grbl_command)
|
|
||||||
#print (len(writebuffer))
|
|
||||||
|
|
||||||
def now_bufferGRBL(grbl_command):
|
|
||||||
global writebuffer
|
|
||||||
writebuffer.insert(1,grbl_command)
|
|
||||||
#print (len(writebuffer))
|
|
||||||
|
|
||||||
def byPass(grbl_command):
|
|
||||||
global writebuffer_byPass
|
|
||||||
#print (grbl_command)
|
|
||||||
if grbl_command == '?':
|
|
||||||
grbl.write(str.encode(grbl_command)) # Send g-code block to grbl
|
|
||||||
grbl_out = grbl.readline().strip()
|
|
||||||
else:
|
|
||||||
#print(grbl_command)
|
|
||||||
writebuffer_byPass.append(grbl_command)
|
|
||||||
grbl.write(str.encode(writebuffer_byPass[0])) # Send g-code block to grbl
|
|
||||||
grbl_out = grbl.readline().strip()
|
|
||||||
#print(writebuffer_byPass)
|
|
||||||
del writebuffer_byPass[0]
|
|
||||||
displayPosition_request(grbl_out)
|
|
||||||
infoScreen(grbl_out)
|
|
||||||
#print(grbl_out)
|
|
||||||
|
|
||||||
def debugWrite(grbl_command):
|
|
||||||
|
|
||||||
grbl.write(str.encode(grbl_command)) # Send g-code block to grbl
|
|
||||||
grbl_out = grbl.readline().strip()
|
|
||||||
displayPosition_request(grbl_out)
|
|
||||||
infoScreen(grbl_out)
|
|
||||||
print(grbl_out)
|
|
||||||
|
|
||||||
def sendGRBL(): #Komplette Gcodes streamen senden
|
|
||||||
global writebuffer
|
|
||||||
global freetosend
|
|
||||||
|
|
||||||
while len(writebuffer) >0:
|
|
||||||
freetosend = 0
|
|
||||||
#print ("current",writebuffer[0])
|
|
||||||
#print (writebuffer)
|
|
||||||
grbl.write(str.encode(writebuffer[0])) # Send g-code block to grbl
|
|
||||||
#writeToFileLog(writebuffer[0])
|
|
||||||
#grbl.timeout = None
|
|
||||||
readbuffer.append(grbl.readline().strip()) # Wait for grbl response with carriage return
|
|
||||||
del writebuffer[0]
|
|
||||||
|
|
||||||
if len(readbuffer) == 5:
|
|
||||||
writebuffer.insert(2,'?' + '\n') #newline need?
|
|
||||||
displayPosition()
|
|
||||||
infoScreen(readbuffer[0])
|
|
||||||
readbuffer.clear()
|
|
||||||
freetosend = 1
|
|
||||||
|
|
||||||
def writeToFileLog(log): #Log für Debugzwecke
|
def writeToFileLog(log): #Log für Debugzwecke
|
||||||
with open("log.txt", 'a') as out:
|
with open("log.txt", 'a') as out:
|
||||||
out.write(log)
|
out.write(log)
|
||||||
@ -366,12 +286,20 @@ def displayPosition():
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
#print("Listerror")
|
#print("Listerror")
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("Serial Busy")
|
print("Serial Busy")
|
||||||
#root.after(1000,displayPosition)
|
#root.after(1000,displayPosition)
|
||||||
|
|
||||||
|
def grblWrite():
|
||||||
|
if gcode_to_stream != None:
|
||||||
|
print("Stream", gcode_to_stream)
|
||||||
|
grbl_gcode_send.send_gcode(grbl, gcode_to_stream)
|
||||||
|
|
||||||
|
#fdbk = grbl_gcode_send.send_gcode(grbl, line)
|
||||||
|
#print(fdbk)
|
||||||
|
grbl_gcode_send.wait_for_buffer_empty()
|
||||||
|
|
||||||
def grblClose():
|
def grblClose():
|
||||||
# Close file and serial port
|
# Close file and serial port
|
||||||
#f.close()
|
#f.close()
|
||||||
@ -385,8 +313,9 @@ def grblClose():
|
|||||||
root = Tk()
|
root = Tk()
|
||||||
root.title('touchCNC')
|
root.title('touchCNC')
|
||||||
root.geometry('1024x600+0+0')
|
root.geometry('1024x600+0+0')
|
||||||
|
root.geometry('1024x600+0+0')
|
||||||
root.resizable(False,False)#17203b
|
root.resizable(False,False)#17203b
|
||||||
root.attributes('-fullscreen', True)
|
root.attributes('-fullscreen', False)
|
||||||
root.tk_setPalette(background='#11192C', foreground='white',activeBackground='#283867', activeForeground='white' )
|
root.tk_setPalette(background='#11192C', foreground='white',activeBackground='#283867', activeForeground='white' )
|
||||||
|
|
||||||
increments = IntVar()
|
increments = IntVar()
|
||||||
@ -538,7 +467,8 @@ mill_table.grid(row=0, column=4,padx=10, pady=10,columnspan = 4, rowspan = 7)
|
|||||||
#BlockedButtons
|
#BlockedButtons
|
||||||
blkbuttons = (up,down,left,right,z_up,z_down, zero_x, zero_y, zero_z, zero_all, setzero, gozero, spindle)
|
blkbuttons = (up,down,left,right,z_up,z_down, zero_x, zero_y, zero_z, zero_all, setzero, gozero, spindle)
|
||||||
|
|
||||||
timedPositionRequest()
|
|
||||||
|
#timedPositionRequest()
|
||||||
|
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
423
cnc_gerbil.py
Normal file
423
cnc_gerbil.py
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
import serial
|
||||||
|
import time
|
||||||
|
from tkinter import *
|
||||||
|
import serial.tools.list_ports
|
||||||
|
from tkinter import filedialog as fd
|
||||||
|
import os
|
||||||
|
import threading
|
||||||
|
from gerbil.gerbil import Gerbil
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class touchCNC:
|
||||||
|
def __init__(self, root):
|
||||||
|
self.root = root
|
||||||
|
|
||||||
|
# GUI Main
|
||||||
|
self.buttonsize_x = 5
|
||||||
|
self.buttonsize_y = 3
|
||||||
|
self.increments = 0
|
||||||
|
self.BORDER = 2
|
||||||
|
self.states = {'M3': '0', 'M8': '0', 'M6': '0', 'G10': '0'} # self.spindle, Coolant, Toolchange
|
||||||
|
|
||||||
|
self.dict_GCODE = {'G': '0',
|
||||||
|
'X': '0',
|
||||||
|
'Y': '0',
|
||||||
|
'Z': '0',
|
||||||
|
'I': '0',
|
||||||
|
'J': '0',
|
||||||
|
'F': '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
# GUI Color Scheme
|
||||||
|
self.attention = 'red'
|
||||||
|
self.loaded = 'green'
|
||||||
|
self.cooling = 'blue'
|
||||||
|
self.toolchange = 'yellow'
|
||||||
|
self.standard = '#17223B'
|
||||||
|
self.feed = '#283B67'
|
||||||
|
|
||||||
|
self.increments = IntVar()
|
||||||
|
self.movement = Frame(root, relief='ridge', bd=self.BORDER)
|
||||||
|
self.left = Button(root, text="-X", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('X', '-1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
self.right = Button(root, text="+X", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('X', '1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
self.up = Button(root, text="+Y", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('Y', '1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
self.down = Button(root, text="-Y", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('Y', '-1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
self.z_up = Button(root, text="+Z", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('Z', '1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
self.z_down = Button(root, text="-Z", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.jogWrite('Z', '-1', self.increments), bd=self.BORDER, bg=self.standard)
|
||||||
|
|
||||||
|
self.zero_x = Button(root, text="zero X", width=self.buttonsize_x, height=1, command=lambda: self.directWrite('G10 P0 L20 X0'),
|
||||||
|
bd=self.BORDER)
|
||||||
|
self.zero_y = Button(root, text="zero Y", width=self.buttonsize_x, height=1, command=lambda: self.directWrite('G10 P0 L20 Y0'),
|
||||||
|
bd=self.BORDER)
|
||||||
|
self.zero_z = Button(root, text="zero Z", width=self.buttonsize_x, height=1, command=lambda: self.directWrite('G10 P0 L20 Z0'),
|
||||||
|
bd=self.BORDER)
|
||||||
|
self.zero_all = Button(root, text="zeroAll", width=self.buttonsize_x, height=3, command=lambda: self.latchWrite('G10'),
|
||||||
|
bd=self.BORDER, bg='magenta')
|
||||||
|
|
||||||
|
self.setzero = Button(root, text="SetPOS", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.directWrite('G28.1'), bd=self.BORDER)
|
||||||
|
self.gozero = Button(root, text="GoPOS", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('G28'),
|
||||||
|
bd=self.BORDER)
|
||||||
|
|
||||||
|
self.connect_ser = Button(root, text="Cnnct", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=self.grblConnect2, bg='grey', bd=self.BORDER)
|
||||||
|
self.discon_ser = Button(root, text="Dsconct", width=self.buttonsize_x, height=self.buttonsize_y, command= self.grblClose,
|
||||||
|
bd=self.BORDER)
|
||||||
|
self.unlock = Button(root, text="Unlock", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('$X'),
|
||||||
|
bd=self.BORDER)
|
||||||
|
self.start = Button(root, text="START", width=self.buttonsize_x, height=self.buttonsize_y, bg=self.attention,
|
||||||
|
command=self.grblWrite, bd=self.BORDER)
|
||||||
|
self.stop = Button(root, text="STOP", width=self.buttonsize_x, height=self.buttonsize_y, bd=self.BORDER,
|
||||||
|
command=self.grblStop)
|
||||||
|
self.pause = Button(root, text="PAUSE", width=self.buttonsize_x, height=self.buttonsize_y, bg=self.cooling, bd=self.BORDER,
|
||||||
|
command=self.grblPause)
|
||||||
|
self.resume = Button(root, text="RESUME", width=self.buttonsize_x, height=self.buttonsize_y, bd=self.BORDER,
|
||||||
|
command=lambda: self.directWrite('~'))
|
||||||
|
|
||||||
|
self.fopen = Button(root, text="GCODE", width=self.buttonsize_x, height=self.buttonsize_y, bg='grey', fg='black',
|
||||||
|
command=self.openGCODE, bd=self.BORDER)
|
||||||
|
|
||||||
|
self.spindle = Button(root, text="Spindle", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.latchWrite('M3'))
|
||||||
|
self.coolant = Button(root, text="Coolant", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.latchWrite('M8'))
|
||||||
|
self.tool = Button(root, text="Tool", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.latchWrite('M6'))
|
||||||
|
self.macro = Button(root, text="Macro1", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: self.directWrite(' G91 G0 X10 Y10 Z50 F1000'))
|
||||||
|
|
||||||
|
self.inc1 = Button(root, text="Inc 1%", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('‘'),
|
||||||
|
bg=self.feed)
|
||||||
|
self.inc10 = Button(root, text="Inc 10%", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('“'),
|
||||||
|
bg=self.feed)
|
||||||
|
self.dec1 = Button(root, text="Dec 1%", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('”'),
|
||||||
|
bg=self.feed)
|
||||||
|
self.dec10 = Button(root, text="Dec 10%", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite('’'),
|
||||||
|
bg=self.feed)
|
||||||
|
self.reset = Button(root, text="<RESET", width=self.buttonsize_x, height=self.buttonsize_y, command=lambda: self.directWrite(''),
|
||||||
|
bg='grey')
|
||||||
|
|
||||||
|
self.reboot = Button(root, text="REBOOT", width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
command=lambda: os.system('reboot'), bg='grey')
|
||||||
|
|
||||||
|
self.step_incr1 = Radiobutton(root, text='0,1', value=1, variable=self.increments, width=self.buttonsize_x,
|
||||||
|
height=self.buttonsize_y, indicatoron=0)
|
||||||
|
self.step_incr2 = Radiobutton(root, text='1', value=2, variable=self.increments, width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
indicatoron=0)
|
||||||
|
self.step_incr3 = Radiobutton(root, text='10', value=3, variable=self.increments, width=self.buttonsize_x, height=self.buttonsize_y,
|
||||||
|
indicatoron=0)
|
||||||
|
self.step_incr4 = Radiobutton(root, text='100', value=4, variable=self.increments, width=self.buttonsize_x,
|
||||||
|
height=self.buttonsize_y, indicatoron=0)
|
||||||
|
self.step_incr2.select()
|
||||||
|
|
||||||
|
self.terminal = Entry(root, width=8, text="GCODE")
|
||||||
|
self.terminal_send = Button(root, text="SEND", width=self.buttonsize_x, height=self.buttonsize_y, bd=3,
|
||||||
|
command=lambda: terminalWrite())
|
||||||
|
self.terminal_recv = Canvas(root, width=200, height=400, bg='white')
|
||||||
|
|
||||||
|
self.show_ctrl_x_label = Label(root, text="X")
|
||||||
|
self.show_ctrl_y_label = Label(root, text="Y")
|
||||||
|
self.show_ctrl_z_label = Label(root, text="Z")
|
||||||
|
self.show_ctrl_x = Label(root, text="X_POS", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
self.show_ctrl_y = Label(root, text="Y_POS", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
self.show_ctrl_z = Label(root, text="Z_POS", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
|
||||||
|
self.show_ctrl_x_w = Label(root, text="X_POS_W", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
self.show_ctrl_y_w = Label(root, text="Y_POS_W", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
self.show_ctrl_z_w = Label(root, text="Z_POS_W", width=8, height=2, bg='white', relief=SUNKEN, fg='black')
|
||||||
|
|
||||||
|
# self.feed_control = Scale(root, orient = HORIZONTAL, length = 400, label = "self.feedrate",tickinterval = 20)
|
||||||
|
|
||||||
|
# Milling Area and Gcode preview with grid generation
|
||||||
|
|
||||||
|
self.mill_table = Canvas(root, width=400, height=400, bg='grey')
|
||||||
|
|
||||||
|
self.mill_table.create_rectangle(50, 50, 350, 350, fill='white')
|
||||||
|
self.mill_table.create_text(200, 25, text='Fräsbereich 300mm x 300mm')
|
||||||
|
|
||||||
|
for x in range(50, 350, 50):
|
||||||
|
self.mill_table.create_text(x, 400 - x, text=x - 50)
|
||||||
|
|
||||||
|
for x in range(0, 400, 50):
|
||||||
|
for y in range(0, 400, 50):
|
||||||
|
gitter_x = self.mill_table.create_line(x, 0, x, 400)
|
||||||
|
gitter_y = self.mill_table.create_line(0, y, 400, y)
|
||||||
|
|
||||||
|
self.movement.grid(row=0, column=0, columnspan=3, rowspan=1)
|
||||||
|
self.left.grid(row=1, column=0, padx=3, pady=2)
|
||||||
|
self.right.grid(row=1, column=2, padx=3, pady=2)
|
||||||
|
self.up.grid(row=0, column=1, padx=3, pady=10)
|
||||||
|
self.down.grid(row=1, column=1, padx=3, pady=2)
|
||||||
|
self.z_up.grid(row=0, column=3, padx=10, pady=10)
|
||||||
|
self.z_down.grid(row=1, column=3, padx=10, pady=2)
|
||||||
|
|
||||||
|
self.step_incr2.select()
|
||||||
|
|
||||||
|
self.step_incr1.grid(row=2, column=0, padx=3, pady=10)
|
||||||
|
self.step_incr2.grid(row=2, column=1, padx=3, pady=10)
|
||||||
|
self.step_incr3.grid(row=2, column=2, padx=3, pady=10)
|
||||||
|
self.step_incr4.grid(row=2, column=3, padx=3, pady=10)
|
||||||
|
|
||||||
|
self.show_ctrl_x_label.grid(row=3, column=0, padx=3, pady=10)
|
||||||
|
self.show_ctrl_y_label.grid(row=4, column=0, padx=3, pady=10)
|
||||||
|
self.show_ctrl_z_label.grid(row=5, column=0, padx=3, pady=10)
|
||||||
|
|
||||||
|
self.show_ctrl_x.grid(row=3, column=1, padx=0, pady=0, columnspan=1)
|
||||||
|
self.show_ctrl_y.grid(row=4, column=1, padx=0, pady=0, columnspan=1)
|
||||||
|
self.show_ctrl_z.grid(row=5, column=1, padx=0, pady=0, columnspan=1)
|
||||||
|
|
||||||
|
self.show_ctrl_x_w.grid(row=3, column=2, padx=0, pady=0, columnspan=1)
|
||||||
|
self.show_ctrl_y_w.grid(row=4, column=2, padx=0, pady=0, columnspan=1)
|
||||||
|
self.show_ctrl_z_w.grid(row=5, column=2, padx=0, pady=0, columnspan=1)
|
||||||
|
|
||||||
|
self.zero_x.grid(row=3, column=3)
|
||||||
|
self.zero_y.grid(row=4, column=3)
|
||||||
|
self.zero_z.grid(row=5, column=3)
|
||||||
|
self.zero_all.grid(row=6, column=3, padx=10, pady=10)
|
||||||
|
|
||||||
|
self.setzero.grid(row=6, column=0, padx=10, pady=10)
|
||||||
|
self.gozero.grid(row=6, column=1, padx=10, pady=10)
|
||||||
|
|
||||||
|
self.connect_ser.grid(row=7, column=0, padx=10, pady=10)
|
||||||
|
self.discon_ser.grid(row=7, column=1, padx=10, pady=10)
|
||||||
|
self.unlock.grid(row=8, column=1, padx=10, pady=10)
|
||||||
|
self.start.grid(row=7, column=2, padx=10, pady=10)
|
||||||
|
self.stop.grid(row=7, column=3, padx=10, pady=10)
|
||||||
|
self.pause.grid(row=8, column=2, padx=10, pady=10)
|
||||||
|
self.resume.grid(row=8, column=3, padx=10, pady=10)
|
||||||
|
self.fopen.grid(row=8, column=0, padx=10, pady=10)
|
||||||
|
|
||||||
|
self.spindle.grid(row=7, column=4, padx=1, pady=10)
|
||||||
|
self.coolant.grid(row=7, column=5, padx=1, pady=10)
|
||||||
|
self.tool.grid(row=7, column=6, padx=1, pady=10)
|
||||||
|
self.macro.grid(row=7, column=7, padx=1, pady=10)
|
||||||
|
|
||||||
|
self.dec10.grid(row=8, column=4, padx=1, pady=10)
|
||||||
|
self.dec1.grid(row=8, column=5, padx=1, pady=10)
|
||||||
|
self.inc1.grid(row=8, column=6, padx=1, pady=10)
|
||||||
|
self.inc10.grid(row=8, column=7, padx=1, pady=10)
|
||||||
|
|
||||||
|
self.reset.grid(row=8, column=8, padx=1, pady=10)
|
||||||
|
self.reboot.grid(row=8, column=9, padx=1, pady=10)
|
||||||
|
|
||||||
|
self.terminal.grid(row=7, column=8, padx=2, pady=10)
|
||||||
|
self.terminal_send.grid(row=7, column=9, padx=2, pady=10)
|
||||||
|
self.terminal_recv.grid(row=0, column=8, padx=10, pady=10, rowspan=7, columnspan=2)
|
||||||
|
|
||||||
|
# self.feed_control.grid(row = 8, column = 4, columnspan =4)
|
||||||
|
|
||||||
|
self.mill_table.grid(row=0, column=4, padx=10, pady=10, columnspan=4, rowspan=7)
|
||||||
|
|
||||||
|
# sendGRBL()
|
||||||
|
|
||||||
|
# BlockedButtons
|
||||||
|
self.blkbuttons = (self.up, self.down, self.left, self.right, self.z_up, self.z_down, self.zero_x, self.zero_y,
|
||||||
|
self.zero_z, self.zero_all, self.setzero, self.gozero, self.spindle)
|
||||||
|
# Initialize the counter
|
||||||
|
|
||||||
|
|
||||||
|
def on_zero_position(self, label, pos):
|
||||||
|
print("Updated", pos)
|
||||||
|
label.config(text=pos)
|
||||||
|
|
||||||
|
def gui_callback(self, eventstring, *data):
|
||||||
|
args = []
|
||||||
|
print(data)
|
||||||
|
for d in data:
|
||||||
|
args.append(str(d))
|
||||||
|
print("GUI CALLBACK: event={} data={}".format(eventstring.ljust(30), ", ".join(args)))
|
||||||
|
|
||||||
|
if eventstring == "on_stateupdate":
|
||||||
|
print("stateupdate")
|
||||||
|
self.on_zero_position(self.show_ctrl_x, data[0])
|
||||||
|
if eventstring == "on_hash_stateupdate":
|
||||||
|
print("args", type(data[0]))
|
||||||
|
|
||||||
|
self.displayWorkPosition(data[0]["G28"])
|
||||||
|
|
||||||
|
def grblConnect2(self):
|
||||||
|
grbl.cnect("/dev/ttyUSB0", 115200) # or /dev/ttyACM0
|
||||||
|
if grbl.connected:
|
||||||
|
grbl.poll_start()
|
||||||
|
else:
|
||||||
|
print("wtf")
|
||||||
|
|
||||||
|
def displayToolPosition(self):
|
||||||
|
print("update")
|
||||||
|
self.show_ctrl_x.config(text=grbl.cmpos[0])
|
||||||
|
self.show_ctrl_y.config(text=grbl.cmpos[1])
|
||||||
|
self.show_ctrl_z.config(text=grbl.cmpos[2])
|
||||||
|
#self.root.after(1000, self.getPosition)
|
||||||
|
|
||||||
|
def displayWorkPosition(self, pos: list):
|
||||||
|
print("update", pos)
|
||||||
|
self.show_ctrl_x_w.config(text = pos[0])
|
||||||
|
self.show_ctrl_y_w.config(text = pos[1])
|
||||||
|
self.show_ctrl_z_w.config(text = pos[2])
|
||||||
|
#self.root.after(1000, self.getPosition)
|
||||||
|
|
||||||
|
def jogWrite(self, axis, cmd, scale):
|
||||||
|
DECIMAL = [0.1, 1, 10, 100]
|
||||||
|
scale = self.increments.get()
|
||||||
|
MOVE = int(cmd) * DECIMAL[scale - 1]
|
||||||
|
grbl_command = ('$J=G91' + 'G21' + axis + str(MOVE) + 'F1000')
|
||||||
|
# print(grbl_command) $J=G91G21X10F185
|
||||||
|
|
||||||
|
grbl.send_immediately(grbl_command)
|
||||||
|
|
||||||
|
def directWrite(self,cmd):
|
||||||
|
grbl.send_immediately(cmd)
|
||||||
|
|
||||||
|
def latchWrite(self, CMD):
|
||||||
|
|
||||||
|
if self.states[CMD] == '0':
|
||||||
|
self.states[CMD] = '1'
|
||||||
|
if CMD == 'M3':
|
||||||
|
self.spindle.config(bg=self.attention) # A31621
|
||||||
|
if CMD == 'M6':
|
||||||
|
self.tool.config(bg=self.toolchange) # E0CA3C
|
||||||
|
if CMD == 'G10':
|
||||||
|
self.zero_all.config(bg=self.loaded)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.states[CMD] = '0'
|
||||||
|
if CMD == 'M3':
|
||||||
|
self.spindle.config(bg=self.loaded) # A2D729
|
||||||
|
if CMD == 'M6':
|
||||||
|
self.tool.config(bg='grey')
|
||||||
|
# if CMD == 'G10':
|
||||||
|
# zero_all.config(bg= attention)
|
||||||
|
|
||||||
|
if CMD == 'M3':
|
||||||
|
if self.states['M3'] == '1':
|
||||||
|
grbl_command = 'M3 S1000'
|
||||||
|
else:
|
||||||
|
grbl_command = 'M3 S0'
|
||||||
|
|
||||||
|
elif CMD == 'M8':
|
||||||
|
if self.states['M8'] == '1':
|
||||||
|
grbl_command = (CMD)
|
||||||
|
self.coolant.config(bg=self.cooling) # 1F7A8C
|
||||||
|
else:
|
||||||
|
grbl_command = 'M9'
|
||||||
|
self.coolant.config(bg='grey')
|
||||||
|
|
||||||
|
elif CMD == 'G10':
|
||||||
|
grbl_command = 'G10 P0 L20 X0 Y0 Z0'
|
||||||
|
|
||||||
|
else:
|
||||||
|
grbl_command = (CMD)
|
||||||
|
|
||||||
|
# grbl_command = (CMD * int(self.[CMD]) )
|
||||||
|
# print(grbl_command)
|
||||||
|
# print(self.)
|
||||||
|
|
||||||
|
grbl.send_immediately(grbl_command)
|
||||||
|
|
||||||
|
def overrideCMD(self,cmd):
|
||||||
|
pass
|
||||||
|
#grbl.
|
||||||
|
|
||||||
|
def openGCODE(self):
|
||||||
|
filetypes = (('GCODE', '*.nc'), ('All files', '*.*'))
|
||||||
|
GCODE = fd.askopenfilename(title='Open a file', initialdir='/home/thomas/Nextcloud/CAM/', filetypes=filetypes)
|
||||||
|
|
||||||
|
if GCODE != 0:
|
||||||
|
self.fopen.config(bg=self.loaded)
|
||||||
|
extracted = self.extract_GCODE(GCODE)
|
||||||
|
self.draw_GCODE(extracted)
|
||||||
|
grbl.load_file(GCODE)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.fopen.config(bg='grey')
|
||||||
|
|
||||||
|
def grblWrite(self):
|
||||||
|
grbl.job_run()
|
||||||
|
def grblStop(self):
|
||||||
|
grbl.abort()
|
||||||
|
|
||||||
|
def grblPause(self):
|
||||||
|
grbl.hold()
|
||||||
|
|
||||||
|
def extract_GCODE(self, gcode_path: str): # Aufschlüsseln der enthaltenen Koordinaten in ein per Schlüssel zugängiges Dictionary
|
||||||
|
with open(gcode_path, 'r') as gcode:
|
||||||
|
list_dict_GCODE = []
|
||||||
|
for line in gcode:
|
||||||
|
l = line.split() # Elemente trennen und in Liste konvertieren
|
||||||
|
for i in range(0, len(l)):
|
||||||
|
# print (l)
|
||||||
|
if 'G' in l[i]:
|
||||||
|
self.dict_GCODE['G'] = l[i].replace('G',
|
||||||
|
'') # Wert einfügen und gleichzeitig G CODE befehl entfernen
|
||||||
|
if 'X' in l[i]:
|
||||||
|
self.dict_GCODE['X'] = l[i].replace('X', '')
|
||||||
|
if 'Y' in l[i]:
|
||||||
|
self.dict_GCODE['Y'] = l[i].replace('Y', '')
|
||||||
|
if 'Z' in l[i]:
|
||||||
|
self.dict_GCODE['Z'] = l[i].replace('Z', '')
|
||||||
|
if 'I' in l[i] and not 'ZMIN':
|
||||||
|
self.dict_GCODE['I'] = l[i].replace('I', '')
|
||||||
|
if 'J' in l[i]:
|
||||||
|
self.dict_GCODE['J'] = l[i].replace('J', '')
|
||||||
|
if 'F' in l[i] and not 'Fusion':
|
||||||
|
self.dict_GCODE['F'] = l[i].replace('F', '')
|
||||||
|
|
||||||
|
# print(dict_GCODE)
|
||||||
|
list_dict_GCODE.append(
|
||||||
|
self.dict_GCODE.copy()) # Copy notwendig da es sich nur um einen "Pointer" handelt der immer auf die zuletzt aktualisierte dict Zeile zeigt.
|
||||||
|
print(list_dict_GCODE)
|
||||||
|
|
||||||
|
return list_dict_GCODE
|
||||||
|
|
||||||
|
def drawgridTable(self):
|
||||||
|
|
||||||
|
self.mill_table.create_rectangle(50, 50, 350, 350, fill='white')
|
||||||
|
self.mill_table.create_text(200, 25, text='Fräsbereich 300mm x 300mm')
|
||||||
|
|
||||||
|
for x in range(50, 350, 50):
|
||||||
|
self.mill_table.create_text(x, 400 - x, text=x - 50)
|
||||||
|
|
||||||
|
for x in range(0, 400, 50):
|
||||||
|
for y in range(0, 400, 50):
|
||||||
|
gitter_x = self.mill_table.create_line(x, 0, x, 400)
|
||||||
|
gitter_y = self.mill_table.create_line(0, y, 400, y)
|
||||||
|
|
||||||
|
def draw_GCODE(self, glist): # Zeichnen des GCodes zur Beurteilung des Bauraums
|
||||||
|
self.mill_table.delete('all')
|
||||||
|
self.drawgridTable()
|
||||||
|
|
||||||
|
for i in range(0, len(glist) - 1):
|
||||||
|
x_y_current = 50 + float(glist[i]['X']), 350 - float(glist[i]['Y'])
|
||||||
|
x_y_next = 50 + float(glist[i + 1]['X']), 350 - float(glist[i + 1]['Y'])
|
||||||
|
|
||||||
|
self.mill_table.create_line(x_y_current, x_y_next)
|
||||||
|
|
||||||
|
def grblClose(self):
|
||||||
|
grbl.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
print("test")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
root = Tk()
|
||||||
|
root.title('touchCNC')
|
||||||
|
root.geometry('1024x600+0+0')
|
||||||
|
root.geometry('1024x600+0+0')
|
||||||
|
root.resizable(False, False) # 17203b
|
||||||
|
root.attributes('-fullscreen', False)
|
||||||
|
root.tk_setPalette(background='#11192C', foreground='white', activeBackground='#283867',
|
||||||
|
activeForeground='white')
|
||||||
|
|
||||||
|
app = touchCNC(root)
|
||||||
|
grbl = Gerbil(app.gui_callback)
|
||||||
|
grbl.setup_logging()
|
||||||
|
grbl.hash_state_requested = True
|
||||||
|
grbl.gcode_parser_state_requested = True
|
||||||
|
|
||||||
|
root.mainloop()
|
55
grbl_gcode_send.py
Normal file
55
grbl_gcode_send.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import serial
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Define the serial port and baud rate for communication
|
||||||
|
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
|
||||||
|
|
||||||
|
# Function to send G-code commands
|
||||||
|
def send_gcode(ser, command):
|
||||||
|
# Split the command into chunks of 120 characters or less
|
||||||
|
chunks = [command[i:i + 120] for i in range(0, len(command), 120)]
|
||||||
|
|
||||||
|
for chunk in chunks:
|
||||||
|
ser.write((chunk + '\n').encode())
|
||||||
|
response = ser.readline().decode().strip()
|
||||||
|
if response != 'ok':
|
||||||
|
# Handle errors or unexpected responses here
|
||||||
|
print(f"GRBL response: {response}")
|
||||||
|
|
||||||
|
# Function to wait until the buffer is empty
|
||||||
|
def wait_for_buffer_empty():
|
||||||
|
while True:
|
||||||
|
status = send_gcode('?')
|
||||||
|
if status.startswith('<Idle'):
|
||||||
|
break
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# Your G-code commands
|
||||||
|
gcode_commands = [
|
||||||
|
'G21', # Set units to millimeters
|
||||||
|
'G90', # Set to absolute positioning
|
||||||
|
'G1 X10 Y10 F100', # Move to X10 Y10 at a feed rate of 100 mm/min
|
||||||
|
'G1 X20 Y20 F100',
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Initialize communication
|
||||||
|
|
||||||
|
#ser.open()
|
||||||
|
ser.flushInput()
|
||||||
|
ser.flushOutput()
|
||||||
|
|
||||||
|
# Send G-code commands
|
||||||
|
for command in gcode_commands:
|
||||||
|
send_gcode(command)
|
||||||
|
|
||||||
|
# Wait for the buffer to empty
|
||||||
|
wait_for_buffer_empty()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {str(e)}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
ser.close()
|
150
grbl_stream.py
Normal file
150
grbl_stream.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
import serial
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
|
||||||
|
RX_BUFFER_SIZE = 128
|
||||||
|
BAUD_RATE = 115200
|
||||||
|
ENABLE_STATUS_REPORTS = True
|
||||||
|
REPORT_INTERVAL = 1.0 # seconds
|
||||||
|
|
||||||
|
is_run = True # Controls query timer
|
||||||
|
|
||||||
|
class GrblController:
|
||||||
|
def __init__(self, device_file, verbose=True, settings_mode=False, check_mode=False):
|
||||||
|
self.ser = serial.Serial(device_file, BAUD_RATE)
|
||||||
|
self.verbose = verbose
|
||||||
|
self.settings_mode = settings_mode
|
||||||
|
self.check_mode = check_mode
|
||||||
|
self.timerThread = None
|
||||||
|
|
||||||
|
def open(self):
|
||||||
|
self.ser.open()
|
||||||
|
self.ser.flushInput()
|
||||||
|
self.ser.flushOutput()
|
||||||
|
time.sleep(2)
|
||||||
|
self.ser.flushInput()
|
||||||
|
if self.check_mode:
|
||||||
|
self.set_check_mode()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.ser.close()
|
||||||
|
|
||||||
|
def set_check_mode(self):
|
||||||
|
self.send_command("$C\n")
|
||||||
|
while True:
|
||||||
|
grbl_out = self.ser.readline().strip()
|
||||||
|
if grbl_out.find('error') >= 0:
|
||||||
|
print("REC:", grbl_out)
|
||||||
|
print(" Failed to set Grbl check-mode. Aborting...")
|
||||||
|
quit()
|
||||||
|
elif grbl_out.find('ok') >= 0:
|
||||||
|
if self.verbose:
|
||||||
|
print('REC:', grbl_out)
|
||||||
|
break
|
||||||
|
|
||||||
|
def send_command(self, command):
|
||||||
|
self.ser.write((command + '\n').encode())
|
||||||
|
|
||||||
|
def read_response(self):
|
||||||
|
return self.ser.readline().strip()
|
||||||
|
|
||||||
|
def send_gcode(self, gcode_file):
|
||||||
|
l_count = 0
|
||||||
|
error_count = 0
|
||||||
|
start_time = time.time()
|
||||||
|
self.start_status_report_timer()
|
||||||
|
|
||||||
|
for line in gcode_file:
|
||||||
|
l_count += 1
|
||||||
|
l_block = line.strip()
|
||||||
|
if self.settings_mode:
|
||||||
|
self.send_command(l_block)
|
||||||
|
while True:
|
||||||
|
grbl_out = self.read_response()
|
||||||
|
if grbl_out.find('ok') >= 0:
|
||||||
|
if self.verbose:
|
||||||
|
print(" REC<{}: \"{}\"".format(l_count, grbl_out))
|
||||||
|
break
|
||||||
|
elif grbl_out.find('error') >= 0:
|
||||||
|
if self.verbose:
|
||||||
|
print(" REC<{}: \"{}\"".format(l_count, grbl_out))
|
||||||
|
error_count += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print(" MSG: \"{}\"".format(grbl_out))
|
||||||
|
else:
|
||||||
|
c_line = []
|
||||||
|
for char in l_block:
|
||||||
|
c_line.append(len(char) + 1)
|
||||||
|
grbl_out = ''
|
||||||
|
while sum(c_line) >= RX_BUFFER_SIZE - 1 or self.ser.inWaiting():
|
||||||
|
out_temp = self.read_response()
|
||||||
|
if out_temp.find('ok') < 0 and out_temp.find('error') < 0:
|
||||||
|
print(" MSG: \"{}\"".format(out_temp))
|
||||||
|
else:
|
||||||
|
if out_temp.find('error') >= 0:
|
||||||
|
error_count += 1
|
||||||
|
del c_line[0]
|
||||||
|
if self.verbose:
|
||||||
|
print(" REC<{}: \"{}\"".format(l_count, out_temp))
|
||||||
|
self.send_command(char)
|
||||||
|
if self.verbose:
|
||||||
|
print("SND>{}: \"{}\"".format(l_count, char))
|
||||||
|
|
||||||
|
while l_count > 0:
|
||||||
|
out_temp = self.read_response()
|
||||||
|
if out_temp.find('ok') < 0 and out_temp.find('error') < 0:
|
||||||
|
print(" MSG: \"{}\"".format(out_temp))
|
||||||
|
else:
|
||||||
|
if out_temp.find('error') >= 0:
|
||||||
|
error_count += 1
|
||||||
|
l_count -= 1
|
||||||
|
del c_line[0]
|
||||||
|
if self.verbose:
|
||||||
|
print(" REC<{}: \"{}\"".format(l_count, out_temp))
|
||||||
|
|
||||||
|
self.stop_status_report_timer()
|
||||||
|
end_time = time.time()
|
||||||
|
is_run = False
|
||||||
|
|
||||||
|
print("\nG-code streaming finished!")
|
||||||
|
print("Time elapsed: {}\n".format(end_time - start_time))
|
||||||
|
|
||||||
|
if self.check_mode:
|
||||||
|
if error_count > 0:
|
||||||
|
print("CHECK FAILED: {} errors found! See output for details.\n".format(error_count))
|
||||||
|
else:
|
||||||
|
print("CHECK PASSED: No errors found in g-code program.\n")
|
||||||
|
else:
|
||||||
|
print("WARNING: Wait until Grbl completes buffered g-code blocks before exiting.")
|
||||||
|
|
||||||
|
def start_status_report_timer(self):
|
||||||
|
if ENABLE_STATUS_REPORTS:
|
||||||
|
self.timerThread = threading.Thread(target=self.periodic_timer)
|
||||||
|
self.timerThread.daemon = True
|
||||||
|
self.timerThread.start()
|
||||||
|
|
||||||
|
def stop_status_report_timer(self):
|
||||||
|
self.timerThread.join()
|
||||||
|
|
||||||
|
def periodic_timer(self):
|
||||||
|
while is_run:
|
||||||
|
self.send_command('?')
|
||||||
|
time.sleep(REPORT_INTERVAL)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='Stream g-code file to grbl.')
|
||||||
|
parser.add_argument('gcode_file', type=argparse.FileType('r'), help='g-code filename to be streamed')
|
||||||
|
parser.add_argument('device_file', help='serial device path')
|
||||||
|
parser.add_argument('-q', '--quiet', action='store_true', default=False, help='suppress output text')
|
||||||
|
parser.add_argument('-s', '--settings', action='store_true', default=False, help='settings write mode')
|
||||||
|
parser.add_argument('-c', '--check', action='store_true', default=False, help='stream in check mode')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
grbl_controller = GrblController(args.device_file, not args.quiet, args.settings, args.check)
|
||||||
|
grbl_controller.open()
|
||||||
|
grbl_controller.send_gcode(args.gcode_file)
|
||||||
|
grbl_controller.close()
|
315
modules.py
Normal file
315
modules.py
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
grbl = 0
|
||||||
|
port = None
|
||||||
|
i = 10
|
||||||
|
GCODE = 0
|
||||||
|
gcode_to_stream = []
|
||||||
|
countbuf = 0
|
||||||
|
writebuffer_byPass = []
|
||||||
|
writebuffer = []
|
||||||
|
readbuffer = []
|
||||||
|
AXIS = 'X'
|
||||||
|
states = {'M3': '0', 'M8': '0', 'M6': '0', 'G10': '0'} # Spindle, Coolant, Toolchange
|
||||||
|
dict_GCODE = {'G': '0',
|
||||||
|
'X': '0',
|
||||||
|
'Y': '0',
|
||||||
|
'Z': '0',
|
||||||
|
'I': '0',
|
||||||
|
'J': '0',
|
||||||
|
'F': '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
# GUI Main
|
||||||
|
buttonsize_x = 5
|
||||||
|
buttonsize_y = 3
|
||||||
|
increments = 0
|
||||||
|
BORDER = 2
|
||||||
|
freetosend = 1
|
||||||
|
|
||||||
|
# GUI Color Scheme
|
||||||
|
attention = 'red'
|
||||||
|
loaded = 'green'
|
||||||
|
cooling = 'blue'
|
||||||
|
toolchange = 'yellow'
|
||||||
|
standard = '#17223B'
|
||||||
|
feed = '#283B67'
|
||||||
|
|
||||||
|
|
||||||
|
def grblConnect2():
|
||||||
|
global grbl
|
||||||
|
global port
|
||||||
|
|
||||||
|
# Serial Connection
|
||||||
|
locations = ['/dev/ttyACM0', '/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyACM1', '/dev/ttyACM2', '/dev/ttyACM3',
|
||||||
|
'/dev/ttyS0', '/dev/ttyS1', '/dev/ttyS2', '/dev/ttyS3']
|
||||||
|
|
||||||
|
for device in locations:
|
||||||
|
try:
|
||||||
|
# print([comport.device for comport in serial.tools.list_ports.comports()])
|
||||||
|
print("Trying...", device)
|
||||||
|
grbl = serial.Serial(port=device, baudrate=115200, timeout=.5) # dsrdtr= True)
|
||||||
|
port = device
|
||||||
|
# grbl.open()
|
||||||
|
# print(grbl.readline())
|
||||||
|
grbl.write(str.encode("\r\n\r\n"))
|
||||||
|
time.sleep(2) # Wait for grbl to initialize
|
||||||
|
grbl.flushInput() # Flush startup text in serial input
|
||||||
|
connect_ser.config(bg=loaded)
|
||||||
|
# print("connected")
|
||||||
|
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
# print ("Failed to connect on",device)
|
||||||
|
grbl = 0
|
||||||
|
|
||||||
|
# Stream g-code to grbl
|
||||||
|
# Stream GCODE from -https://onehossshay.wordpress.com/2011/08/26/grbl-a-simple-python-interface/-
|
||||||
|
|
||||||
|
|
||||||
|
def jogWrite(AXIS, CMD, scale): # Schreiben von manuellen Positionierungsbefehlen
|
||||||
|
global freetosend
|
||||||
|
|
||||||
|
DECIMAL = [0.1, 1, 10, 100]
|
||||||
|
scale = increments.get()
|
||||||
|
MOVE = int(CMD) * DECIMAL[scale - 1]
|
||||||
|
grbl_command = ('$J=G91' + 'G21' + AXIS + str(MOVE) + 'F1000')
|
||||||
|
# print(grbl_command) $J=G91G21X10F185
|
||||||
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
|
|
||||||
|
|
||||||
|
def switchButtonState(button): # Umschalter für Knopfstatus
|
||||||
|
if button["state"] == DISABLED:
|
||||||
|
button["state"] = NORMAL
|
||||||
|
else:
|
||||||
|
button["state"] = DISABLED
|
||||||
|
|
||||||
|
|
||||||
|
def directWrite(CMD): # Direktes schreiben eines Befehls
|
||||||
|
global freetosend
|
||||||
|
# print(freetosend)
|
||||||
|
grbl_command = CMD
|
||||||
|
|
||||||
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
|
|
||||||
|
|
||||||
|
def latchWrite(CMD):
|
||||||
|
global states
|
||||||
|
global freetosend
|
||||||
|
if states[CMD] == '0':
|
||||||
|
states[CMD] = '1'
|
||||||
|
if CMD == 'M3':
|
||||||
|
spindle.config(bg=attention) # A31621
|
||||||
|
if CMD == 'M6':
|
||||||
|
tool.config(bg=toolchange) # E0CA3C
|
||||||
|
if CMD == 'G10':
|
||||||
|
zero_all.config(bg=loaded)
|
||||||
|
|
||||||
|
else:
|
||||||
|
states[CMD] = '0'
|
||||||
|
if CMD == 'M3':
|
||||||
|
spindle.config(bg=loaded) # A2D729
|
||||||
|
if CMD == 'M6':
|
||||||
|
tool.config(bg='grey')
|
||||||
|
# if CMD == 'G10':
|
||||||
|
# zero_all.config(bg= attention)
|
||||||
|
|
||||||
|
if CMD == 'M3':
|
||||||
|
if states['M3'] == '1':
|
||||||
|
grbl_command = 'M3 S1000'
|
||||||
|
else:
|
||||||
|
grbl_command = 'M3 S0'
|
||||||
|
|
||||||
|
elif CMD == 'M8':
|
||||||
|
if states['M8'] == '1':
|
||||||
|
grbl_command = (CMD)
|
||||||
|
coolant.config(bg=cooling) # 1F7A8C
|
||||||
|
else:
|
||||||
|
grbl_command = 'M9'
|
||||||
|
coolant.config(bg='grey')
|
||||||
|
|
||||||
|
elif CMD == 'G10':
|
||||||
|
grbl_command = 'G10 P0 L20 X0 Y0 Z0'
|
||||||
|
|
||||||
|
else:
|
||||||
|
grbl_command = (CMD)
|
||||||
|
|
||||||
|
# grbl_command = (CMD * int(states[CMD]) )
|
||||||
|
# print(grbl_command)
|
||||||
|
# print(states)
|
||||||
|
|
||||||
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
|
|
||||||
|
|
||||||
|
def terminalWrite(): # Holt Zeichenstring von Editfeld und sendet es
|
||||||
|
grbl_command = terminal.get()
|
||||||
|
# print(grbl_command)
|
||||||
|
|
||||||
|
grbl_gcode_send.send_gcode(grbl, grbl_command)
|
||||||
|
|
||||||
|
|
||||||
|
def infoScreen(data): # Anzeigecanvas für GRBL Rückmeldungen
|
||||||
|
global i
|
||||||
|
terminalFrame = Frame(terminal_recv, bg='white')
|
||||||
|
terminal_recv.create_window(10, i, window=terminalFrame, anchor='nw')
|
||||||
|
Label(terminalFrame, text=data, font=('Calibri', 10), bg='white', fg='black').pack()
|
||||||
|
i += 22
|
||||||
|
if i >= 400:
|
||||||
|
i = 10
|
||||||
|
terminal_recv.delete("all")
|
||||||
|
|
||||||
|
|
||||||
|
def openGCODE(): # Dialog zur Gcode Auswahl und öffnen der Datei als GCODE Objekt
|
||||||
|
global gcode_to_stream
|
||||||
|
filetypes = (('GCODE', '*.nc'), ('All files', '*.*'))
|
||||||
|
GCODE = fd.askopenfile(title='Open a file', initialdir='/home/thomas/Nextcloud/CAM/', filetypes=filetypes)
|
||||||
|
|
||||||
|
if GCODE != 0:
|
||||||
|
fopen.config(bg=loaded)
|
||||||
|
extracted = extract_GCODE(GCODE)
|
||||||
|
draw_GCODE(extracted)
|
||||||
|
gcode_to_stream = GCODE
|
||||||
|
|
||||||
|
else:
|
||||||
|
fopen.config(bg='grey')
|
||||||
|
|
||||||
|
# build_xy = findEnvelope() #Aufruf PLatz im Bauraum
|
||||||
|
# mill_table.create_rectangle(build_xy[0],build_xy[1], fill = 'blue', stipple = 'gray75') # Zeichnen des Objekts im Bauraum
|
||||||
|
|
||||||
|
|
||||||
|
def extract_GCODE(gcode: list): # Aufschlüsseln der enthaltenen Koordinaten in ein per Schlüssel zugängiges Dictionary
|
||||||
|
|
||||||
|
list_dict_GCODE = []
|
||||||
|
for line in gcode:
|
||||||
|
l = line.split() # Elemente trennen und in Liste konvertieren
|
||||||
|
for i in range(0, len(l)):
|
||||||
|
# print (l)
|
||||||
|
if 'G' in l[i]:
|
||||||
|
dict_GCODE['G'] = l[i].replace('G', '') # Wert einfügen und gleichzeitig G CODE befehl entfernen
|
||||||
|
if 'X' in l[i]:
|
||||||
|
dict_GCODE['X'] = l[i].replace('X', '')
|
||||||
|
if 'Y' in l[i]:
|
||||||
|
dict_GCODE['Y'] = l[i].replace('Y', '')
|
||||||
|
if 'Z' in l[i]:
|
||||||
|
dict_GCODE['Z'] = l[i].replace('Z', '')
|
||||||
|
if 'I' in l[i] and not 'ZMIN':
|
||||||
|
dict_GCODE['I'] = l[i].replace('I', '')
|
||||||
|
if 'J' in l[i]:
|
||||||
|
dict_GCODE['J'] = l[i].replace('J', '')
|
||||||
|
if 'F' in l[i] and not 'Fusion':
|
||||||
|
dict_GCODE['F'] = l[i].replace('F', '')
|
||||||
|
|
||||||
|
# print(dict_GCODE)
|
||||||
|
list_dict_GCODE.append(
|
||||||
|
dict_GCODE.copy()) # Copy notwendig da es sich nur um einen "Pointer" handelt der immer auf die zuletzt aktualisierte dict Zeile zeigt.
|
||||||
|
print(list_dict_GCODE)
|
||||||
|
|
||||||
|
return list_dict_GCODE
|
||||||
|
|
||||||
|
|
||||||
|
def draw_GCODE(glist): # Zeichnen des GCodes zur Beurteilung des Bauraums
|
||||||
|
|
||||||
|
for i in range(0, len(glist) - 1):
|
||||||
|
x_y_current = 50 + float(glist[i]['X']), 350 - float(glist[i]['Y'])
|
||||||
|
x_y_next = 50 + float(glist[i + 1]['X']), 350 - float(glist[i + 1]['Y'])
|
||||||
|
|
||||||
|
mill_table.create_line(x_y_current, x_y_next)
|
||||||
|
|
||||||
|
|
||||||
|
def writeToFileLog(log): # Log für Debugzwecke
|
||||||
|
with open("log.txt", 'a') as out:
|
||||||
|
out.write(log)
|
||||||
|
|
||||||
|
|
||||||
|
def displayPosition_request(grbl_pos):
|
||||||
|
if grbl != 0:
|
||||||
|
try:
|
||||||
|
position = str(grbl_pos)
|
||||||
|
# print (readbuffer)
|
||||||
|
|
||||||
|
position = position.replace('Idle|', ',')
|
||||||
|
position = position.replace('Run|', ',')
|
||||||
|
position = position.replace('WPos:', '')
|
||||||
|
position = position.replace('MPos:', '')
|
||||||
|
position = position.replace('>', ',')
|
||||||
|
position = position.replace('|', ',')
|
||||||
|
position.strip()
|
||||||
|
coordinates_list = position.split(',')
|
||||||
|
# print(coordinates_list)
|
||||||
|
show_ctrl_x.config(text=coordinates_list[1])
|
||||||
|
show_ctrl_y.config(text=coordinates_list[2])
|
||||||
|
show_ctrl_z.config(text=coordinates_list[3])
|
||||||
|
|
||||||
|
mill_table.create_line(coordinates_list[1], coordinates_list[2], coordinates_list[1],
|
||||||
|
coordinates_list[2] + 50, arrow=FIRST)
|
||||||
|
|
||||||
|
# show_ctrl_x_w.config(text = coordinates_list[4])
|
||||||
|
# show_ctrl_y_w.config(text = coordinates_list[5])
|
||||||
|
# show_ctrl_z_w.config(text = coordinates_list[6])
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# print("Listerror")
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Serial Busy")
|
||||||
|
# root.after(1000,displayPosition)
|
||||||
|
|
||||||
|
|
||||||
|
def displayPosition():
|
||||||
|
global readbuffer
|
||||||
|
if grbl != 0:
|
||||||
|
try:
|
||||||
|
position = str(readbuffer[2])
|
||||||
|
# print (readbuffer)
|
||||||
|
|
||||||
|
position = position.replace('Idle|', ',')
|
||||||
|
position = position.replace('Run|', ',')
|
||||||
|
position = position.replace('WPos:', '')
|
||||||
|
position = position.replace('MPos:', '')
|
||||||
|
position = position.replace('>', ',')
|
||||||
|
position = position.replace('|', ',')
|
||||||
|
position.strip()
|
||||||
|
coordinates_list = position.split(',')
|
||||||
|
# print(coordinates_list)
|
||||||
|
show_ctrl_x.config(text=coordinates_list[1])
|
||||||
|
show_ctrl_y.config(text=coordinates_list[2])
|
||||||
|
show_ctrl_z.config(text=coordinates_list[3])
|
||||||
|
|
||||||
|
mill_table.create_line(coordinates_list[1], coordinates_list[2], coordinates_list[1] + 10,
|
||||||
|
coordinates_list[2] + 20)
|
||||||
|
mill_table.create_line(coordinates_list[1], coordinates_list[2], coordinates_list[1] - 10,
|
||||||
|
coordinates_list[2] + 20)
|
||||||
|
mill_table.create_line(coordinates_list[1] - 10, coordinates_list[2] + 20, coordinates_list[1] + 10,
|
||||||
|
coordinates_list[2] + 20)
|
||||||
|
# show_ctrl_x_w.config(text = coordinates_list[4])
|
||||||
|
# show_ctrl_y_w.config(text = coordinates_list[5])
|
||||||
|
# show_ctrl_z_w.config(text = coordinates_list[6])
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
# print("Listerror")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Serial Busy")
|
||||||
|
# root.after(1000,displayPosition)
|
||||||
|
|
||||||
|
|
||||||
|
def grblWrite():
|
||||||
|
if gcode_to_stream != None:
|
||||||
|
print("Stream", gcode_to_stream)
|
||||||
|
grbl_gcode_send.send_gcode(grbl, gcode_to_stream)
|
||||||
|
|
||||||
|
# fdbk = grbl_gcode_send.send_gcode(grbl, line)
|
||||||
|
# print(fdbk)
|
||||||
|
grbl_gcode_send.wait_for_buffer_empty()
|
||||||
|
|
||||||
|
|
||||||
|
def grblClose():
|
||||||
|
# Close file and serial port
|
||||||
|
# f.close()
|
||||||
|
try:
|
||||||
|
grbl.close()
|
||||||
|
print("closed")
|
||||||
|
connect_ser.config(bg='grey')
|
||||||
|
except:
|
||||||
|
print("Connection still open")
|
Loading…
Reference in New Issue
Block a user