-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgcode.py
202 lines (191 loc) · 5.25 KB
/
gcode.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
#!/usr/bin/env python
#
# vim: set tabstop=4:
#
# Copyright (c) 2014 David Jander
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
from math import *
import sys
class GCode(object):
def __init__(self, cfg):
self.dim = cfg.settings["num_motors"]
self.motor_name = cfg.settings["motor_name"]
self.pos = {}
self.reset()
self.pos["command"] = "position" # Default position command
self.set_zero_extruder(False)
self.relative_mode = False
self.zoffset = 0.0
def reset(self):
for m in self.motor_name:
self.pos[m] = 0.0
self.pos["F"] = 0.0 # Feedrate
def set_position(self, pos):
for i, m in enumerate(self.motor_name):
self.pos[m] = pos[i]
def set_zero_extruder(self, val):
self.zero_extruder = val
def process_M(self, code, args):
if code == 82: # Absolute E codes
pass
elif code == 104: # Set hotend temperature
val = float(args['S'])
return {"command": "setpoint", "type": "ext", "value": val, "wait": False}
elif code == 106: # Set extruder fan speed
print("Set extruder fan speed:", args.get("S", 0))
elif code == 109: # Set temperature and wait
val = float(args['S'])
return {"command": "setpoint", "type": "ext", "value": val, "wait": True}
elif code == 116: # Wait for setpoints
return {"command": "wait"}
elif code == 120: # Enable endstop
return {"command": "endstop", "enable": True}
elif code == 121: # Disable endstop
return {"command": "endstop", "enable": False}
elif code == 140: # Set heated bed temperature
val = float(args['S'])
return {"command": "setpoint", "type": "bed", "value": val, "wait": False}
elif code == 190: # Set heated bed temperature and wait
val = float(args['S'])
return {"command": "setpoint", "type": "bed", "value": val, "wait": True}
else:
print("Unimplemented M: code =", code, repr(args))
return None
def process_G(self, code, args):
if code == 1 or code == 0: # Controlled movement
for code in args:
if self.zero_extruder and code == "E":
continue
val = args[code]
if code in self.pos:
if code == "F":
val = val / 60
if self.relative_mode and code in ['X', 'Y', 'Z', 'E']:
self.pos[code] += val
else:
if code == 'Z':
val += self.zoffset
self.pos[code] = val
else:
print("G1 unknown code:", code)
return self.pos
elif code == 21: # Set metric units
pass
elif code == 28: # Home position
print("Home position")
for n in self.motor_name:
if n in args:
self.pos[n] = 0.0
ret = {"command": "home"}
ret.update(args)
return ret
elif code == 90: # Absolute positioning
print("Set absolute positioning")
self.relative_mode = False
elif code == 91: # Relative positioning
print("Set relative positioning")
self.relative_mode = True
elif code == 92: # Set position
for a in ['X', 'Y', 'Z', 'E']:
if a in args:
self.pos[a] = args[a]
elif len(args) == 0:
self.pos[a] = 0
ret = {}
ret.update(self.pos)
ret["command"] = "set_position"
return ret
else:
print("Unimplemented G: code =", code, repr(args))
return None
def process_T(self, code, args):
if code == 0: # Tool selection 0
pass
else:
print("Unimplemented T: code =", code, repr(args))
def process_comment(self, l):
l = l.lower().strip(' \r\n')
cmd = {"command": "log", 'type': 'part'}
if l.startswith('layer:'):
num = l.split(':',1)[1]
try:
num = int(num)
except ValueError:
return None
cmd['type'] = 'layer'
cmd['value'] = num
return cmd
elif l.startswith('type:'):
cmd['value'] = l.split(':',1)[1]
return cmd
elif l.startswith('layer count:') or l.startswith('layer_count:'):
num = l.split(':',1)[1]
try:
num = int(num)
except ValueError:
return None
cmd['type'] = 'layer_count'
cmd['value'] = num
return cmd
elif l.startswith('layer '):
num = l.split(' ',1)[1]
if num[0] == 's':
num = num[1:]
try:
num = int(num)
except ValueError:
return None
cmd['type'] = 'layer'
cmd['value'] = num
return cmd
elif l.startswith('skirt'):
cmd['value'] = 'skirt'
return cmd
elif l.startswith('infill'):
cmd['value'] = 'fill'
return cmd
elif l.startswith('shell'):
cmd['value'] = 'wall'
return cmd
def process_line(self, l):
l = l.strip(" \r\n")
if len(l) < 2:
return None
cmd = l[0]
if cmd == ";":
return self.process_comment(l[1:])
words = l[1:].split()
try:
code = int(words[0], 10)
except ValueError:
return None
words = words[1:]
args = {}
for w in words:
if w[0] == ";":
# return self.process_comment(w[1:]) # FIXME: Rest of line?
break
if w[0] in ["X", "Y", "Z", "E", "F", "S", "P", "R"]:
snum = w[1:]
try:
if "." in snum:
num = float(snum)
else:
num = int(snum)
except ValueError:
num = w
args[w[0]] = num
if cmd == "G":
return self.process_G(code, args)
elif cmd == "M":
return self.process_M(code, args)
elif cmd == "T":
return self.process_T(code, args)
return None
def set_zoffset(self, zoff):
self.pos['Z'] = self.pos['Z'] - self.zoffset + zoff
self.zoffset = zoff