public override string ReadLine() { var baseLine = base.ReadLine(); if (baseLine == null) { return(null); } if (baseLine.EndsWith("; NO_PROCESSING")) { return(baseLine); } // if we are not printing or the line has no content don't process it if (baseLine.Length == 0 || baseLine.Trim().Length == 0) { return(baseLine); } var lines = ProcessGCodeLine(baseLine, printer); for (int i = lines.Count - 1; i >= 1; i--) { queueStream.Add(lines[i], true); } var lineToSend = lines[0]; return(lineToSend); }
public override string ReadLine() { var baseLine = base.ReadLine(); if (baseLine == null) { return(null); } if (baseLine.EndsWith("; NO_PROCESSING")) { return(baseLine); } // if the line has no content don't process it if (baseLine.Length == 0 || baseLine.Trim().Length == 0) { return(baseLine); } var lines = ProcessWriteRegEx(baseLine, printer); for (int i = lines.Count - 1; i >= 1; i--) { queueStream.Add(lines[i], true); } var lineToSend = lines[0]; if (lineToSend != null && LineIsMovement(lineToSend)) { currentMove = GetPosition(lineToSend, currentMove); } // is it a position set? if (lineToSend.StartsWith("G92")) { GCodeFile.GetFirstNumberAfter("X", lineToSend, ref this.currentMove.position.X); GCodeFile.GetFirstNumberAfter("Y", lineToSend, ref this.currentMove.position.Y); GCodeFile.GetFirstNumberAfter("Z", lineToSend, ref this.currentMove.position.Z); GCodeFile.GetFirstNumberAfter("E", lineToSend, ref this.currentMove.extrusion); // tell the stream pipeline what the actual printer position is this.SetPrinterPosition(this.currentMove); } return(lineToSend); }
public override string ReadLine() { // Send any commands that are queue before moving on to the internal stream. string nextCommand = queuedCommands.ReadLine(); if (nextCommand != null) { return(nextCommand); } switch (RecoveryState) { // heat the extrude to remove it from the part case RecoveryState.RemoveHeating: // TODO: make sure we heat up all the extruders that we need to (all that are used) queuedCommands.Add("G21; set units to millimeters"); queuedCommands.Add("M107; fan off"); queuedCommands.Add("T0; set the active extruder to 0"); queuedCommands.Add("G90; use absolute coordinates"); queuedCommands.Add("G92 E0; reset the expected extruder position"); queuedCommands.Add("M82; use absolute distance for extrusion"); bool hasHeatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed); double bedTemp = printer.Settings.GetValue <double>(SettingsKey.bed_temperature); if (hasHeatedBed && bedTemp > 0) { // start heating the bed queuedCommands.Add($"M140 S{bedTemp}"); } // heat up the extruder queuedCommands.Add("M109 S{0}".FormatWith(printer.Settings.Helpers.ExtruderTemperature(0))); if (hasHeatedBed && bedTemp > 0) { // finish heating the bed queuedCommands.Add($"M190 S{bedTemp}"); } RecoveryState = RecoveryState.Raising; return(""); // remove it from the part case RecoveryState.Raising: // We don't know where the printer is for sure (it make have been turned off). Disable leveling until we know where it is. PrintLevelingStream.AllowLeveling = false; queuedCommands.Add("M114 ; get current position"); queuedCommands.Add("G91 ; move relative"); queuedCommands.Add("G1 Z10 F{0}".FormatWith(printer.Settings.ZSpeed())); queuedCommands.Add("G90 ; move absolute"); RecoveryState = RecoveryState.Homing; return(""); // if top homing, home the extruder case RecoveryState.Homing: if (printer.Settings.GetValue <bool>(SettingsKey.z_homes_to_max)) { queuedCommands.Add("G28"); } else { // home x queuedCommands.Add("G28 X0"); // home y queuedCommands.Add("G28 Y0"); // move to the place we can home z from Vector2 recoveryPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home); queuedCommands.Add("G1 X{0:0.###}Y{1:0.###}F{2}".FormatWith(recoveryPositionXy.X, recoveryPositionXy.Y, printer.Settings.XSpeed())); // home z queuedCommands.Add("G28 Z0"); } // We now know where the printer is re-enable print leveling PrintLevelingStream.AllowLeveling = true; RecoveryState = RecoveryState.FindingRecoveryLayer; return(""); // This is to recover printing if an out a filament occurs. // Help the user move the extruder down to just touching the part case RecoveryState.FindingRecoveryLayer: if (false) // help the user get the head to the right position { // move to above the completed print // move over a know good part of the model at the current top layer (extrude vertex from gcode) // let the user move down until they like the height // calculate that position and continue } else // we are resuming because of disconnect or reset, skip this { RecoveryState = RecoveryState.SkippingGCode; goto case RecoveryState.SkippingGCode; } case RecoveryState.SkippingGCode: // run through the gcode that the device expected looking for things like temp // and skip everything else until we get to the point we left off last time int commandCount = 0; boundsOfSkippedLayers = RectangleDouble.ZeroIntersection; while (internalStream.GCodeFile.PercentComplete(internalStream.LineIndex) < percentDone) { string line = internalStream.ReadLine(); if (line == null) { break; } commandCount++; // make sure we don't parse comments if (line.Contains(";")) { line = line.Split(';')[0]; } lastDestination = GetPosition(line, lastDestination); if (commandCount > 100) { boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy); } // check if the line is something we want to send to the printer (like a temp) if (line.StartsWith("M109") || // heat and wait extruder line.StartsWith("M104") || // heat extruder line.StartsWith("M190") || // heat and wait bed line.StartsWith("M140") || // heat bed line.StartsWith("T") || // switch extruder line.StartsWith("M106") || // fan on line.StartsWith("M107") || // fan off line.StartsWith("G92")) // set position { return(line); } } RecoveryState = RecoveryState.PrimingAndMovingToStart; // make sure we always- pick up the last movement boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy); return(""); case RecoveryState.PrimingAndMovingToStart: { if (printer.Settings.GetValue("z_homes_to_max") == "0") // we are homed to the bed { // move to the height we can recover printing from Vector2 recoverPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home); queuedCommands.Add(CreateMovementLine(new PrinterMove(new VectorMath.Vector3(recoverPositionXy.X, recoverPositionXy.Y, lastDestination.position.Z), 0, printer.Settings.ZSpeed()))); } double extruderWidth = printer.Settings.GetValue <double>(SettingsKey.nozzle_diameter); // move to a position outside the printed bounds queuedCommands.Add(CreateMovementLine(new PrinterMove( new Vector3(boundsOfSkippedLayers.Left - extruderWidth * 2, boundsOfSkippedLayers.Bottom + boundsOfSkippedLayers.Height / 2, lastDestination.position.Z), 0, printer.Settings.XSpeed()))); // let's prime the extruder queuedCommands.Add("G1 E10 F{0}".FormatWith(printer.Settings.EFeedRate(0))); // extrude 10 queuedCommands.Add("G1 E9"); // and retract a bit // move to the actual print position queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position, 0, printer.Settings.XSpeed()))); /// reset the printer to know where the filament should be queuedCommands.Add("G92 E{0}".FormatWith(lastDestination.extrusion)); RecoveryState = RecoveryState.PrintingSlow; } return(""); case RecoveryState.PrintingSlow: { string lineToSend = internalStream.ReadLine(); if (lineToSend == null) { return(null); } if (!GCodeFile.IsLayerChange(lineToSend)) { // have not seen the end of this layer so keep printing slow if (LineIsMovement(lineToSend)) { PrinterMove currentMove = GetPosition(lineToSend, lastDestination); PrinterMove moveToSend = currentMove; moveToSend.feedRate = recoverFeedRate; lineToSend = CreateMovementLine(moveToSend, lastDestination); lastDestination = currentMove; return(lineToSend); } return(lineToSend); } } // we only fall through to here after seeing the next "; Layer:" RecoveryState = RecoveryState.PrintingToEnd; return(""); case RecoveryState.PrintingToEnd: return(internalStream.ReadLine()); } return(null); }
private void QueueAfterGCode() { string afterGcodeToQueue = ""; switch (RequestedTool) { case 0: afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode).Replace("\\n", "\n"); break; case 1: afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode_1).Replace("\\n", "\n"); break; case 2: afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode_2).Replace("\\n", "\n"); break; case 3: afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode_3).Replace("\\n", "\n"); break; } PrinterMove newToolMove = GetPosition(postSwitchLine, PrinterMove.Unknown); var newToolPosition = newToolMove.position; var lineNoComment = postSwitchLine.Split(';')[0]; // if there is no extrusion we can move directly to the desired position after the extruder switch. // Otherwise we need to go to the last position to start the extrusion. if (!lineNoComment.Contains("E")) { newToolPosition.X = newToolPosition.X == double.PositiveInfinity ? preSwitchPosition.X : newToolPosition.X; newToolPosition.Y = newToolPosition.Y == double.PositiveInfinity ? preSwitchPosition.Y : newToolPosition.Y; } // no matter what happens with the x and y we want to set our z if we have one before newToolPosition.Z = newToolPosition.Z == double.PositiveInfinity ? preSwitchPosition.Z : newToolPosition.Z; // put together the output we want to send var gcode = new StringBuilder(); // If the printer is heating, make sure we are at temp before switching extruders var nextToolTargetTemp = targetTemps[RequestedTool]; var currentPrinterTargeTemp = printer.Connection.GetTargetHotendTemperature(RequestedTool); if (currentPrinterTargeTemp > 0 && printer.Connection.GetActualHotendTemperature(RequestedTool) < nextToolTargetTemp - 3) { // ensure our next tool is at temp (the one we are switching to) gcode.AppendLine($"M109 T{RequestedTool} S{nextToolTargetTemp}"); } if (afterGcodeToQueue.Trim().Length > 0) { gcode.Append(printer.Settings.ReplaceMacroValues(afterGcodeToQueue)); } // move to selected tool to the last tool position at the travel speed if (newToolPosition.X != double.PositiveInfinity && newToolPosition.Y != double.PositiveInfinity) { gcode.AppendLine($"\n G1 X{newToolPosition.X}Y{newToolPosition.Y}F{printer.Settings.XSpeed()}"); } // move to the z position if (newToolPosition.Z != double.PositiveInfinity) { gcode.AppendLine($"G1 Z{newToolPosition.Z}F{printer.Settings.ZSpeed()}"); } // set the feedrate back to what was before we added any code if (preSwitchFeedRate != double.PositiveInfinity) { gcode.AppendLine($"G1 F{preSwitchFeedRate}"); } // and queue the travel gcode.AppendLine(postSwitchLine); queuedCommandsStream.Add(gcode.ToString()); }
public override string ReadLine() { string nextCommand = queuedCommands.ReadLine(); if (nextCommand != null) { return(nextCommand); } switch (resumeState) { // heat the extrude to remove it from the part case ResumeState.RemoveHeating: // TODO: make sure we heat up all the extruders that we need to (all that are used) queuedCommands.Add("G21; set units to millimeters"); queuedCommands.Add("M107; fan off"); queuedCommands.Add("T0; set the active extruder to 0"); queuedCommands.Add("G90; use absolute coordinates"); queuedCommands.Add("G92 E0; reset the expected extruder position"); queuedCommands.Add("M82; use absolute distance for extrusion"); queuedCommands.Add("M109 S{0}".FormatWith(ActiveSliceSettings.Instance.ExtruderTemperature(0))); resumeState = ResumeState.Raising; return(""); // remove it from the part case ResumeState.Raising: queuedCommands.Add("M114 ; get current position"); queuedCommands.Add("G91 ; move relative"); queuedCommands.Add("G1 Z10 F{0}".FormatWith(MovementControls.ZSpeed)); queuedCommands.Add("G90 ; move absolute"); resumeState = ResumeState.Homing; return(""); // if top homing, home the extruder case ResumeState.Homing: if (ActiveSliceSettings.Instance.ActiveValue("z_homes_to_max") == "1") { queuedCommands.Add("G28"); } else { // home x queuedCommands.Add("G28 X0"); // home y queuedCommands.Add("G28 Y0"); // move to the place we can home z from Vector2 resumePositionXy = ActiveSliceSettings.Instance.ActiveVector2("resume_position_before_z_home"); queuedCommands.Add("G1 X{0:0.000}Y{1:0.000}F{2}".FormatWith(resumePositionXy.x, resumePositionXy.y, MovementControls.XSpeed)); // home z queuedCommands.Add("G28 Z0"); } resumeState = ResumeState.FindingResumeLayer; return(""); // This is to resume printing if an out a filament occurs. // Help the user move the extruder down to just touching the part case ResumeState.FindingResumeLayer: if (false) // help the user get the head to the right position { // move to above the completed print // move over a know good part of the model at the current top layer (extrude vertex from gcode) // let the user move down until they like the height // calculate that position and continue } else // we are resuming because of disconnect or reset, skip this { resumeState = ResumeState.SkippingGCode; goto case ResumeState.SkippingGCode; } case ResumeState.SkippingGCode: // run through the gcode that the device expected looking for things like temp // and skip everything else until we get to the point we left off last time while (internalStream.FileStreaming.PercentComplete(internalStream.LineIndex) < percentDone) { string line = internalStream.ReadLine(); lastDestination = GetPosition(line, lastDestination); // check if the line is something we want to send to the printer (like a temp) if (line.StartsWith("M109") || line.StartsWith("M104") || line.StartsWith("T") || line.StartsWith("M106") || line.StartsWith("M107")) { return(line); } } resumeState = ResumeState.PrimingAndMovingToStart; return(""); case ResumeState.PrimingAndMovingToStart: { // let's prime the extruder, move to a good position over the part, then start printing queuedCommands.Add("G1 E5"); queuedCommands.Add("G1 E4"); if (ActiveSliceSettings.Instance.ActiveValue("z_homes_to_max") == "0") // we are homed to the bed { // move to the height we can resume printing from Vector2 resumePositionXy = ActiveSliceSettings.Instance.ActiveVector2("resume_position_before_z_home"); queuedCommands.Add(CreateMovementLine(new PrinterMove(new VectorMath.Vector3(resumePositionXy.x, resumePositionXy.y, lastDestination.position.z + 5), 0, MovementControls.ZSpeed))); // move just above the actual print position queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position + new VectorMath.Vector3(0, 0, 5), 0, MovementControls.XSpeed))); // move down to part queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position, 0, MovementControls.ZSpeed))); } else { // move to the actual print position queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position, 0, MovementControls.ZSpeed))); } // extrude back to our filament start queuedCommands.Add("G1 E5"); /// reset the printer to know where the filament should be queuedCommands.Add("G92 E{0}".FormatWith(lastDestination.extrusion)); resumeState = ResumeState.PrintingSlow; } return(""); case ResumeState.PrintingSlow: { string lineToSend = internalStream.ReadLine(); if (lineToSend != null && lineToSend.StartsWith("; LAYER:")) { if (lineToSend != null && LineIsMovement(lineToSend)) { PrinterMove currentMove = GetPosition(lineToSend, lastDestination); PrinterMove moveToSend = currentMove; double feedRate; string firstLayerSpeed = ActiveSliceSettings.Instance.ActiveValue("resume_first_layer_speed"); if (!double.TryParse(firstLayerSpeed, out feedRate)) { feedRate = 10; } feedRate *= 60; moveToSend.feedRate = feedRate; lineToSend = CreateMovementLine(moveToSend, lastDestination); lastDestination = currentMove; return(lineToSend); } return(lineToSend); } } resumeState = ResumeState.PrintingToEnd; return(""); case ResumeState.PrintingToEnd: return(internalStream.ReadLine()); } return(null); }
public override string ReadLine() { string lineToSend = base.ReadLine(); if (lineToSend == null) { return(null); } if (lineToSend.EndsWith("; NO_PROCESSING")) { return(lineToSend); } // check if any of the heaters we will be switching to need to start heating ManageReHeating(lineToSend); if (lineToSend == compleatedBeforeGCodeString) { activeTool = requestedTool; SendState = SendStates.Normal; QueueAfterGCode(); } // track the tool state if (lineToSend.StartsWith("T")) { int changeCommandTool = -1; if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref changeCommandTool) && changeCommandTool != activeTool) { requestedTool = changeCommandTool; if (SendState == SendStates.Normal) { SendState = SendStates.WaitingForMove; // don't queue the tool change until after the before gcode has been sent return($"; waiting for move on T{requestedTool}"); } } } // check if there is a temperature change request else if (lineToSend.StartsWith("M104") || lineToSend.StartsWith("M109")) { double toolBeingSet = -1; // if there is a tool specification if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref toolBeingSet)) { if (toolBeingSet != activeTool) { // For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not) queuedCommandsStream.Add("T{0} ; NO_PROCESSING".FormatWith(activeTool)); } } } if (QueueBeforeIfNeedToSwitchExtruders(lineToSend)) { return(""); } if (LineIsMovement(lineToSend)) { lastDestination = GetPosition(lineToSend, lastDestination); } return(lineToSend); }