Skip to content

Commit

Permalink
bugfix: fix temperature with a floating point.
Browse files Browse the repository at this point in the history
The start gcode macros in recent versions of Cura
format the print temperature as a floating point.
Other temperature commands in the gcode don't have
such behavior.

On Finder (version 1?) with the more recent firmware, this
causes the temperature to be the fixed to start at 185C,
which appears to be the "default start temperature" or some
rounding error when reading the floating point temperature.

This commit fixes that by parsing the 'M104 SXXX' commands,
and changing the temperature by converting it to integer.
This also allows the temperature to be embedded to the .gx
file header.

I took the opportunity to move the parsing commands into the
gx.py script, as a way to potentially easy the proccess to
make this a standalone script that can potentially be used
by other slicers/software.

Fixes #21
Related to #2 and #16
  • Loading branch information
ronoaldo committed Apr 7, 2024
1 parent abd556b commit 69a8ec5
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 34 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ plugins/FlashforgeFinderIntegration/printer/defs/finder.def.json:
git submodule init
git submodule update

release: build
test:
find plugins -type f -iname '*_test.py' | xargs -I{} python3 {}

release: build test
if [ x"$(VERSION)" = x"master" ] ; then echo "Unable to release from master. Use make VERSION=X.Y.Z" ; exit 1; fi
git tag v$(VERSION)
git push --tags
38 changes: 5 additions & 33 deletions plugins/GXWriter/GXWriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")

import re
from io import StringIO, BufferedIOBase
from typing import cast, List
from . import gx
from .gx import GX

qt_version = 6
try:
Expand All @@ -26,17 +25,6 @@
qt_version = 5
from PyQt5 import QtGui, QtCore

# Helper function that extracts values from gcode to add to the binary header.
def getValue(line, key, default=None):
if key not in line:
return default
else:
subPart = line[line.find(key) + len(key):]
m = re.search('^-?[0-9]+\\.?[0-9]*', subPart)
try:
return float(m.group(0))
except:
return default

# Implements a MeshWriter that creates the xgcode header before the gcode
# content.
Expand Down Expand Up @@ -77,30 +65,14 @@ def write(self, stream, nodes: List[SceneNode], mode = MeshWriter.OutputMode.Bin
def modify(self, gcode):
try:
# Initialize GX header variables
g = gx.GX()
g.gcode = gcode.encode('latin-1')
# Parse values from original gcode
self._parse_gcode_info(g, gcode)
self._createSnapshot(g)
return g.encode()
gx = GX.from_gcode(gcode)
# Add snapshot image from Cura
self._createSnapshot(gx)
return gx.encode()
except Exception:
Logger.logException("w", "\n*** Failed to create gx file, defaulting to write regular gcode!!! ***\n")
return gcode.encode('latin-1')

def _parse_gcode_info(self, gx, gcode):
for line in gcode.split("\n"):
if line.startswith(';TIME:'):
gx.print_time = int(getValue(line, ';TIME:', 0))
if line.startswith(';Filament used:'):
f = float(line.split(':')[1].split('m')[0].strip())
f = f*100
gx.filament_usage = int(f)
if line.startswith(';Layer height:'):
f = float(getValue(line, ';Layer height:', 0))
f = f*1000
gx.layer_height = int(f)
Logger.log("i", "Updated values from struct =>", vars(gx))

def _createSnapshot(self, g, *args):
Logger.log("i", "Creating thumbnail image ...")
try:
Expand Down
43 changes: 43 additions & 0 deletions plugins/GXWriter/gx.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@

import struct
import base64
import re

# Helper function that extracts values from gcode to add to the binary header.
def getValue(line, key, default=None):
if key not in line:
return default
else:
subPart = line[line.find(key) + len(key):]
m = re.search('^-?[0-9]+\\.?[0-9]*', subPart)
try:
return float(m.group(0))
except:
return default

class GX(object):
"""
Expand Down Expand Up @@ -103,6 +116,36 @@ def _encode(self):
buff+= self.gcode
return buff

@staticmethod
def from_gcode(gcode):
gx = GX()
gx.gcode = gcode.encode('latin-1')
for line in gcode.split("\n"):
if line.startswith(';TIME:'):
gx.print_time = int(getValue(line, ';TIME:', 0))
if line.startswith(';Filament used:'):
f = float(line.split(':')[1].split('m')[0].strip())
f = f*100
gx.filament_usage = int(f)
if line.startswith(';Layer height:'):
f = float(getValue(line, ';Layer height:', 0))
f = f*1000
gx.layer_height = int(f)
if line.startswith('M104 S'):
# Fixes temperature if expressed in float (195.0 -> 195)
args = []
for a in line.split(' '):
if a.startswith('S'):
t = float(a.replace('S', ''))
t = int(t)
a = "S{}".format(t)
if gx.print_temperature <= 0.00:
# Stores the first temperature to the xgcode header
gx.print_temperature = t
args.append(a)
gx.gcode = gx.gcode.replace(line.encode(), ' '.join(args).encode())
return gx

# base64 --wrap=80 testdata/cura.bmp | xclip -sel clip
_SAMPLE_BMP = base64.decodebytes("""
Qk12OAAAAAAAADYAAAAoAAAAUAAAADwAAAABABgAAAAAAEA4AADDDgAAww4AAAAAAAAAAAAAnJycnJyc
Expand Down
49 changes: 49 additions & 0 deletions plugins/GXWriter/gx_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest
from gx import GX

test_gcode = """;FLAVOR:Marlin
;TIME:1066
;Filament used: 0.681442m
;Layer height: 0.12
;MINX:-14
;MINY:-14
;MINZ:0.2
;MAXX:14
;MAXY:14
;MAXZ:10.04
;TARGET_MACHINE.NAME:Flashforge Finder
;Generated with Cura_SteamEngine 5.6.0
M82 ;absolute extrusion mode
M140 S0
M104 S195.0 T0
M104 S0 T1
M107
G90
G28
M132 X Y Z A B
G1 Z50.00 F400
G161 X Y F3300
M6 T0
M907 X100 Y100 Z40 A80 B20
M108 T0
G1 Z.20 F400
G92 E0
G92 E0
G1 F1800 E-1.3
;LAYER_COUNT:83
;LAYER:0
M106 S255
G0 F3000 X14 Y9.314 Z0.2"""

class TestGX(unittest.TestCase):

def test_from_gcode(self):
gx = GX.from_gcode(test_gcode)
result = gx.encode().decode('latin1')
print("Resulting gcode: ", result)
self.assertFalse(' S195.0 ' in result)
self.assertTrue(' S195 ' in result)
self.assertTrue('xgcode' in result)

if __name__ == '__main__':
unittest.main()

0 comments on commit 69a8ec5

Please sign in to comment.