- Added executable

- Removed old files
- changed readme
- Added old color scheme
- added requirements.txt
This commit is contained in:
Thomas Herrmann 2023-12-28 20:38:53 +01:00
parent 20dc9754d9
commit f1ee9b8419
9 changed files with 36 additions and 1002 deletions

View File

@ -1,5 +1,5 @@
# touchCNC -not ready for production - TESTING STAGE # touchCNC 1.0
GRBL 1.1 CNC Controller for ODROID C2 with VU PLus Touch Screen GRBL 1.1 CNC Controller for ODROID C2 with VU PLus Touch Screen or Linux Desktop
Should run on any System wit at least 1024x600 Screen Resolution. Should run on any System wit at least 1024x600 Screen Resolution.
@ -7,19 +7,35 @@ Should run on any System wit at least 1024x600 Screen Resolution.
- Zero positions - Zero positions
- Job commands - Job commands
- Spindle Coolant, Tool and Macro commands - Spindle Coolant, Tool and Macro commands
- Gcode milling envelope preview (low cpu usage), - Gcode milling envelope preview
- G28 Position - G28 Position
- Feed override - Feed override (Not yet working)
- terminal - terminal
- Laser status and switch
![Screen](https://user-images.githubusercontent.com/6392076/133233601-8ef0e06f-e055-4677-8828-ed092aa37250.png) ![Screen](https://user-images.githubusercontent.com/6392076/133233601-8ef0e06f-e055-4677-8828-ed092aa37250.png)
- Tested on latest Armbian stable https://www.armbian.com/odroid-c2/#kernels-archive-all
- Tested on Manjaro
- Using cncpro v3 with grbl1.1f
Tested on latest Armbian stable https://www.armbian.com/odroid-c2/#kernels-archive-all ## Clone to your PC
`git clone https://github.com/BKLronin/touchCNC.git`
Based on ## Install
- (Create env)
- In folder enter:
`pip install requirements.txt`
## Run
`python cnc_gerbil.py`
or
`cd dist`
`./cnc_gerbil`
### Based on:
Python3 Python3
tkinter tkinter
pyserial pyserial
gerbil
In some cases you have to manually install tkinter via apt and pyserial via pip.

474
cnc.py
View File

@ -1,474 +0,0 @@
import serial
import time
from tkinter import *
import serial.tools.list_ports
from tkinter import filedialog as fd
import os
import threading
import grbl_gcode_send
import grbl_stream
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")
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' )
increments = IntVar()
movement = Frame(root, relief = 'ridge', bd = BORDER)
left = Button(root, text="-X", width = buttonsize_x, height = buttonsize_y, command = lambda:jogWrite('X', '-1', increments),bd = BORDER, bg = standard)
right = Button(root, text="+X",width = buttonsize_x, height = buttonsize_y,command = lambda:jogWrite('X', '1', increments),bd = BORDER, bg = standard)
up = Button(root, text="+Y", width = buttonsize_x, height = buttonsize_y,command = lambda:jogWrite('Y', '1', increments),bd = BORDER, bg = standard)
down = Button(root, text="-Y",width = buttonsize_x, height = buttonsize_y,command = lambda:jogWrite('Y', '-1', increments),bd = BORDER, bg = standard)
z_up = Button(root, text="+Z",width = buttonsize_x, height = buttonsize_y,command = lambda:jogWrite('Z', '1', increments) ,bd = BORDER, bg = standard)
z_down = Button(root, text="-Z",width = buttonsize_x, height = buttonsize_y,command = lambda:jogWrite('Z', '-1', increments),bd = BORDER, bg = standard)
zero_x = Button(root, text="zero X",width = buttonsize_x, height = 1, command = lambda:directWrite('G10 P0 L20 X0'),bd = BORDER)
zero_y = Button(root, text="zero Y",width = buttonsize_x, height = 1, command = lambda:directWrite('G10 P0 L20 Y0'),bd = BORDER)
zero_z = Button(root, text="zero Z",width = buttonsize_x, height = 1, command = lambda:directWrite('G10 P0 L20 Z0'),bd = BORDER)
zero_all=Button(root, text="zeroAll",width = buttonsize_x, height = 3, command = lambda:latchWrite('G10'),bd = BORDER, bg= 'magenta')
setzero =Button(root, text="SetPOS",width = buttonsize_x, height = buttonsize_y, command = lambda:directWrite('G28.1'),bd = BORDER)
gozero =Button(root, text="GoPOS",width = buttonsize_x, height = buttonsize_y, command = lambda:directWrite('G28'),bd = BORDER)
connect_ser = Button(root, text="Cnnct",width = buttonsize_x, height = buttonsize_y, command = grblConnect2, bg = 'grey',bd = BORDER)
discon_ser = Button(root, text="Dsconct",width = buttonsize_x, height = buttonsize_y, command = lambda:grblClose(),bd = BORDER)
unlock = Button(root, text="Unlock",width = buttonsize_x, height = buttonsize_y, command = lambda:directWrite('$X'),bd = BORDER)
start = Button(root, text="START",width = buttonsize_x, height = buttonsize_y, bg = attention, command = lambda: threading.Thread(target = grblWrite).start(),bd = BORDER)
stop = Button(root, text="STOP",width = buttonsize_x, height = buttonsize_y,bd = BORDER, command = lambda: directWrite('') )
pause = Button(root, text="PAUSE",width = buttonsize_x, height = buttonsize_y, bg = cooling,bd = BORDER,command = lambda: directWrite('!') )
resume = Button(root, text="RESUME",width = buttonsize_x, height = buttonsize_y,bd = BORDER,command = lambda: directWrite('~'))
fopen = Button(root, text="GCODE",width = buttonsize_x , height = buttonsize_y, bg = 'grey',fg = 'black', command = openGCODE,bd = BORDER)
spindle = Button(root, text="Spindle",width = buttonsize_x, height = buttonsize_y,command = lambda:latchWrite('M3'))
coolant = Button(root, text="Coolant",width = buttonsize_x, height = buttonsize_y,command = lambda:latchWrite('M8') )
tool = Button(root, text="Tool",width = buttonsize_x, height = buttonsize_y,command = lambda:latchWrite('M6') )
macro = Button(root, text="Macro1",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(' G91 G0 X10 Y10 Z50 F1000') )
inc1 = Button(root, text="Inc 1%",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(''),bg= feed)
inc10 = Button(root,text="Inc 10%",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(''),bg= feed )
dec1 = Button(root, text="Dec 1%",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(''),bg= feed )
dec10 = Button(root,text="Dec 10%",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(''),bg= feed )
reset = Button(root,text="<RESET",width = buttonsize_x, height = buttonsize_y,command = lambda:directWrite(''),bg= 'grey' )
reboot= Button(root,text="REBOOT",width = buttonsize_x, height = buttonsize_y,command = lambda: os.system('reboot'),bg= 'grey' )
step_incr1 = Radiobutton(root, text= '0,1', value = 1 , variable = increments,width = buttonsize_x, height = buttonsize_y, indicatoron = 0 )
step_incr2 = Radiobutton(root, text= '1', value = 2 , variable = increments,width = buttonsize_x, height = buttonsize_y, indicatoron = 0 )
step_incr3 = Radiobutton(root, text= '10', value = 3 , variable = increments,width = buttonsize_x, height = buttonsize_y, indicatoron = 0 )
step_incr4 = Radiobutton(root, text= '100', value = 4 , variable = increments,width = buttonsize_x, height = buttonsize_y, indicatoron = 0 )
step_incr2.select()
terminal = Entry(root, width =8, text="GCODE")
terminal_send = Button(root, text="SEND",width = buttonsize_x, height = buttonsize_y, bd= 3, command = lambda: terminalWrite())
terminal_recv = Canvas(root, width = 200, height =400, bg = 'white')
show_ctrl_x_label = Label(root,text = "X")
show_ctrl_y_label = Label(root,text = "Y")
show_ctrl_z_label = Label(root,text = "Z")
show_ctrl_x =Label(root, text = "X_POS", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
show_ctrl_y =Label(root, text = "Y_POS", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
show_ctrl_z =Label(root, text = "Z_POS", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
show_ctrl_x_w =Label(root, text = "X_POS_W", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
show_ctrl_y_w =Label(root, text = "Y_POS_W", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
show_ctrl_z_w =Label(root, text = "Z_POS_W", width = 8, height = 2, bg ='white', relief = SUNKEN, fg= 'black')
#feed_control = Scale(root, orient = HORIZONTAL, length = 400, label = "Feedrate",tickinterval = 20)
#Milling Area and Gcode preview with grid generation
mill_table= Canvas(root, width= 400, height = 400, bg = 'grey')
mill_table.create_rectangle(50,50,350,350, fill ='white')
mill_table.create_text(200,25,text = 'Fräsbereich 300mm x 300mm')
for x in range(50,350,50):
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 = mill_table.create_line(x,0,x,400)
gitter_y = mill_table.create_line(0,y,400,y)
movement.grid(row = 0, column = 0, columnspan = 3, rowspan = 1)
left.grid(row=1, column=0, padx=3, pady=2)
right.grid(row=1, column=2,padx=3, pady=2)
up.grid(row=0, column=1, padx=3, pady=10)
down.grid(row=1, column=1,padx=3, pady=2)
z_up.grid(row=0, column=3,padx=10, pady=10)
z_down.grid(row=1, column=3,padx=10, pady=2)
step_incr2.select()
step_incr1.grid(row=2, column=0,padx=3, pady=10)
step_incr2.grid(row=2, column=1,padx=3, pady=10)
step_incr3.grid(row=2, column=2,padx=3, pady=10)
step_incr4.grid(row=2, column=3,padx=3, pady=10)
show_ctrl_x_label.grid(row=3, column=0,padx=3, pady=10)
show_ctrl_y_label.grid(row=4, column=0,padx=3, pady=10)
show_ctrl_z_label.grid(row=5, column=0,padx=3, pady=10)
show_ctrl_x.grid(row=3, column=1,padx=0, pady=0, columnspan =1)
show_ctrl_y.grid(row=4, column=1,padx=0, pady=0, columnspan =1)
show_ctrl_z.grid(row=5, column=1,padx=0, pady=0, columnspan =1)
show_ctrl_x_w.grid(row=3, column=2,padx=0, pady=0, columnspan =1)
show_ctrl_y_w.grid(row=4, column=2,padx=0, pady=0, columnspan =1)
show_ctrl_z_w.grid(row=5, column=2,padx=0, pady=0, columnspan =1)
zero_x.grid(row=3, column=3)
zero_y.grid(row=4, column=3)
zero_z.grid(row=5, column=3)
zero_all.grid(row=6, column=3,padx=10, pady=10)
setzero.grid(row=6, column=0,padx=10, pady=10)
gozero.grid(row=6, column=1,padx=10, pady=10)
connect_ser.grid(row=7, column=0,padx=10, pady=10)
discon_ser.grid(row=7, column=1,padx=10, pady=10)
unlock.grid(row=8, column=1,padx=10, pady=10)
start.grid(row=7, column=2,padx=10, pady=10)
stop.grid(row=7, column=3,padx=10, pady=10)
pause.grid(row=8, column=2,padx=10, pady=10)
resume.grid(row=8, column=3,padx=10, pady=10)
fopen.grid(row=8, column=0,padx=10, pady=10)
spindle.grid(row=7, column=4,padx=1, pady=10)
coolant.grid(row=7, column=5,padx=1, pady=10)
tool.grid(row=7, column=6,padx=1, pady=10)
macro.grid(row=7, column=7,padx=1, pady=10)
dec10.grid(row=8, column=4,padx=1, pady=10)
dec1.grid(row=8, column=5,padx=1, pady=10)
inc1.grid(row=8, column=6,padx=1, pady=10)
inc10.grid(row=8, column=7,padx=1, pady=10)
reset.grid(row=8, column=8,padx=1, pady=10)
reboot.grid(row=8, column=9,padx=1, pady=10)
terminal.grid(row = 7, column = 8, padx =2, pady =10)
terminal_send.grid(row = 7, column = 9, padx =2, pady =10)
terminal_recv.grid(row = 0, column = 8, padx =10, pady =10,rowspan = 7, columnspan =2)
#feed_control.grid(row = 8, column = 4, columnspan =4)
mill_table.grid(row=0, column=4,padx=10, pady=10,columnspan = 4, rowspan = 7)
#sendGRBL()
#BlockedButtons
blkbuttons = (up,down,left,right,z_up,z_down, zero_x, zero_y, zero_z, zero_all, setzero, gozero, spindle)
#timedPositionRequest()
root.mainloop()

View File

@ -21,7 +21,7 @@ class touchCNC:
self.increments = 0 self.increments = 0
self.BORDER = 2 self.BORDER = 2
self.feedspeed = None self.feedspeed = None
self.states = {'M3': '0', 'M8': '0', 'M6': '0', 'G10': '0', '32' :0} # self.spindle, Coolant, Toolchange self.states = {'M3': '0', 'M8': '0', 'M6': '0', 'G10': '0', '32' :'0'} # self.spindle, Coolant, Toolchange
self.dict_GCODE = {'G': '0', self.dict_GCODE = {'G': '0',
'X': '0', 'X': '0',
@ -43,6 +43,14 @@ class touchCNC:
self.feed = self.secondary self.feed = self.secondary
self.transport = '#FA7921' self.transport = '#FA7921'
# Classic Scheme
attention = 'red'
loaded = 'green'
cooling = 'blue'
toolchange = 'yellow'
standard = '#17223B'
feed = '#283B67'
self.increments = IntVar() self.increments = IntVar()
self.movement = Frame(root, relief='ridge', bd=self.BORDER, padx=10, pady=10) self.movement = Frame(root, relief='ridge', bd=self.BORDER, padx=10, pady=10)
@ -343,6 +351,7 @@ class touchCNC:
def grblClose(self): def grblClose(self):
grbl.softreset() grbl.softreset()
print(grbl.connected)
grbl.disconnect() grbl.disconnect()
self.connect_ser.config(bg=self.secondary) self.connect_ser.config(bg=self.secondary)

BIN
dist/cnc vendored

Binary file not shown.

BIN
dist/cnc_gerbil vendored Executable file

Binary file not shown.

View File

@ -1,55 +0,0 @@
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()

View File

@ -1,150 +0,0 @@
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()

View File

@ -1,315 +0,0 @@
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")

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
altgraph==0.17.4
numpy==1.26.2
pyserial==3.5