Handle G90/G91 and M82/M83 distinct by default

By default G90/G91 define relativeMode, M82/M83 define relativeE. The
extruder coordinate will be viewed as relative when either
relativeMode or relativeE are set. This mirrors the implementation in
Marlin (current and legacy forks) as well as Repetier.

SmoothieWare's implementation resets the relative mode of the
extruder on a G90/G91. To still accomodate this different
implementation a new settings has been added under Settings >
Feature: "G90/G91 overrides relative extruder mode". Checking this
switches to the alternative interpretation for future gcode analysis
and visualization.

The only difference between the two of them is that the following
segment of GCODE:

    M83
    G90

will have the extruder still set to relative on Marlin and
Repetier but set to absolute on Smoothieware.

Please note that the setting in all likelihood will be moved to
the printer profile in the future, since it makes more sense to have
it on a per printer basis. It's not part of the set of features
available for auto detection since it's required for GCODE analysis
and hence needs to be known even outside of a connection to the
printer.

Implements #1818
This commit is contained in:
Gina Häußge 2017-05-10 16:40:52 +02:00
parent f0b63a8e7f
commit dba95ee94f
8 changed files with 73 additions and 38 deletions

View file

@ -128,7 +128,8 @@ def getSettings():
"modelSizeDetection": s.getBoolean(["feature", "modelSizeDetection"]),
"firmwareDetection": s.getBoolean(["feature", "firmwareDetection"]),
"printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"]),
"blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"])
"blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"]),
"g90InfluencesExtruder": s.getBoolean(["feature", "g90InfluencesExtruder"])
},
"serial": {
"port": connectionOptions["portPreference"],
@ -335,6 +336,7 @@ def _saveSettings(data):
if "firmwareDetection" in data["feature"]: s.setBoolean(["feature", "firmwareDetection"], data["feature"]["firmwareDetection"])
if "printCancelConfirmation" in data["feature"]: s.setBoolean(["feature", "printCancelConfirmation"], data["feature"]["printCancelConfirmation"])
if "blockWhileDwelling" in data["feature"]: s.setBoolean(["feature", "blockWhileDwelling"], data["feature"]["blockWhileDwelling"])
if "g90InfluencesExtruder" in data["feature"]: s.setBoolean(["feature", "g90InfluencesExtruder"], data["feature"]["g90InfluencesExtruder"])
if "serial" in data.keys():
if "autoconnect" in data["serial"]: s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"])

View file

@ -205,7 +205,8 @@ default_settings = {
"modelSizeDetection": True,
"firmwareDetection": True,
"printCancelConfirmation": True,
"blockWhileDwelling": False
"blockWhileDwelling": False,
"g90InfluencesExtruder": False
},
"folder": {
"uploads": None,

View file

@ -9,6 +9,7 @@ var firstReport;
var toolOffsets = [
{x: 0, y: 0}
];
var g90InfluencesExtruder = false;
var z_heights = {};
var model = [];
var max = {x: undefined, y: undefined, z: undefined};
@ -232,8 +233,8 @@ var doParse = function () {
var center_i, center_j, direction;
var prevX = 0, prevY = 0, prevZ = 0;
var f, lastF = 4000;
var extrude = false, extrudeRelative = false, retract = 0;
var positionRelative = false;
var extrude = false, relativeE = false, retract = 0;
var relativeMode = false;
var zLift = false;
var zLiftZ = undefined;
var zLiftMoves = [];
@ -273,7 +274,7 @@ var doParse = function () {
for (var j = 0; j < args.length; j++) {
switch (argChar = args[j].charAt(0).toLowerCase()) {
case 'x':
if (positionRelative) {
if (relativeMode) {
x = prevX + Number(args[j].slice(1)) + offset.x;
} else {
x = Number(args[j].slice(1)) + offset.x;
@ -282,7 +283,7 @@ var doParse = function () {
break;
case 'y':
if (positionRelative) {
if (relativeMode) {
y = prevY + Number(args[j].slice(1)) + offset.y;
} else {
y = Number(args[j].slice(1)) + offset.y;
@ -291,7 +292,7 @@ var doParse = function () {
break;
case 'z':
if (positionRelative) {
if (relativeMode) {
z = prevZ + Number(args[j].slice(1));
} else {
z = Number(args[j].slice(1));
@ -306,13 +307,13 @@ var doParse = function () {
assumeNonDC = true;
numSlice = Number(args[j].slice(1));
if (!extrudeRelative) {
if (relativeMode || relativeE) {
prev_extrude[tool]["abs"] = numSlice;
prev_extrude[tool][argChar] += numSlice;
} else {
// absolute extrusion positioning
prev_extrude[tool]["abs"] = numSlice - prev_extrude[tool][argChar];
prev_extrude[tool][argChar] = numSlice;
} else {
prev_extrude[tool]["abs"] = numSlice;
prev_extrude[tool][argChar] += numSlice;
}
extrude = prev_extrude[tool]["abs"] > 0;
@ -359,15 +360,19 @@ var doParse = function () {
move = true;
}
} else if (/^(?:M82)/i.test(line)) {
extrudeRelative = false;
relativeE = false;
} else if (/^(?:G91)/i.test(line)) {
positionRelative = true;
extrudeRelative = true;
relativeMode = true;
if (g90InfluencesExtruder) {
relativeE = true;
}
} else if (/^(?:G90)/i.test(line)) {
positionRelative = false;
extrudeRelative = false;
relativeMode = false;
if (g90InfluencesExtruder) {
relativeE = false;
}
} else if (/^(?:M83)/i.test(line)) {
extrudeRelative = true;
relativeE = true;
} else if (/^(?:M101)/i.test(line)) {
dcExtrude = true;
} else if (/^(?:M103)/i.test(line)) {
@ -407,10 +412,10 @@ var doParse = function () {
case 'b':
case 'c':
numSlice = Number(args[j].slice(1));
if (!extrudeRelative)
prev_extrude[tool][argChar] = 0;
else {
if (relativeMode || relativeE) {
prev_extrude[tool][argChar] = numSlice;
} else {
prev_extrude[tool][argChar] = 0;
}
break;
}
@ -568,7 +573,8 @@ var parseGCode = function (message) {
gcode = message.gcode;
firstReport = message.options.firstReport;
toolOffsets = message.options.toolOffsets;
if (!toolOffsets || toolOffsets.length == 0) toolOffsets = [{x: 0, y: 0}]
if (!toolOffsets || toolOffsets.length == 0) toolOffsets = [{x: 0, y: 0}];
g90InfluencesExtruder = message.options.g90InfluencesExtruder;
doParse();
gcode = [];

View file

@ -24,7 +24,8 @@ GCODE.gCodeReader = (function(){
analyzeModel: false,
toolOffsets: [
{x: 0, y: 0}
]
],
g90InfluencesExtruder: false
};
var percentageTree = undefined;
@ -138,7 +139,8 @@ GCODE.gCodeReader = (function(){
gcode: gcode,
options: {
firstReport: 5,
toolOffsets: gCodeOptions["toolOffsets"]
toolOffsets: gCodeOptions["toolOffsets"],
g90InfluencesExtruder: gCodeOptions["g90InfluencesExtruder"]
}
}
}

View file

@ -138,6 +138,14 @@ $(function() {
}
});
self.settings.feature_g90InfluencesExtruder.subscribe(function() {
GCODE.ui.updateOptions({
reader: {
g90InfluencesExtruder: self.settings.feature_g90InfluencesExtruder()
}
});
});
self._retrieveBedDimensions = function(currentProfileData) {
if (currentProfileData == undefined) {
currentProfileData = self.settings.printerProfiles.currentProfileData();

View file

@ -143,6 +143,7 @@ $(function() {
self.feature_firmwareDetection = ko.observable(undefined);
self.feature_printCancelConfirmation = ko.observable(undefined);
self.feature_blockWhileDwelling = ko.observable(undefined);
self.feature_g90InfluencesExtruder = ko.observable(undefined);
self.serial_port = ko.observable();
self.serial_baudrate = ko.observable();

View file

@ -41,6 +41,13 @@
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: feature_g90InfluencesExtruder" id="settings-g90InfluencesExtruder"> {{ _('<code>G90</code>/<code>G91</code> overrides relative extruder mode') }} <span class="label">{{ _('Smoothieware') }}</span>
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">

View file

@ -230,9 +230,9 @@ class gcode(object):
maxExtrusion = [0.0]
currentExtruder = 0
totalMoveTimeMinute = 0.0
absoluteE = True
relativeE = False
relativeMode = False
scale = 1.0
posAbs = True
fwretractTime = 0
fwretractDist = 0
fwrecoverTime = 0
@ -242,6 +242,8 @@ class gcode(object):
feedrate = 2000
offsets = printer_profile["extruder"]["offsets"]
g90InfluencesExtruder = settings().getBoolean(["feature", "g90InfluencesExtruder"])
for line in gcodeFile:
if self._abort:
raise AnalysisAborted(reenqueue=self._reenqueue)
@ -318,23 +320,25 @@ class gcode(object):
# Use new coordinates if provided. If not provided, use prior coordinates (minus tool offset)
# in absolute and 0.0 in relative mode.
newPos = Vector3D(x if x is not None else (pos.x - toolOffset.x if posAbs else 0.0),
y if y is not None else (pos.y - toolOffset.y if posAbs else 0.0),
z if z is not None else (pos.z - toolOffset.z if posAbs else 0.0))
newPos = Vector3D(x if x is not None else (0.0 if relativeMode else pos.x - toolOffset.x),
y if y is not None else (0.0 if relativeMode else pos.y - toolOffset.y),
z if z is not None else (0.0 if relativeMode else pos.z - toolOffset.z))
if posAbs:
# Absolute mode: scale coordinates and apply tool offsets
pos = newPos * scale + toolOffset
else:
if relativeMode:
# Relative mode: scale and add to current position
pos += newPos * scale
else:
# Absolute mode: scale coordinates and apply tool offsets
pos = newPos * scale + toolOffset
if f is not None and f != 0:
feedrate = f
if e is not None:
if absoluteE:
# make sure e is relative
if relativeMode or relativeE:
# e is already relative, nothing to do
pass
else:
e -= currentE[currentExtruder]
# If move with extrusion, calculate new min/max coordinates of model
@ -389,9 +393,13 @@ class gcode(object):
if z is not None:
pos.z = center.z
elif G == 90: #Absolute position
posAbs = True
relativeMode = False
if g90InfluencesExtruder:
relativeE = False
elif G == 91: #Relative position
posAbs = False
relativeMode = True
if g90InfluencesExtruder:
relativeE = True
elif G == 92:
x = getCodeFloat(line, 'X')
y = getCodeFloat(line, 'Y')
@ -417,9 +425,9 @@ class gcode(object):
elif M is not None:
if M == 82: #Absolute E
absoluteE = True
relativeE = False
elif M == 83: #Relative E
absoluteE = False
relativeE = True
elif M == 207 or M == 208: #Firmware retract settings
s = getCodeFloat(line, 'S')
f = getCodeFloat(line, 'F')