-
Notifications
You must be signed in to change notification settings - Fork 0
/
draw copy 8.py
386 lines (286 loc) · 13.8 KB
/
draw copy 8.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox, filedialog
import serial # Import the serial module
import tempfile
import os
# Declare global variables
canvas = None
serial_port = None
def setup_serial():
global serial_port
serial_port = serial.Serial('COM3', 115200, timeout=1)
print("Serial port opened on COM3 with baud rate 115200.")
setup_serial() # Call the setup_serial function to initialize the serial port
def send_lines_to_engraver():
global canvas
lines = canvas.find_withtag("line") # Get all items tagged with 'line'
gcode_commands = []
for line in lines:
x1, y1, x2, y2 = canvas.coords(line) # Get coordinates of each line
gcode_commands.append(f"G1 X{x1} Y{y1} S100") # Assuming laser power is set to 100 (adjust as needed)
gcode_commands.append(f"G1 X{x2} Y{y2} S0") # Turn off laser at the end of the line
send_command(gcode_commands)
def send_command(gcode_commands):
global serial_port
for command in gcode_commands:
serial_port.write((command + "\n").encode())
serial_port.flush()
def save_gcode():
global canvas
lines = canvas.find_withtag("line")
machine_height = 860 # Assuming the machine's height is 860mm, adjust as needed
gcode_lines = []
for line in lines:
x1, y1, x2, y2 = canvas.coords(line)
# Adjust coordinates to match desired position relative to bottom-left corner
# Subtract x-coordinate from machine width and y-coordinate from machine height
# to move the origin to the bottom-left corner
y1 = machine_height - y1
y2 = machine_height - y2
# Add feedrate (speed) and laser power (S1000 for full power, S0 for off)
gcode_lines.append(f"G1 X{x1} Y{y1} F2000") # Move to starting position
gcode_lines.append("M3 S1000") # Turn laser on
gcode_lines.append(f"G1 X{x1} Y{y1} F2000") # Move to starting position (redundant)
gcode_lines.append(f"G1 X{x2} Y{y2} F2000") # Move to ending position
gcode_lines.append("M5") # Turn laser off
file_path = filedialog.asksaveasfilename(defaultextension=".gcode",
filetypes=[("G-code Files", "*.gcode")])
if file_path:
with open(file_path, 'w') as f:
f.write("\n".join(gcode_lines))
messagebox.showinfo("G-code Export", "G-code saved successfully.")
import tempfile
def Engrave():
global canvas, speed_entry, power_entry
# Get the values from the speed and power entries
speed = speed_entry.get()
power = power_entry.get()
# Convert speed and power to integers (assuming they are entered as integers)
speed = int(speed)
power = int(power)
# Define the traveling speed when the laser is off
travel_speed = 2000
lines = canvas.find_withtag("line")
machine_height = 860 # Assuming the machine's height is 860mm, adjust as needed
gcode_lines = []
for line in lines:
x1, y1, x2, y2 = canvas.coords(line)
# Adjust coordinates to match desired position relative to bottom-left corner
y1 = machine_height - y1
y2 = machine_height - y2
# Move to starting position
gcode_lines.append(f"G1 X{x1} Y{y1} F{travel_speed} S{power}")
# Turn laser on
gcode_lines.append(f"M3 S{power}")
# Move to starting position (redundant)
gcode_lines.append(f"G1 X{x1} Y{y1} F{travel_speed}")
# Move to ending position
gcode_lines.append(f"G1 X{x2} Y{y2} F{speed if power > 0 else travel_speed}")
# Turn laser off
gcode_lines.append("M5")
# Create a temporary file to store the G-code
with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file:
temp_file.write("\n".join(gcode_lines))
# Send the G-code from the temporary file to the laser engraver
with open(temp_file.name, 'r') as f:
gcode_commands = f.readlines()
send_command([command.strip() for command in gcode_commands])
# Delete the temporary file after sending the G-code
os.unlink(temp_file.name)
messagebox.showinfo("Engraving", "G-code sent to the laser engraver.")
# Function to create a rectangle shape with drag
def create_rectangle_with_drag(start_x, start_y, end_x, end_y):
# Calculate the coordinates for the rectangle based on the drag
x1 = min(start_x, end_x)
y1 = min(start_y, end_y)
x2 = max(start_x, end_x)
y2 = max(start_y, end_y)
# Create the rectangle on the canvas
canvas.create_rectangle(x1, y1, x2, y2, outline="black", width=2, tags="line")
# Function to create a rectangle shape
def create_rectangle():
# Set the shape variable to rectangle
shape_var.set("rectangle")
# Prompt the user to drag to create the rectangle
messagebox.showinfo("Draw Rectangle", "Click and drag to draw a rectangle.")
# Function to create a circle shape
def create_circle():
# Set the shape variable to circle
shape_var.set("circle")
# Prompt the user to drag to create the circle
messagebox.showinfo("Draw Circle", "Click and drag to draw a circle.")
def cut():
global serial_port
file_path = filedialog.askopenfilename(filetypes=[("G-code Files", "*.gcode")])
if file_path:
print("Reading G-code file:", file_path)
with open(file_path, 'r') as f:
gcode_commands = f.readlines()
print("Sending G-code commands:")
for command in gcode_commands:
print(command.strip())
send_command([command.strip() for command in gcode_commands]) # Sending each command individually
def home_laser():
global serial_port
print("Sending homing command...")
# Send homing command along with the current position as 0,0
send_command(["G28 F2000 "])
print("Homing command sent.")
Set_Zero()
def Set_Zero():
global serial_port
print("Sending Zero homing command...")
# Send homing command along with the current position as 0,0
send_command([" G90 G28 X0 Y0 Z0"])
print("Zero homing command sent.")
def main():
global canvas, serial_port
root = tk.Tk()
root.title("Draw Cut Application")
root.geometry("1600x1200") # Adjusted window size for better layout
# Menu frame for inputs at the top of the window
menu_frame = tk.Frame(root)
menu_frame.pack(side='top', fill='x', expand=False)
# Variables for machine and material dimensions with default values
machine_width = tk.IntVar(value=410)
machine_height = tk.IntVar(value=860)
# Canvas setup; dimensions will be updated via a function
canvas = tk.Canvas(root, bg='white')
canvas.pack(fill='both', expand=True)
# Function to update canvas size based on machine dimensions
def update_canvas():
mw, mh = machine_width.get(), machine_height.get()
canvas.config(width=mw, height=mh)
canvas.delete("all") # Clear previous drawings
# Draw the maximum cutting area
canvas.create_rectangle(2.5, 2.5, mw - 2.5, mh - 2.5, outline="blue", width=1)
# Function to clear all lines from the canvas
def clear_lines():
canvas.delete("line") # Assumes all lines are tagged with 'line' when created
# Machine width and height entries
machine_width_label = ttk.Label(menu_frame, text="Machine Width (mm):")
machine_width_label.pack(side='left', padx=5)
machine_width_entry = ttk.Entry(menu_frame, textvariable=machine_width, width=7)
machine_width_entry.pack(side='left', padx=5)
machine_height_label = ttk.Label(menu_frame, text="Machine Height (mm):")
machine_height_label.pack(side='left', padx=5)
machine_height_entry = ttk.Entry(menu_frame, textvariable=machine_height, width=7)
machine_height_entry.pack(side='left', padx=5)
confirm_machine_button = ttk.Button(menu_frame, text="Set Machine Size", command=update_canvas)
confirm_machine_button.pack(side='left', padx=5)
material_x_label = ttk.Label(menu_frame, text="Material Width (mm):")
material_x_label.pack(side='left', padx=5)
material_x_entry = ttk.Entry(menu_frame, width=7)
material_x_entry.pack(side='left', padx=5)
material_y_label = ttk.Label(menu_frame, text="Material Height (mm):")
material_y_label.pack(side='left', padx=5)
material_y_entry = ttk.Entry(menu_frame, width=7)
material_y_entry.pack(side='left', padx=5)
confirm_button = ttk.Button(menu_frame, text="Set Material", command=lambda: draw_material())
confirm_button.pack(side='left', padx=5)
draw_line_button = ttk
draw_line_button = ttk.Button(menu_frame, text="Enable Draw Line", command=lambda: toggle_line_drawing())
draw_line_button.pack(side='left', padx=5)
# Additional button to clear lines
clear_lines_button = ttk.Button(menu_frame, text="Clear Lines", command=clear_lines)
clear_lines_button.pack(side='left', padx=5)
# Additional button to clear lines
gcode_button = ttk.Button(menu_frame, text="save g_code", command=save_gcode)
gcode_button.pack(side='left', padx=5)
# Additional button to clear lines
cut_button = ttk.Button(menu_frame, text="Cut", command=cut)
cut_button.pack(side='left', padx=5)
# Button for homing
home_button = ttk.Button(menu_frame, text="Home", command=home_laser)
home_button.pack(side='left', padx=5)
# Button for homing
zero_button = ttk.Button(menu_frame, text="Set Zero", command=Set_Zero)
zero_button.pack(side='left', padx=5)
engrave_button = ttk.Button(menu_frame, text="Engrave", command=Engrave)
engrave_button.pack(side='left', padx=5)
# Inside the main() function, define speed_entry and power_entry as global variables
global speed_entry, power_entry
speed_label = ttk.Label(menu_frame, text="Speed (F):")
speed_label.pack(side='left', padx=5)
speed_entry = ttk.Entry(menu_frame, width=7)
speed_entry.pack(side='left', padx=5)
power_label = ttk.Label(menu_frame, text="Power (S):")
power_label.pack(side='left', padx=5)
power_entry = ttk.Entry(menu_frame, width=7)
power_entry.pack(side='left', padx=5)
# Second menu frame for basic shapes
shape_menu_frame = tk.Frame(root)
shape_menu_frame.pack(side='top', fill='x', expand=False)
# Button to create a rectangle
rectangle_button = ttk.Button(shape_menu_frame, text="Rectangle", command=create_rectangle)
rectangle_button.pack(side='left', padx=5)
# Button to create a circle
circle_button = ttk.Button(shape_menu_frame, text="Circle", command=create_circle)
circle_button.pack(side='left', padx=5)
# Variables to track mouse drag
start_x = None
start_y = None
# Function to handle mouse button press
def handle_mouse_press(event):
nonlocal start_x, start_y
start_x = event.x
start_y = event.y
# Function to handle mouse button release
def handle_mouse_release(event):
nonlocal start_x, start_y
if start_x is not None and start_y is not None:
end_x = event.x
end_y = event.y
# Create the shape based on the starting and ending coordinates
create_rectangle_with_drag(start_x, start_y, end_x, end_y)
start_x = None
start_y = None
# Bind mouse press and release events to the canvas
canvas.bind("<ButtonPress-1>", handle_mouse_press)
canvas.bind("<ButtonRelease-1>", handle_mouse_release)
# Functions to handle drawing and material settings
line_start = None
line_drawing_enabled = False # To track if line drawing mode is enabled
def handle_left_click(event):
nonlocal line_start
if line_drawing_enabled:
if line_start is None:
line_start = (event.x, event.y)
canvas.create_oval(event.x-2, event.y-2, event.x+2, event.y+2, fill="green")
else:
# Tagging lines with 'line' for easy removal
canvas.create_line(line_start[0], line_start[1], event.x, event.y, fill="green", width=2, tags="line")
line_start = (event.x, event.y)
def handle_right_click(event):
nonlocal line_start
line_start = None
def draw_material():
canvas.delete("material_area")
try:
material_width = int(material_x_entry.get())
material_height = int(material_y_entry.get())
if 0 < material_width <= machine_width.get() and 0 < material_height <= machine_height.get():
x1 = 2.5
y1 = machine_height.get() - material_height - 2.5
canvas.create_rectangle(x1, y1, x1 + material_width, y1 + material_height, outline="red", width=2, fill="light grey", tags="material_area")
else:
messagebox.showerror("Error", "Material dimensions must fit within the specified machine dimensions.")
except ValueError:
messagebox.showerror("Error", "Please enter valid integer dimensions.")
def toggle_line_drawing():
nonlocal line_drawing_enabled
if line_drawing_enabled:
canvas.unbind("<Button-1>")
canvas.unbind("<Button-3>")
draw_line_button.config(text="Enable Draw Line")
else:
canvas.bind("<Button-1>", handle_left_click)
canvas.bind("<Button-3>", handle_right_click)
draw_line_button.config(text="Disable Draw Line")
line_drawing_enabled = not line_drawing_enabled
# Initialize the canvas with the default machine size
update_canvas()
root.mainloop()
if __name__ == "__main__":
main()