Rounding errors, but produces usable gcode files
This commit is contained in:
parent
6c86742582
commit
5358841b07
7 changed files with 79 additions and 37 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
*.gcode
|
||||
gcodeprocessor
|
||||
gcode_processor
|
||||
|
|
3
Makefile
3
Makefile
|
@ -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:
|
||||
|
|
|
@ -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
50
src/generator.nim
Normal 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
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
import std/lists
|
||||
import types
|
||||
|
||||
func injectFeatureAccel*(oldState, newState: GcodeState): GcodeState =
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -67,7 +67,9 @@ type
|
|||
posX: float64
|
||||
posY: float64
|
||||
posZ: float64
|
||||
speed: float64
|
||||
comment: string
|
||||
parsedComment: string
|
||||
postInject: string
|
||||
klipperAccels: KlipperAccels
|
||||
extruderTemp: float
|
||||
|
|
Loading…
Add table
Reference in a new issue