Rounding errors, but produces usable gcode files

This commit is contained in:
Kyle Brown 2022-07-27 22:13:36 -07:00
parent 6c86742582
commit 5358841b07
7 changed files with 79 additions and 37 deletions

2
.gitignore vendored
View file

@ -1,2 +1,2 @@
*.gcode
gcodeprocessor
gcode_processor

View file

@ -32,7 +32,8 @@ debug:
.PHONY: clean
clean:
rm -f ./${BIN}
rm -rf ./${SRCDIR}/htmldocs
rm -rf ./${SRCDIR}/htmldocs/
rm -f ./testOut.gcode
.PHONY: run
run:

View file

@ -6,6 +6,7 @@ import docopt
import types
import parsing
import injection
import generator
let doc = """
pmm - Emulating Gentoo's world files and sets for other package managers.
@ -31,30 +32,4 @@ when isMainModule:
# get data from file
let allGcode = openAndParse(gcodeFile)
var newGcode: DoublyLinkedList[GcodeState]
# Keeps track of accel injections. Only done once per feature
var featureAccelInjectDone: bool
var oldState: GcodeState
# Do some processing
for i in allGcode:
# Init vars for state changes
var newState = i
if i.comment.isEmptyOrWhitespace and i.moveType == extrude:
newState = injectFeatureAccel(oldState, i)
# Set the old state to allow for comparison in the new loop
oldState = newState
newGcode.add(newState)
# if i.comment.isEmptyOrWhitespace: newState.echo
# var oldCheck: GcodeState
# for i in newGcode:
# if i.comment.isEmptyOrWhitespace and i != oldCheck:
# i.debugecho
# "\n".debugEcho
# elif i == oldCheck: "lolololol".debugEcho
# oldCheck = i
let bla = openAndWrite("testOut.gcode", allGcode)

50
src/generator.nim Normal file
View file

@ -0,0 +1,50 @@
import std/math
import std/lists
import std/strutils
import std/strformat
import types
proc openAndWrite*(fileName: string, gcodeStates: DoublyLinkedList[
GcodeState]): bool =
## Writes a file from the state stored in gcode
let f = open(fileName, fmWrite)
defer: f.close()
# Initialize something to check the state against between iterations
var old: GcodeState
for line in gcodeStates:
if not line.comment.isEmptyOrWhitespace:
# Comments have the highest priority going out as they have the lowest priority
# going in. This means it must only contain information that was not processable
# and therefor should be written back raw.
f.writeLine(line.comment)
if not line.parsedComment.isEmptyOrWhitespace:
# Even parsed comments should be added back for other tools to read
f.writeLine(line.parsedComment)
elif line.posX != old.posX or line.posY != old.posY or line.posZ != old.posZ or line.speed != old.speed:
# Motion is required
var moveX: string
var moveY: string
if line.posX != old.posX or line.posY != old.posY:
# Motion on X/Y has happened. Set both
moveX = if line.posX != old.posX: fmt" X{line.posX.round(5)}" else: fmt" X{old.posX.round(5)}"
moveY = if line.posY != old.posY: fmt" Y{line.posY.round(5)}" else: fmt" Y{old.posY.round(5)}"
let moveZ = if line.posZ != old.posZ: fmt" Z{line.posZ}" else: ""
# Set move speed if it's not 0
var speedStr: string
if line.speed != 0.0:
# Round to whole number if possible
let speed = if line.speed == line.speed.round: $line.speed.int else: $line.speed.round(5)
if line.moveType == MoveType.travel or line.moveType == MoveType.layerChange:
speedStr = fmt" F{speed}"
else: speedStr = fmt" E{speed}"
f.writeLine(fmt"G1{moveX}{moveY}{moveZ}{speedStr}")
elif line.comment.isEmptyOrWhitespace: f.writeLine(line.comment)
else:
discard
old = line
return true

View file

@ -1,5 +1,3 @@
import std/lists
import types
func injectFeatureAccel*(oldState, newState: GcodeState): GcodeState =

View file

@ -2,6 +2,7 @@ import std/lists
import std/sequtils
import std/strformat
import std/strutils
import std/math
import convenience
import types
@ -20,25 +21,27 @@ func moveCheck*(line: string): MoveType =
elif travelCheck[^1].startsWith("E"):
return MoveType.extrude
func setPosition*(x, y, z: float64, line: string): tuple[x, y, z: float64] =
func setPosition*(x, y, z: float64, line: string): tuple[x, y, z, speed:float64] =
## Sets the position. Takes X, Y, and/or Z in a gcode line and will
## assume that they haven't changed if they aren't specified.
var
newX: float64
newY: float64
newZ: float64
newSpeed: float64
for i in line.split:
let trimmed = i[1 .. ^1] # The potential float minus the letter
if i.contains "X": newX = trimmed.parseFloat
elif i.contains "Y": newY = trimmed.parseFloat
elif i.contains "Z": newZ = trimmed.parseFloat
if i.contains "X": newX = trimmed.parseFloat.round(5)
if i.contains "Y": newY = trimmed.parseFloat.round(5)
if i.contains "Z": newZ = trimmed.parseFloat.round(5)
if i.contains("F") or i.contains("E"): newSpeed = trimmed.parseFloat.round(5)
if newX == 0.0: newX = x
if newY == 0.0: newY = y
if newZ == 0.0: newZ = z
return (newX, newY, newZ)
return (newX, newY, newZ, newSpeed)
func accelFormat*(line: string): string =
## Transforms comment line like 'ACCEL: 8000/8000/8 for Travel'
@ -101,6 +104,8 @@ func parseKlipperAccel*(line: string, oldAccels: KlipperAccels): KlipperAccels =
newAccels.supportMaterialInterface = line.accelFormat
elif "TYPE:Support material" in line:
newAccels.supportMaterial = line.accelFormat
elif "TYPE:Custom" in line:
newAccels.custom = line.accelFormat
return newAccels
func parseTemp*(line: string): float =
@ -145,7 +150,9 @@ proc openAndParse*(fileName: string): DoublyLinkedList[GcodeState] =
posX: 0.0,
posY: 0.0,
posZ: 0.0,
speed: 0.0,
comment: "",
parsedComment: "",
postInject: "",
klipperAccels: accels,
extruderTemp: 0.0,
@ -157,33 +164,41 @@ proc openAndParse*(fileName: string): DoublyLinkedList[GcodeState] =
for line in gcodeFile:
state.comment = "" # Reset comment
state.parsedComment = "" # Reset parsed comment
state.preInject = "" # reset injections
state.postInject = "" # reset injections
if line.isFeature:
state.feature = line.stripFeature
state.parsedComment = line
elif line.islayerChange:
state.layer.inc
state.parsedComment = line
elif line.split[0] in [$BaseGcode.move, $BaseGcode.moveAlt]:
state.moveType = line.moveCheck
(state.posX, state.posY, state.posZ) = setPosition(state.posX,
(state.posX, state.posY, state.posZ, state.speed) = setPosition(state.posX,
state.posY, state.posZ, line)
elif line.split[0] == $BaseGcode.absolute:
state.moveMode = BaseGcode.absolute
state.parsedComment = line # TODO remove
elif line.split[0] == $BaseGcode.relative:
state.moveMode = BaseGcode.relative
state.parsedComment = line # TODO remove
elif line.startsWith("; ACCEL"):
state.parsedComment = line
state.klipperAccels = parseKlipperAccel(line, state.klipperAccels)
elif line.split[0] == $BaseGcode.extruderTemp:
state.extruderTemp = line.parseTemp
state.parsedComment = line # TODO remove
elif line.split[0] == $BaseGcode.bedTemp:
state.bedTemp = line.parseTemp
state.parsedComment = line # TODO remove
elif line.isComment or line.isEmptyOrWhitespace:
# If comments aren't parsed for info, they are just stored in the line state.
@ -210,6 +225,7 @@ proc openAndParse*(fileName: string): DoublyLinkedList[GcodeState] =
return allGcode
except:
echo getCurrentExceptionMsg()
fmt"Could not read {fileName} file.".echo
quit(QuitFailure)

View file

@ -67,7 +67,9 @@ type
posX: float64
posY: float64
posZ: float64
speed: float64
comment: string
parsedComment: string
postInject: string
klipperAccels: KlipperAccels
extruderTemp: float