public override PrinterMachineInstruction Instruction(int index) { lock (locker) { if (index < readLineCount - MaxLinesToBuffer) { throw new Exception("You are asking for a line we no longer have buffered"); } while (index >= readLineCount) { string line = openGcodeStream.ReadLine(); if (line == null) { readLastLineOfFile = true; line = ""; } int ringBufferIndex = readLineCount % MaxLinesToBuffer; readLinesRingBuffer[ringBufferIndex] = new PrinterMachineInstruction(line); string lineToParse = line.ToUpper().Trim(); if (lineToParse.StartsWith("G0") || lineToParse.StartsWith("G1")) { double newFeedRateMmPerMin = 0; if (GetFirstNumberAfter("F", lineToParse, ref newFeedRateMmPerMin)) { feedRateMmPerMin = newFeedRateMmPerMin; } Vector3 attemptedDestination = lastPrinterPosition; GetFirstNumberAfter("X", lineToParse, ref attemptedDestination.X); GetFirstNumberAfter("Y", lineToParse, ref attemptedDestination.Y); GetFirstNumberAfter("Z", lineToParse, ref attemptedDestination.Z); double ePosition = lastEPosition; GetFirstNumberAfter("E", lineToParse, ref ePosition); lastPrinterPosition = attemptedDestination; lastEPosition = ePosition; } else if (lineToParse.StartsWith("G92")) { double ePosition = 0; if (GetFirstNumberAfter("E", lineToParse, ref ePosition)) { lastEPosition = ePosition; } } readLineCount++; } } return(readLinesRingBuffer[index % MaxLinesToBuffer]); }
public PrinterMachineInstruction(string Line, PrinterMachineInstruction copy, bool clientInsertion = false) : this(Line) { xyzPosition = copy.xyzPosition; FeedRate = copy.FeedRate; EPosition = copy.EPosition; MovementType = copy.MovementType; SecondsToEndFromHere = copy.SecondsToEndFromHere; ToolIndex = copy.ToolIndex; }
public PrinterMachineInstruction(string Line, PrinterMachineInstruction copy, bool clientInsertion = false) : this(Line) { xyzPosition = copy.xyzPosition; feedRate = copy.feedRate; ePosition = copy.ePosition; movementType = copy.movementType; secondsToEndFromHere = copy.secondsToEndFromHere; ExtruderIndex = copy.ExtruderIndex; this.clientInsertion = clientInsertion; }
public void Insert(int insertIndex, PrinterMachineInstruction printerMachineInstruction) { for (int i = 0; i < IndexOfLayerStart.Count; i++) { if (insertIndex < IndexOfLayerStart[i]) { IndexOfLayerStart[i]++; } } GCodeCommandQueue.Insert(insertIndex, printerMachineInstruction); }
public override double GetFilamentUsedMm(double filamentDiameter) { if (filamentUsedMmCache == 0 || filamentDiameter != diameterOfFilamentUsedMmCache) { double lastEPosition = 0; double filamentMm = 0; for (int i = 0; i < gCodeCommandQueue.Count; i++) { PrinterMachineInstruction instruction = gCodeCommandQueue[i]; // filamentMm += instruction.EPosition; string lineToParse = instruction.Line; if (lineToParse.StartsWith("G0") || lineToParse.StartsWith("G1")) { double ePosition = lastEPosition; if (GetFirstNumberAfter("E", lineToParse, ref ePosition)) { if (instruction.XyzeMovementType == PrinterMachineInstruction.MovementTypes.Relative || instruction.ExtuderRelativeOverride) { filamentMm += ePosition; } else { double deltaEPosition = ePosition - lastEPosition; filamentMm += deltaEPosition; } lastEPosition = ePosition; } } else if (lineToParse.StartsWith("G92")) { double ePosition = 0; if (GetFirstNumberAfter("E", lineToParse, ref ePosition)) { lastEPosition = ePosition; } } } filamentUsedMmCache = filamentMm; diameterOfFilamentUsedMmCache = filamentDiameter; } return(filamentUsedMmCache); }
public void Add(PrinterMachineInstruction printerMachineInstruction) { Insert(LineCount, printerMachineInstruction); }
private void ParseGLine(string lineString, PrinterMachineInstruction processingMachineState) { // take off any comments before we check its length int commentIndex = lineString.IndexOf(';'); if (commentIndex != -1) { lineString = lineString.Substring(0, commentIndex); } string[] splitOnSpace = lineString.Split(' '); string onlyNumber = splitOnSpace[0].Substring(1).Trim(); switch (onlyNumber) { case "0": goto case "1"; case "4": case "04": // wait a given number of milliseconds break; case "1": // get the x y z to move to { double ePosition = processingMachineState.EPosition; var position = processingMachineState.Position; if (processingMachineState.MovementType == PrinterMachineInstruction.MovementTypes.Relative) { position = Vector3.Zero; ePosition = 0; } GCodeFile.GetFirstNumberAfter("X", lineString, ref position.X); GCodeFile.GetFirstNumberAfter("Y", lineString, ref position.Y); GCodeFile.GetFirstNumberAfter("Z", lineString, ref position.Z); GCodeFile.GetFirstNumberAfter("E", lineString, ref ePosition); double feedrate = 0; if (GCodeFile.GetFirstNumberAfter("F", lineString, ref feedrate)) { processingMachineState.FeedRate = (float)feedrate; } if (processingMachineState.MovementType == PrinterMachineInstruction.MovementTypes.Absolute) { processingMachineState.Position = position; processingMachineState.EPosition = (float)ePosition; } else { processingMachineState.Position += position; processingMachineState.EPosition += (float)ePosition; } } if (!gcodeHasExplicitLayerChangeInfo) { if (processingMachineState.Z != parsingLastZ || IndexOfLayerStart.Count == 0) { // if we changed z or there is a movement and we have never started a layer index IndexOfLayerStart.Add(GCodeCommandQueue.Count); } } parsingLastZ = processingMachineState.Position.Z; break; case "10": // firmware retract break; case "11": // firmware unretract break; case "21": // set to metric break; case "28": // G28 Return to home position (machine zero, aka machine reference point) break; case "29": // G29 Probe the z-bed in 3 places break; case "30": // G30 Probe z in current position break; case "90": // G90 is Absolute Distance Mode processingMachineState.MovementType = PrinterMachineInstruction.MovementTypes.Absolute; break; case "91": // G91 is Incremental Distance Mode processingMachineState.MovementType = PrinterMachineInstruction.MovementTypes.Relative; break; case "92": { // set current head position values (used to reset origin) double value = 0; if (GCodeFile.GetFirstNumberAfter("X", lineString, ref value)) { processingMachineState.PositionSet |= PositionSet.X; processingMachineState.X = value; } if (GCodeFile.GetFirstNumberAfter("Y", lineString, ref value)) { processingMachineState.PositionSet |= PositionSet.Y; processingMachineState.Y = value; } if (GCodeFile.GetFirstNumberAfter("Z", lineString, ref value)) { processingMachineState.PositionSet |= PositionSet.Z; processingMachineState.Z = value; } if (GCodeFile.GetFirstNumberAfter("E", lineString, ref value)) { processingMachineState.PositionSet |= PositionSet.E; processingMachineState.EPosition = (float)value; } } break; case "130": //Set Digital Potentiometer value break; case "161": // home x,y axis minimum break; case "162": // home z axis maximum break; default: break; } }
private void ParseMLine(string lineString, PrinterMachineInstruction processingMachineState) { // take off any comments before we check its length int commentIndex = lineString.IndexOf(';'); if (commentIndex != -1) { lineString = lineString.Substring(0, commentIndex); } string[] splitOnSpace = lineString.Split(' '); switch (splitOnSpace[0].Substring(1).Trim()) { case "01": // show a message? break; case "6": // wait for tool to heat up (wait for condition?) break; case "101": // extrude on, forward break; case "18": // turn off steppers break; case "42": // Stop on material exhausted / Switch I/O pin break; case "72": // makerbot, Play tone or song break; case "73": // makerbot, Manually set build percentage break; case "82": // set extruder to absolute mode break; case "83": //Set extruder to relative mode break; case "84": // lineString = "M84 ; disable motors\r" break; case "92": // set steps per mm break; case "102": // extrude on reverse break; case "103": // extrude off break; case "104": // set extruder temperature break; case "105": // M105 Custom code for temperature reading. (Not used) break; case "106": // turn fan on break; case "107": // turn fan off break; case "108": // set extruder speed break; case "109": // set heated platform temperature break; case "114": break; case "117": // in Marlin: Display Message break; case "126": // enable fan (makerbot) break; case "127": // disable fan (makerbot) break; case "132": // recall stored home offsets for axis xyzab break; case "133": // MakerBot wait for toolhead to heat break; case "134": // MakerBot wait for platform to reach target temp break; case "135": // MakerBot change toolhead break; case "140": // set bed temperature break; case "190": // wait for bed temperature to be reached break; case "200": // M200 sets the filament diameter. break; case "201": // set axis acceleration break; case "204": // - Set default acceleration break; case "207": // M207: calibrate z axis by detecting z max length break; case "208": // M208: set axis max travel break; case "209": // M209: enable automatic retract break; case "210": // Set homing rate break; case "226": // user request pause break; case "227": // Enable Automatic Reverse and Prime break; case "301": break; case "400": // Wait for current moves to finish break; case "565": // M565: Set Z probe offset break; case "1200": //M1200 Makerbot Fake gCode command for start build notification break; case "1201": //M1201 Makerbot Fake gCode command for end build notification break; case "1202": //M1202 Makerbot Fake gCode command for reset board break; default: break; } }
private void AnalyzeGCodeLines(CancellationToken cancellationToken, Action <double, string> progressReporter, Vector4 maxAccelerationMmPerS2, Vector4 maxVelocityMmPerS, Vector4 velocitySameAsStopMmPerS, Vector4 speedMultiplier) { double feedRateMmPerMin = 0; Vector3 lastPrinterPosition = new Vector3(); double lastEPosition = 0; Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); for (int lineIndex = 0; lineIndex < GCodeCommandQueue.Count; lineIndex++) { PrinterMachineInstruction instruction = GCodeCommandQueue[lineIndex]; string line = instruction.Line; Vector3 deltaPositionThisLine = new Vector3(); double deltaEPositionThisLine = 0; string lineToParse = line.ToUpper().Trim(); if (lineToParse.StartsWith("G0") || lineToParse.StartsWith("G1")) { double newFeedRateMmPerMin = 0; if (GetFirstNumberAfter("F", lineToParse, ref newFeedRateMmPerMin)) { feedRateMmPerMin = newFeedRateMmPerMin; } Vector3 attemptedDestination = lastPrinterPosition; GetFirstNumberAfter("X", lineToParse, ref attemptedDestination.X); GetFirstNumberAfter("Y", lineToParse, ref attemptedDestination.Y); GetFirstNumberAfter("Z", lineToParse, ref attemptedDestination.Z); double ePosition = lastEPosition; GetFirstNumberAfter("E", lineToParse, ref ePosition); deltaPositionThisLine = attemptedDestination - lastPrinterPosition; deltaEPositionThisLine = Math.Abs(ePosition - lastEPosition); lastPrinterPosition = attemptedDestination; lastEPosition = ePosition; } else if (lineToParse.StartsWith("G92")) { double ePosition = 0; if (GetFirstNumberAfter("E", lineToParse, ref ePosition)) { lastEPosition = ePosition; } } if (feedRateMmPerMin > 0) { var timeForE = Estimator.GetSecondsForMovement(deltaEPositionThisLine, feedRateMmPerMin / 60.0, maxAccelerationMmPerS2[3], maxVelocityMmPerS[3], velocitySameAsStopMmPerS[3], speedMultiplier[3]); var timeForPosition = Estimator.GetSecondsForMovement(deltaPositionThisLine, feedRateMmPerMin / 60.0, new Vector3(maxAccelerationMmPerS2), new Vector3(maxVelocityMmPerS), new Vector3(velocitySameAsStopMmPerS), new Vector3(speedMultiplier)); instruction.SecondsThisLine = (float)Math.Max(timeForE, timeForPosition); } if (progressReporter != null && maxProgressReport.ElapsedMilliseconds > 200) { progressReporter(((double)lineIndex / GCodeCommandQueue.Count / 2) + .5, ""); if (cancellationToken.IsCancellationRequested) { return; } maxProgressReport.Restart(); } } double accumulatedTime = 0; for (int i = GCodeCommandQueue.Count - 1; i >= 0; i--) { PrinterMachineInstruction line = GCodeCommandQueue[i]; accumulatedTime += line.SecondsThisLine; line.SecondsToEndFromHere = (float)accumulatedTime; } }
private static GCodeMemoryFile ParseFileContents(string gCodeString, Vector4 maxAccelerationMmPerS2, Vector4 maxVelocityMmPerS, Vector4 velocitySameAsStopMmPerS, Vector4 speedMultiplier, CancellationToken cancellationToken, Action <double, string> progressReporter) { if (gCodeString == null) { return(null); } Stopwatch loadTime = Stopwatch.StartNew(); Stopwatch maxProgressReport = new Stopwatch(); maxProgressReport.Start(); PrinterMachineInstruction machineInstructionForLine = new PrinterMachineInstruction("None"); bool gcodeHasExplicitLayerChangeInfo = false; if (gCodeString.Contains("LAYER:") || gCodeString.Contains("; layer")) { gcodeHasExplicitLayerChangeInfo = true; } PrinterMachineInstruction previousInstruction = null; var speeds = new HashSet <float>(); GCodeMemoryFile loadedGCodeFile = new GCodeMemoryFile(gcodeHasExplicitLayerChangeInfo); // Add the first start index (of 0) loadedGCodeFile.IndexOfLayerStart.Add(0); int crCount = CountNumLines(gCodeString); int lineIndex = 0; foreach (string outputString in CustomSplit(gCodeString, '\n')) { string lineString = outputString.Trim(); machineInstructionForLine = new PrinterMachineInstruction(lineString, machineInstructionForLine, false); if (lineString.Length > 0) { switch (lineString[0]) { case 'G': loadedGCodeFile.ParseGLine(lineString, machineInstructionForLine); break; case 'M': loadedGCodeFile.ParseMLine(lineString, machineInstructionForLine); break; case 'T': double extruderIndex = 0; if (GetFirstNumberAfter("T", lineString, ref extruderIndex)) { machineInstructionForLine.ExtruderIndex = (int)extruderIndex; } break; case ';': if (gcodeHasExplicitLayerChangeInfo && IsLayerChange(lineString)) { // The first "layer" statement in the gcode file is after the start gcode and we ignore // it because we already added a marker for the start of the file (before start gcode) if (!loadedGCodeFile.foundFirstLayerMarker) { loadedGCodeFile.foundFirstLayerMarker = true; } else { loadedGCodeFile.IndexOfLayerStart.Add(loadedGCodeFile.GCodeCommandQueue.Count); } } else if (lineString.StartsWith("; LAYER_HEIGHT:")) { double layerWidth = 0; if (GetFirstNumberAfter("LAYER_HEIGHT:", lineString, ref layerWidth, 0, "")) { loadedGCodeFile.layerHeights.Add(layerWidth); } } break; case '@': break; default: #if DEBUG throw new NotImplementedException(); #else break; #endif } } loadedGCodeFile.GCodeCommandQueue.Add(machineInstructionForLine); // Accumulate speeds for extruded moves if (previousInstruction != null && machineInstructionForLine.EPosition > previousInstruction.EPosition && (machineInstructionForLine.Line.IndexOf('X') != -1 || machineInstructionForLine.Line.IndexOf('Y') != -1)) { speeds.Add((float)machineInstructionForLine.FeedRate); } if (progressReporter != null && maxProgressReport.ElapsedMilliseconds > 200) { progressReporter((double)lineIndex / crCount / 2, ""); if (cancellationToken.IsCancellationRequested) { return(null); } maxProgressReport.Restart(); } previousInstruction = machineInstructionForLine; lineIndex++; } loadedGCodeFile.AnalyzeGCodeLines(cancellationToken, progressReporter, maxAccelerationMmPerS2, maxVelocityMmPerS, velocitySameAsStopMmPerS, speedMultiplier); loadedGCodeFile.Speeds = speeds; loadTime.Stop(); Console.WriteLine("Time To Load Seconds: {0:0.00}".FormatWith(loadTime.Elapsed.TotalSeconds)); return(loadedGCodeFile); }