public void Report(ProgressStatus progressStatus) { double currentValue = 0; double destValue = 10; string statusText = progressStatus.Status = progressStatus.Status.Trim().TrimEnd('.'); if (GCodeFile.GetFirstNumberAfter("", statusText, ref currentValue) && GCodeFile.GetFirstNumberAfter("/", statusText, ref destValue)) { if (destValue == 0) { destValue = 1; } progressStatus.Progress0To1 = currentValue / destValue; progressStatus.Target = null; } else { progressStatus.Status = statusText; progressStatus.Target = "terminal"; } reporter.Report(progressStatus); }
private string KeepTrackOfPostionAndDestination(string lineBeingSent) { if (lineBeingSent.StartsWith("G0 ") || lineBeingSent.StartsWith("G1 ")) { Vector3 newDestination = currentDestination; if (PrinterConnectionAndCommunication.Instance.MovementMode == PrinterMachineInstruction.MovementTypes.Relative) { newDestination = Vector3.Zero; } GCodeFile.GetFirstNumberAfter("X", lineBeingSent, out newDestination.x); GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, out newDestination.y); GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, out newDestination.z); GCodeFile.GetFirstNumberAfter("E", lineBeingSent, out currentExtruderDestination); GCodeFile.GetFirstNumberAfter("F", lineBeingSent, out currentFeedRate); if (PrinterConnectionAndCommunication.Instance.MovementMode == PrinterMachineInstruction.MovementTypes.Relative) { newDestination += currentDestination; } if (currentDestination != newDestination) { currentDestination = newDestination; DestinationChanged.CallEvents(this, null); } } return(lineBeingSent); }
public string ApplyLeveling(Vector3 currentDestination, string lineBeingSent) { if ((lineBeingSent.StartsWith("G0") || lineBeingSent.StartsWith("G1")) && lineBeingSent.Length > 2 && lineBeingSent[2] == ' ') { double extruderDelta = 0; GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref extruderDelta); double feedRate = 0; GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref feedRate); string newLine = "G1 "; if (lineBeingSent.Contains("X") || lineBeingSent.Contains("Y") || lineBeingSent.Contains("Z")) { Vector3 outPosition = PrintLevelingPlane.Instance.ApplyLeveling(currentDestination); newLine = newLine + String.Format("X{0:0.##} Y{1:0.##} Z{2:0.###}", outPosition.X, outPosition.Y, outPosition.Z); } if (extruderDelta != 0) { newLine = newLine + String.Format(" E{0:0.###}", extruderDelta); } if (feedRate != 0) { newLine = newLine + String.Format(" F{0:0.##}", feedRate); } lineBeingSent = newLine; } return(lineBeingSent); }
private string ApplyExtrusionMultiplier(string lineBeingSent) { if (lineBeingSent != null) { if (LineIsMovement(lineBeingSent)) { double gcodeRequestedExtrusionPosition = 0; if (GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref gcodeRequestedExtrusionPosition)) { double delta = gcodeRequestedExtrusionPosition - previousGcodeRequestedExtrusionPosition; double newActualExtruderPosition = currentActualExtrusionPosition + delta * ExtrusionRatio; lineBeingSent = GCodeFile.ReplaceNumberAfter('E', lineBeingSent, newActualExtruderPosition); previousGcodeRequestedExtrusionPosition = gcodeRequestedExtrusionPosition; currentActualExtrusionPosition = newActualExtruderPosition; } } else if (lineBeingSent.StartsWith("G92")) { double gcodeRequestedExtrusionPosition = 0; if (GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref gcodeRequestedExtrusionPosition)) { previousGcodeRequestedExtrusionPosition = gcodeRequestedExtrusionPosition; currentActualExtrusionPosition = gcodeRequestedExtrusionPosition; } } } return(lineBeingSent); }
public static PrinterMove GetPosition(string lineBeingSent, PrinterMove startPositionPosition) { PrinterMove currentDestination = startPositionPosition; GCodeFile.GetFirstNumberAfter("X", lineBeingSent, ref currentDestination.position.x); GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, ref currentDestination.position.y); GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, ref currentDestination.position.z); GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref currentDestination.extrusion); GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref currentDestination.feedRate); return(currentDestination); }
public string ApplyLeveling(Vector3 currentDestination, PrinterMachineInstruction.MovementTypes movementMode, string lineBeingSent, bool addLFCR, bool includeSpaces) { if ((lineBeingSent.StartsWith("G0") || lineBeingSent.StartsWith("G1")) && lineBeingSent.Length > 2 && lineBeingSent[2] == ' ') { double extruderDelta = 0; GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref extruderDelta); double feedRate = 0; GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref feedRate); string newLine = "G1 "; if (lineBeingSent.Contains('X') || lineBeingSent.Contains('Y') || lineBeingSent.Contains('Z')) { Vector3 outPosition = PrintLeveling.Instance.ApplyLeveling(currentDestination); if (movementMode == PrinterMachineInstruction.MovementTypes.Relative) { Vector3 relativeMove = Vector3.Zero; GCodeFile.GetFirstNumberAfter("X", lineBeingSent, ref relativeMove.x); GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, ref relativeMove.y); GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, ref relativeMove.z); outPosition = PrintLeveling.Instance.ApplyLevelingRotation(relativeMove); } if (includeSpaces) { newLine = newLine + String.Format("X{0:0.##} Y{1:0.##} Z{2:0.##}", outPosition.x, outPosition.y, outPosition.z); } else { newLine = newLine + String.Format("X{0:0.##}Y{1:0.##}Z{2:0.##}", outPosition.x, outPosition.y, outPosition.z); } } if (extruderDelta != 0) { newLine = newLine + String.Format(" E{0:0.###}", extruderDelta); } if (feedRate != 0) { newLine = newLine + String.Format(" F{0:0.##}", feedRate); } lineBeingSent = newLine; if (addLFCR) { lineBeingSent += "\r\n"; } } return(lineBeingSent); }
private void GetZProbeHeight(object sender, string line) { if (line != null) { double sampleRead = double.MinValue; if (line.StartsWith("Bed")) // marlin G30 return code (looks like: 'Bed Position X:20 Y:32 Z:.01') { sampledPosition.X = positionToSample.X; sampledPosition.Y = positionToSample.Y; GCodeFile.GetFirstNumberAfter("Z:", line, ref sampleRead); } else if (line.StartsWith("Z:")) // smoothie G30 return code (looks like: 'Z:10.01') { sampledPosition.X = positionToSample.X; sampledPosition.Y = positionToSample.Y; // smoothie returns the position relative to the start position double reportedProbeZ = 0; GCodeFile.GetFirstNumberAfter("Z:", line, ref reportedProbeZ); sampleRead = positionToSample.Z - reportedProbeZ; } if (sampleRead != double.MinValue) { samplesForSinglePosition.Add(sampleRead); int numberOfSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); if (samplesForSinglePosition.Count >= numberOfSamples) { samplesForSinglePosition.Sort(); if (samplesForSinglePosition.Count > 3) { // drop the high and low values samplesForSinglePosition.RemoveAt(0); samplesForSinglePosition.RemoveAt(samplesForSinglePosition.Count - 1); } sampledPosition.Z = Math.Round(samplesForSinglePosition.Average(), 2); // When probe data has been collected, resume our thread to continue collecting waitingToCompleteNextSample = false; } else { // add the next request for probe printer.Connection.QueueLine("G30"); // raise the probe after each sample var feedRates = printer.Settings.Helpers.ManualMovementSpeeds(); printer.Connection.QueueLine($"G1 X{positionToSampleWithProbeOffset.X:0.###}Y{positionToSampleWithProbeOffset.Y:0.###}Z{positionToSampleWithProbeOffset.Z:0.###} F{feedRates.X}"); } } } }
private void GetZProbeHeight(object sender, string line) { if (line != null) { double sampleRead = double.MinValue; if (line.StartsWith("Bed")) // marlin G30 return code (looks like: 'Bed Position X:20 Y:32 Z:.01') { probePositions[probePositionsBeingEditedIndex].Position.X = probeStartPosition.X; probePositions[probePositionsBeingEditedIndex].Position.Y = probeStartPosition.Y; GCodeFile.GetFirstNumberAfter("Z:", line, ref sampleRead); } else if (line.StartsWith("Z:")) // smoothie G30 return code (looks like: 'Z:10.01') { probePositions[probePositionsBeingEditedIndex].Position.X = probeStartPosition.X; probePositions[probePositionsBeingEditedIndex].Position.Y = probeStartPosition.Y; // smoothie returns the position relative to the start position double reportedProbeZ = 0; GCodeFile.GetFirstNumberAfter("Z:", line, ref reportedProbeZ); sampleRead = probeStartPosition.Z - reportedProbeZ; } if (sampleRead != double.MinValue) { samples.Add(sampleRead); int numberOfSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); if (samples.Count >= numberOfSamples) { samples.Sort(); if (samples.Count > 3) { // drop the high and low values samples.RemoveAt(0); samples.RemoveAt(samples.Count - 1); } probePositions[probePositionsBeingEditedIndex].Position.Z = Math.Round(samples.Average(), 2); // When probe data has been collected, resume our thread to continue collecting autoResetEvent.Set(); } else if (!this.HasBeenClosed) { // add the next request for probe printer.Connection.QueueLine("G30"); // raise the probe after each sample printer.Connection.MoveAbsolute(adjustedProbePosition, feedRates.X); } } } }
public override string ReadLine() { string lineToSend = base.ReadLine(); if (lineToSend != null && lineToSend.EndsWith("; NO_PROCESSING")) { return(lineToSend); } if (lineToSend != null && lineToSend.StartsWith("T")) { int extruder = 0; if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruder)) { extruderIndex = extruder; } } if (lineToSend != null && LineIsMovement(lineToSend)) { inputNoBabyStepping = GetPosition(lineToSend, inputNoBabyStepping); // it is a struct so this is making a new copy we con modify PrinterMove moveToSend = inputNoBabyStepping; printer.Settings.ForTools <double>(SettingsKey.baby_step_z_offset, (key, value, i) => { if (extruderIndex == i) { moveToSend.position = new Vector3(moveToSend.position.X, moveToSend.position.Y, moveToSend.position.Z + GetBabbyStepOffset(i)); } }); moveToSend.position -= extruderOffsets[Math.Min(extruderIndex, 4)]; if (moveToSend.HaveAnyPosition) { lineToSend = CreateMovementLine(moveToSend, outputWithBabyStepping); } outputWithBabyStepping = moveToSend; return(lineToSend); } 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); }
private void GetZProbeHeight(object sender, EventArgs e) { StringEventArgs currentEvent = e as StringEventArgs; if (currentEvent != null) { double sampleRead = double.MinValue; if (currentEvent.Data.StartsWith("Bed")) // marlin G30 return code (looks like: 'Bed Position X:20 Y:32 Z:.01') { probePositions[probePositionsBeingEditedIndex].position.X = probeStartPosition.X; probePositions[probePositionsBeingEditedIndex].position.Y = probeStartPosition.Y; GCodeFile.GetFirstNumberAfter("Z:", currentEvent.Data, ref sampleRead); } else if (currentEvent.Data.StartsWith("Z:")) // smoothie G30 return code (looks like: 'Z:10.01') { probePositions[probePositionsBeingEditedIndex].position.X = probeStartPosition.X; probePositions[probePositionsBeingEditedIndex].position.Y = probeStartPosition.Y; // smoothie returns the position relative to the start position double reportedProbeZ = 0; GCodeFile.GetFirstNumberAfter("Z:", currentEvent.Data, ref reportedProbeZ); sampleRead = probeStartPosition.Z - reportedProbeZ; } if (sampleRead != double.MinValue) { samples.Add(sampleRead); int numberOfSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); if (samples.Count == numberOfSamples) { samples.Sort(); if (samples.Count > 3) { // drop the high and low values samples.RemoveAt(0); samples.RemoveAt(samples.Count - 1); } probePositions[probePositionsBeingEditedIndex].position.Z = Math.Round(samples.Average(), 2); UiThread.RunOnIdle(() => nextButton.InvokeClick()); } } } }
private string ApplyFeedRateMultiplier(string lineBeingSent) { if (lineBeingSent != null && FeedRateRatio != 1) { lineBeingSent = lineBeingSent.ToUpper().Trim(); if (lineBeingSent.StartsWith("G0") || lineBeingSent.StartsWith("G1")) { double feedRate = 0; if (GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref feedRate)) { lineBeingSent = GCodeFile.ReplaceNumberAfter('F', lineBeingSent, feedRate * FeedRateRatio); } } } return lineBeingSent; }
private void TrackExtruderState(string line) { if (line == null) { return; } if (line.StartsWith("G28)")) { activeExtruderIndex = 0; requestedExtruder = 0; } if (line.StartsWith("T")) { GCodeFile.GetFirstNumberAfter("T", line, ref requestedExtruder); } }
public string DoApplyLeveling(string lineBeingSent, Vector3 currentDestination, PrinterMachineInstruction.MovementTypes movementMode) { double extruderDelta = 0; GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref extruderDelta); double feedRate = 0; GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref feedRate); StringBuilder newLine = new StringBuilder("G1 "); if (lineBeingSent.Contains("X") || lineBeingSent.Contains("Y") || lineBeingSent.Contains("Z")) { Vector3 outPosition = GetPositionWithZOffset(currentDestination); if (movementMode == PrinterMachineInstruction.MovementTypes.Relative) { Vector3 delta = outPosition - lastDestinationWithLevelingApplied; lastDestinationWithLevelingApplied = outPosition; outPosition = delta; } else { lastDestinationWithLevelingApplied = outPosition; } newLine = newLine.Append(String.Format("X{0:0.##} Y{1:0.##} Z{2:0.###}", outPosition.x, outPosition.y, outPosition.z)); } if (extruderDelta != 0) { newLine = newLine.Append(String.Format(" E{0:0.###}", extruderDelta)); } if (feedRate != 0) { newLine = newLine.Append(String.Format(" F{0:0.##}", feedRate)); } lineBeingSent = newLine.ToString(); return(lineBeingSent); }
public override string ReadLine() { string lineToSend = base.ReadLine(); if (lineToSend != null && lineToSend.EndsWith("; NO_PROCESSING")) { return(lineToSend); } if (lineToSend != null && lineToSend.StartsWith("T")) { int extruder = 0; if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruder)) { extruderIndex = extruder; } } if (lineToSend != null && LineIsMovement(lineToSend)) { PrinterMove currentMove = GetPosition(lineToSend, lastDestination); PrinterMove moveToSend = currentMove; if (extruderIndex < 4) { moveToSend.position += BabbyStepOffset; moveToSend.position -= extruderOffsets[extruderIndex]; } if (moveToSend.HaveAnyPosition) { lineToSend = CreateMovementLine(moveToSend, lastDestination); } lastDestination = currentMove; return(lineToSend); } return(lineToSend); }
public static PrinterMove GetPosition(string lineBeingSent, PrinterMove startPositionPosition) { if (lineBeingSent.StartsWith("G28") || lineBeingSent.StartsWith("G29") || lineBeingSent.StartsWith("G30")) { return(PrinterMove.Unknown); } PrinterMove currentDestination = startPositionPosition; GCodeFile.GetFirstNumberAfter("X", lineBeingSent, ref currentDestination.position.X); GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, ref currentDestination.position.Y); GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, ref currentDestination.position.Z); GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref currentDestination.extrusion); GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref currentDestination.feedRate); return(currentDestination); }
public void Leveling7PointsNeverGetsTooHigh() { StaticData.Instance = new MatterHackers.Agg.FileSystemStaticData(Path.Combine("..", "..", "..", "..", "StaticData")); MatterControlUtilities.OverrideAppDataLocation(); var levelingData = new PrintLevelingData(ActiveSliceSettings.Instance); double radius = 100; levelingData.SampledPositions = new List <Vector3>(); levelingData.SampledPositions.Add(new Vector3(130.00, 0.00, 0)); levelingData.SampledPositions.Add(new Vector3(65.00, 112.58, 10)); levelingData.SampledPositions.Add(new Vector3(-65.00, 112.58, 0)); levelingData.SampledPositions.Add(new Vector3(-130.00, 0.00, 10)); levelingData.SampledPositions.Add(new Vector3(-65.00, -112.58, 0)); levelingData.SampledPositions.Add(new Vector3(65.00, -112.58, 10)); levelingData.SampledPositions.Add(new Vector3(0, 0, 0)); levelingData.SampledPositions.Add(new Vector3(0, 0, 6)); Vector2 bedCenter = Vector2.Zero; RadialLevlingFunctions levelingFunctions7Point = new RadialLevlingFunctions(6, levelingData, bedCenter); int totalPoints = 2000; for (int curPoint = 0; curPoint < totalPoints; curPoint++) { Vector2 currentTestPoint = new Vector2(radius, 0); currentTestPoint.Rotate(MathHelper.Tau / totalPoints * curPoint); Vector3 destPosition = new Vector3(currentTestPoint, 0); Vector3 outPosition = levelingFunctions7Point.GetPositionWithZOffset(destPosition); Assert.IsTrue(outPosition.z <= 10); string outPositionString = levelingFunctions7Point.DoApplyLeveling(GetGCodeString(destPosition), destPosition, PrinterMachineInstruction.MovementTypes.Absolute); double outZ = 0; Assert.IsTrue(GCodeFile.GetFirstNumberAfter("Z", outPositionString, ref outZ)); Assert.IsTrue(outZ <= 10); } }
public override string ReadLine() { string lineToSend = base.ReadLine(); if (lineToSend != null && lineToSend.EndsWith("; NO_PROCESSING")) { return(lineToSend); } if (lineToSend != null && lineToSend.StartsWith("T")) { int extruder = 0; if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruder)) { extruderIndex = extruder; } } if (lineToSend != null && LineIsMovement(lineToSend)) { inputNoBabyStepping = GetPosition(lineToSend, inputNoBabyStepping); // it is a struct so this is making a new copy we con modify PrinterMove moveToSend = inputNoBabyStepping; moveToSend.position += BabbyStepOffset; moveToSend.position -= extruderOffsets[Math.Min(extruderIndex, 4)]; if (moveToSend.HaveAnyPosition) { lineToSend = CreateMovementLine(moveToSend, outputWithBabyStepping); } outputWithBabyStepping = moveToSend; return(lineToSend); } return(lineToSend); }
public static string GetLayerFanSpeeds(this GCodeFile loadedGCode, int activeLayerIndex) { if (loadedGCode == null || loadedGCode.LayerCount == 0) { return("---"); } int startInstruction = loadedGCode.GetFirstLayerInstruction(activeLayerIndex); if (activeLayerIndex == 0) { startInstruction = 0; } int endInstruction = loadedGCode.GetFirstLayerInstruction(activeLayerIndex + 1); string separator = ""; string fanSpeeds = ""; for (int i = startInstruction; i < endInstruction; i++) { var line = loadedGCode.Instruction(i).Line; if (line.StartsWith("M107")) // fan off { fanSpeeds += separator + "Off"; separator = ", "; } else if (line.StartsWith("M106")) // fan on { double speed = 0; if (GCodeFile.GetFirstNumberAfter("M106", line, ref speed, 0, "")) { fanSpeeds += separator + $"{speed / 255 * 100:0}%"; separator = ", "; } } } return(fanSpeeds); }
public void Leveling7PointsNeverGetsTooHeigh() { PrintLevelingData levelingData = new PrintLevelingData(); double radius = 100; levelingData.SampledPositions = new List <Vector3>(); levelingData.SampledPositions.Add(new Vector3(130.00, 0.00, 0)); levelingData.SampledPositions.Add(new Vector3(65.00, 112.58, 10)); levelingData.SampledPositions.Add(new Vector3(-65.00, 112.58, 0)); levelingData.SampledPositions.Add(new Vector3(-130.00, 0.00, 10)); levelingData.SampledPositions.Add(new Vector3(-65.00, -112.58, 0)); levelingData.SampledPositions.Add(new Vector3(65.00, -112.58, 10)); levelingData.SampledPositions.Add(new Vector3(0, 0, 0)); levelingData.SampledPositions.Add(new Vector3(0, 0, 6)); Vector2 bedCenter = Vector2.Zero; RadialLevlingFunctions levelingFunctions7Point = new RadialLevlingFunctions(6, levelingData, bedCenter); int totalPoints = 2000; for (int curPoint = 0; curPoint < totalPoints; curPoint++) { Vector2 currentTestPoint = new Vector2(radius, 0); currentTestPoint.Rotate(MathHelper.Tau / totalPoints * curPoint); Vector3 destPosition = new Vector3(currentTestPoint, 0); Vector3 outPosition = levelingFunctions7Point.GetPositionWithZOffset(destPosition); Assert.IsTrue(outPosition.z <= 10); string outPositionString = levelingFunctions7Point.DoApplyLeveling(GetGCodeString(destPosition), destPosition, PrinterMachineInstruction.MovementTypes.Absolute); double outZ = 0; Assert.IsTrue(GCodeFile.GetFirstNumberAfter("Z", outPositionString, ref outZ)); Assert.IsTrue(outZ <= 10); } }
public void Report(ProgressStatus progressStatus) { double currentValue = 0; double destValue = 10; string statusText = progressStatus.Status = progressStatus.Status.Trim().TrimEnd('.'); if (GCodeFile.GetFirstNumberAfter("", statusText, ref currentValue) && GCodeFile.GetFirstNumberAfter("/", statusText, ref destValue)) { if (destValue == 0) { destValue = 1; } progressStatus.Progress0To1 = currentValue / destValue; } else { printer.Connection.TerminalLog.WriteLine(statusText); } reporter.Report(progressStatus); }
private void GetZProbeHeight(object sender, string line) { if (line != null) { double sampleRead = double.MinValue; if (line.StartsWith("Bed")) // marlin G30 return code (looks like: 'Bed Position X:20 Y:32 Z:.01') { sampledPositions[activeProbeIndex].Position.X = positionToSample.X; sampledPositions[activeProbeIndex].Position.Y = positionToSample.Y; GCodeFile.GetFirstNumberAfter("Z:", line, ref sampleRead); } else if (line.StartsWith("Z:")) // smoothie G30 return code (looks like: 'Z:10.01') { sampledPositions[activeProbeIndex].Position.X = positionToSample.X; sampledPositions[activeProbeIndex].Position.Y = positionToSample.Y; // smoothie returns the position relative to the start position double reportedProbeZ = 0; GCodeFile.GetFirstNumberAfter("Z:", line, ref reportedProbeZ); sampleRead = positionToSample.Z - reportedProbeZ; } if (sampleRead != double.MinValue) { samplesForSinglePosition.Add(sampleRead); int numberOfSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); if (samplesForSinglePosition.Count >= numberOfSamples) { samplesForSinglePosition.Sort(); if (samplesForSinglePosition.Count > 3) { // drop the high and low values samplesForSinglePosition.RemoveAt(0); samplesForSinglePosition.RemoveAt(samplesForSinglePosition.Count - 1); } sampledPositions[activeProbeIndex].Position.Z = Math.Round(samplesForSinglePosition.Average(), 2); // If we are sampling the first point, check if it is unchanged from the last time we ran leveling if (activeProbeIndex == 0) { var levelingData = printer.Settings.Helpers.PrintLevelingData; var currentSample = sampledPositions[activeProbeIndex].Position.Z; var oldSample = levelingData.SampledPositions.Count > 0 ? levelingData.SampledPositions[activeProbeIndex].Z : 0; var delta = currentSample - oldSample; printer.Connection.TerminalLog.WriteLine($"Validation Sample: Old {oldSample}, New {currentSample}, Delta {delta}"); if (levelingData.SampledPositions.Count == sampledPositions.Count && Math.Abs(delta) < printer.Settings.GetValue <double>(SettingsKey.validation_threshold)) { // the last leveling is still good abort this new calibration and start printing CancelValidation(); waitingToCompleteNextSample = false; validationRunning = false; validationHasBeenRun = true; } } // When probe data has been collected, resume our thread to continue collecting waitingToCompleteNextSample = false; // and go on to the next point activeProbeIndex++; } else { // add the next request for probe queuedCommands.Enqueue("G30"); // raise the probe after each sample var feedRates = printer.Settings.Helpers.ManualMovementSpeeds(); queuedCommands.Enqueue($"G1 X{positionToSampleWithProbeOffset.X:0.###}Y{positionToSampleWithProbeOffset.Y:0.###}Z{positionToSampleWithProbeOffset.Z:0.###} F{feedRates.X}"); } } } }
public override string ReadLine() { if (queuedCommands.Count > 0) { return(queuedCommands.Dequeue()); } string lineToSend = base.ReadLine(); if (lineToSend == null) { return(null); } if (lineToSend.EndsWith("; NO_PROCESSING")) { return(lineToSend); } GCodeFile.GetFirstNumberAfter("F", lineToSend, ref lastSeenFeedRate); var requestedToolForTempChange = -1; // if we see a temp command remember what heat we are setting if (lineToSend.StartsWith("M109") || lineToSend.StartsWith("M104")) { int toolTemp = 0; // get the temp we are setting GCodeFile.GetFirstNumberAfter("S", lineToSend, ref toolTemp); // set it to the tool we will be changing to requestedToolForTempChange = RequestedTool; // check if this command contains a tool specification GCodeFile.GetFirstNumberAfter("T", lineToSend, ref requestedToolForTempChange); if (!lineToSend.Contains("; INACTIVE_COOL_DOWN")) { if (targetTemps[requestedToolForTempChange] != toolTemp) { targetTemps[requestedToolForTempChange] = toolTemp; } } } // check if any of the heaters we will be switching to need to start heating ManageReHeating(lineToSend); if (lineToSend == completedBeforeGCodeString && sendState != SendStates.Normal) { activeTool = RequestedTool; sendState = SendStates.Normal; QueueAfterGCode(); } var lineNoComment = lineToSend.Split(';')[0]; if (lineNoComment == "G28" || lineNoComment == "G28 Z0") { sendState = SendStates.Normal; RequestedTool = activeTool = 0; } // if this command is a temperature change request if (requestedToolForTempChange != -1) { if (requestedToolForTempChange != activeTool) { if (DoSmoothieCorrections) { // For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not) queuedCommands.Enqueue($"T{activeTool}"); } var temp = GetNextToolTemp(requestedToolForTempChange); if (temp > 0) { return($"{lineToSend.Substring(0, 4)} T{requestedToolForTempChange} S{temp}"); } else // send the temp as requested { return(lineToSend); } } // if we are waiting to switch to the next tool else if (activeTool != RequestedTool) { // if this command does not include the extruder to switch to, than we need to switch before sending it if (!lineNoComment.Contains("T")) { queuedCommands.Enqueue($"T{RequestedTool}"); } if (DoSmoothieCorrections) { // For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not) queuedCommands.Enqueue($"T{activeTool}"); } // then send the heat command return(lineToSend); } } // if this is a tool change request else if (lineToSend.StartsWith("T")) { int changeCommandTool = -1; if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref changeCommandTool)) { if (changeCommandTool == activeTool) { if (sendState == SendStates.WaitingForMove) { // we have to switch back to our starting tool without a move // change back to normal processing and don't change tools sendState = SendStates.Normal; var lastRequestedTool = RequestedTool; // set the requested tool RequestedTool = changeCommandTool; // don't send the change we are on the right tool now return($"; switch back without move from T{lastRequestedTool} to T{activeTool}"); } } else // we are switching tools { if (sendState == SendStates.Normal) { sendState = SendStates.WaitingForMove; // set the requested tool RequestedTool = changeCommandTool; // don't queue the tool change until after the before gcode has been sent return($"; waiting for move on T{RequestedTool}"); } } } } // if it is only an extrusion move if (sendState == SendStates.WaitingForMove && activeTool != RequestedTool && // is different than the last extruder set (lineNoComment.StartsWith("G0 ") || lineNoComment.StartsWith("G1 ")) && // is a G1 or G0 lineNoComment.Contains("E") // it is an extrusion move // and have no other position information && !lineNoComment.Contains("X") && !lineNoComment.Contains("Y") && !lineNoComment.Contains("Z")) { double ePosition = 0; if (GCodeFile.GetFirstNumberAfter("E", lineNoComment, ref ePosition)) { // switch extruders queuedCommands.Enqueue($"T{RequestedTool}"); if (DoSmoothieCorrections) { // if we know the current E position before the switch // set the E value to the previous E value. if (lastDestination.extrusion != double.PositiveInfinity) { // On Marlin E position is shared between extruders and this code has no utility // On Smoothie E is stored per extruder and this makes it behave the same as Marlin queuedCommands.Enqueue($"G92 E{lastDestination.extrusion}"); } } // send the extrusion queuedCommands.Enqueue(lineNoComment + " ; NO_PROCESSING"); lastDestination.extrusion = ePosition; if (DoSmoothieCorrections) { // switch back queuedCommands.Enqueue($"T{activeTool}"); queuedCommands.Enqueue($"G92 E{lastDestination.extrusion}"); } return(""); } } if (QueueBeforeIfNeedToSwitchExtruders(lineToSend, lineNoComment)) { return(""); } if (LineIsMovement(lineToSend)) { lastDestination = GetPosition(lineToSend, lastDestination); } return(lineToSend); }
public override string ReadLine() { switch (state) { case State.passthrough: { string lineToSend = base.ReadLine(); if (lineToSend != null && lineToSend.StartsWith("M")) { // initial test is just to see if it is an M109 if (lineToSend.StartsWith("M109")) // extruder set and wait temp { if (lineToSend.Contains("F") || // If it has a control character F (auto temp) !lineToSend.Contains("S")) // if it is a reset (has no S temperature) { // don't replace it return(lineToSend); } // send an M104 instead waitWhenCooling = false; lineToSend = "M104" + lineToSend.Substring(4); GCodeFile.GetFirstNumberAfter("S", lineToSend, ref targetTemp); extruderIndex = 0; GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruderIndex); if (targetTemp > ignoreRequestIfBelowTemp) { state = State.waitingForExtruderTemp; timeHaveBeenAtTemp.Reset(); } else { Thread.Sleep(100); // sleep .1 second while waiting for temp return(""); // return nothing until we reach temp } } else if (lineToSend.StartsWith("M190")) // bed set and wait temp { // send an M140 instead bool gotR = GCodeFile.GetFirstNumberAfter("R", lineToSend, ref targetTemp); bool gotS = GCodeFile.GetFirstNumberAfter("S", lineToSend, ref targetTemp); if (gotR || gotS) { if (targetTemp > ignoreRequestIfBelowTemp) { waitWhenCooling = gotR; lineToSend = "M140 S" + targetTemp.ToString(); state = State.waitingForBedTemp; timeHaveBeenAtTemp.Reset(); } else { Thread.Sleep(100); // sleep .1 second while waiting for temp return(""); // return nothing until we reach temp } } else { Thread.Sleep(100); // sleep .1 second while waiting for temp return(""); // return nothing until we reach temp } } } return(lineToSend); } case State.waitingForExtruderTemp: { double extruderTemp = PrinterConnectionAndCommunication.Instance.GetActualExtruderTemperature((int)extruderIndex); bool tempWithinRange = extruderTemp >= targetTemp - sameTempRange && extruderTemp <= targetTemp + sameTempRange; if (tempWithinRange && !timeHaveBeenAtTemp.IsRunning) { timeHaveBeenAtTemp.Start(); } if (timeHaveBeenAtTemp.Elapsed.TotalSeconds > waitAfterReachTempTime || PrinterConnectionAndCommunication.Instance.PrintWasCanceled) { // switch to pass through and continue state = State.passthrough; return(""); } else { // send a wait command Thread.Sleep(100); // sleep .1 second while waiting for temp return(""); // return nothing until we reach temp } } case State.waitingForBedTemp: { double bedTemp = PrinterConnectionAndCommunication.Instance.ActualBedTemperature; bool tempWithinRange; if (waitWhenCooling) { tempWithinRange = bedTemp >= targetTemp - sameTempRange && bedTemp <= targetTemp + sameTempRange; } else { tempWithinRange = bedTemp >= targetTemp - sameTempRange; } // Added R code for M190 if (tempWithinRange && !timeHaveBeenAtTemp.IsRunning) { timeHaveBeenAtTemp.Start(); } if (timeHaveBeenAtTemp.Elapsed.TotalSeconds > waitAfterReachTempTime || PrinterConnectionAndCommunication.Instance.PrintWasCanceled) { // switch to pass through and continue state = State.passthrough; return(""); } else { // send a wait command Thread.Sleep(100); // sleep .1 second while waiting for temp return(""); // return nothing until we reach temp } } } return(null); }
private void LineReceived(object sender, string line) { if (line != null) { if (line.Contains("ros_")) { if (line.Contains("TRIGGERED")) { readOutOfFilament = true; } } if (line.Contains("pos_")) { double sensorDistance = 0; double stepperDistance = 0; if (GCodeFile.GetFirstNumberAfter("SENSOR:", line, ref sensorDistance)) { var checkDistance = printer.Settings.GetValue <double>(SettingsKey.runout_sensor_check_distance); if (sensorDistance < -checkDistance || sensorDistance > checkDistance) { printer.Connection.FilamentPositionSensorDetected = true; } if (printer.Connection.FilamentPositionSensorDetected) { GCodeFile.GetFirstNumberAfter("STEPPER:", line, ref stepperDistance); var stepperDelta = Math.Abs(stepperDistance - positionSensorData.LastStepperDistance); // if we think we should have moved the filament by more than 1mm if (stepperDelta > checkDistance) { var sensorDelta = Math.Abs(sensorDistance - positionSensorData.LastSensorDistance); var deltaRatio = sensorDelta / stepperDelta; if (printer.Settings.GetValue <bool>(SettingsKey.report_runout_sensor_data)) { // report the position for debugging printer.Connection.TerminalLog.WriteLine($"RUNOUT ({positionSensorData.ExtrusionDiscrepency}): Sensor ({sensorDelta:0.##}) / Stepper ({stepperDelta:0.##}) = {deltaRatio:0.##}"); } var ratio = Math.Max(.1, Math.Min(20, printer.Settings.GetValue <double>(SettingsKey.runout_sensor_trigger_ratio))); var sensorMaxRatio = Math.Max(ratio, 1 / ratio); var sensorMinRatio = Math.Min(ratio, 1 / ratio); // check if the sensor data is within a tolerance of the stepper data if (deltaRatio < sensorMinRatio || deltaRatio > sensorMaxRatio) { // we have a discrepancy set a runout state positionSensorData.ExtrusionDiscrepency++; if (positionSensorData.ExtrusionDiscrepency > 2) { readOutOfFilament = true; positionSensorData.ExtrusionDiscrepency = 0; } } else { positionSensorData.ExtrusionDiscrepency = 0; } // and record this position positionSensorData.LastSensorDistance = sensorDistance; positionSensorData.LastStepperDistance = stepperDistance; } } } } } }
public static void Main(string[] args) { #if false // this is for some early testing of SLA output var test = new PhotonFile(); void Progress(string message) { Debug.WriteLine(message); } var sourceFile = @"C:\Users\LarsBrubaker\Downloads\10mm-benchy.photon"; if (File.Exists(sourceFile)) { test.ReadFile(sourceFile, Progress); test.SaveFile(@"C:\Users\LarsBrubaker\Downloads\10mm-bench2.photon"); } else { sourceFile = @"C:\Users\larsb\Downloads\_rocktopus.ctb"; test.ReadFile(sourceFile, Progress); test.SaveFile(@"C:\Users\larsb\Downloads\_rocktopus.photon"); } #endif #if false // this is for processing print log exports var filename = "C:\\Users\\LarsBrubaker\\Downloads\\210309 B2 print_log.txt"; var lines = File.ReadAllLines(filename); var newPosition = default(Vector3); var ePosition = 0.0; var instruction = 0; var layer = 0; using (var writetext = new StreamWriter("C:\\Temp\\printlog.gcode")) { foreach (var line in lines) { if (line.Contains(" G1 ")) { GCodeFile.GetFirstNumberAfter("X", line, ref newPosition.X); GCodeFile.GetFirstNumberAfter("Y", line, ref newPosition.Y); GCodeFile.GetFirstNumberAfter("Z", line, ref newPosition.Z); GCodeFile.GetFirstNumberAfter("E", line, ref ePosition); writetext.WriteLine($"G1 X{newPosition.X} Y{newPosition.Y} Z{newPosition.Z} E{ePosition}"); instruction++; if (instruction % 500 == 0) { writetext.WriteLine($"; LAYER:{layer++}"); } } } } #endif // Set the global culture for the app, current thread and all new threads CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture; CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; // make sure we can build a system relevant serial port FrostedSerialPortFactory.GetPlatformSerialPort = (serialPortName) => { return(new CSharpSerialPortWrapper(serialPortName)); }; // Set default Agg providers AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.GlfwProvider.GlfwWindowProvider, MatterHackers.GlfwProvider"; // for now we will ship release with the old renderer #if !DEBUG AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms"; #endif string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); _raygunClient = new RaygunClient("hQIlyUUZRGPyXVXbI6l1dA==") // this is the PC key { ApplicationVersion = VersionInfo.Instance.ReleaseVersion }; #if !DEBUG if (AggContext.OperatingSystem == OSType.Windows) { waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "MatterControl#Startup", out bool created); if (!created) { // If an instance is already running, create a service proxy and execute ShellOpenFile var proxy = new ServiceProxy(); // and at least one argument is an acceptable shell file extension var itemsToAdd = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower())); if (itemsToAdd.Any()) { // notify the running instance of the event proxy.ShellOpenFile(itemsToAdd.ToArray()); } System.Threading.Thread.Sleep(1000); // Finally, close the process spawned by Explorer.exe return; } var serviceHost = new ServiceHost(typeof(LocalService), new[] { new Uri(ServiceBaseUri) }); serviceHost.AddServiceEndpoint(typeof(IMainService), new NetNamedPipeBinding(), mainServiceName); serviceHost.Open(); Console.Write( "Service started: {0};", string.Join(", ", serviceHost.Description.Endpoints.Select(s => s.ListenUri.AbsoluteUri).ToArray())); } #endif // If MatterControl isn't running and valid files were shelled, schedule a StartupAction to open the files after load var shellFiles = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower())); if (shellFiles.Any()) { ApplicationController.StartupActions.Add(new ApplicationController.StartupAction() { Title = "Shell Files", Priority = 0, Action = () => { // Open each shelled file foreach (string file in shellFiles) { ApplicationController.Instance.ShellOpenFile(file); } } }); } // Load optional user configuration IConfiguration config = new ConfigurationBuilder() .AddJsonFile("appsettings.json", optional: true) .AddJsonFile(Path.Combine(userProfilePath, "MatterControl.json"), optional: true) .Build(); // Override defaults via configuration config.Bind("Agg:ProviderTypes", AggContext.Config.ProviderTypes); config.Bind("Agg:GraphicsMode", AggContext.Config.GraphicsMode); Slicer.RunInProcess = config.GetValue <bool>("MatterControl:Slicer:Debug"); Application.EnableF5Collect = config.GetValue <bool>("MatterControl:Application:EnableF5Collect"); Application.EnableNetworkTraffic = config.GetValue <bool>("MatterControl:Application:EnableNetworkTraffic", true); Application.MiniTouchScreen.Make = config.GetValue <string>("MatterControl:MiniTouchScreen:Make", ""); Application.MiniTouchScreen.Model = config.GetValue <string>("MatterControl:MiniTouchScreen:Model", ""); // Make sure we have the right working directory as we assume everything relative to the executable. Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location)); Datastore.Instance.Initialize(DesktopSqlite.CreateInstance()); if (UserSettings.Instance.get(UserSettingsKey.ApplicationUseHeigResDisplays) == "true") { SetProcessDpiAwareness((int)DpiAwareness.PerMonitorAware); } var isExperimental = OemSettings.Instance.WindowTitleExtra == "Experimental"; #if !DEBUG // Conditionally spin up error reporting if not on the Stable channel string channel = UserSettings.Instance.get(UserSettingsKey.UpdateFeedType); if (string.IsNullOrEmpty(channel) || channel != "release" || isExperimental) #endif { System.Windows.Forms.Application.ThreadException += (s, e) => { if (raygunNotificationCount++ < RaygunMaxNotifications) { _raygunClient.Send(e.Exception); } if (System.Windows.Forms.Application.OpenForms.Count > 0 && !System.Windows.Forms.Application.OpenForms[0].InvokeRequired) { System.Windows.Forms.Application.Exit(); } }; AppDomain.CurrentDomain.UnhandledException += (s, e) => { if (raygunNotificationCount++ < RaygunMaxNotifications) { _raygunClient.Send(e.ExceptionObject as Exception); } System.Windows.Forms.Application.Exit(); }; } // Init platformFeaturesProvider before ShowAsSystemWindow string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms"; string textSizeMode = UserSettings.Instance.get(UserSettingsKey.ApplicationTextSize); if (!string.IsNullOrEmpty(textSizeMode)) { if (double.TryParse(textSizeMode, out double textSize)) { GuiWidget.DeviceScale = textSize; } } AppContext.Platform = AggContext.CreateInstanceFrom <INativePlatformFeatures>(platformFeaturesProvider); AppContext.Platform.InitPluginFinder(); AppContext.Platform.ProcessCommandline(); config.Bind("MatterControl", MatterHackers.MatterControl.AppContext.Options); // Get startup bounds from MatterControl and construct system window // var systemWindow = new DesktopMainWindow(400, 200) var(width, height) = RootSystemWindow.GetStartupBounds(); var systemWindow = Application.LoadRootWindow(width, height); var theme = ApplicationController.Instance.Theme; SingleWindowProvider.SetWindowTheme(theme.TextColor, theme.DefaultFontSize - 1, theme.InvertIcons, () => theme.CreateSmallResetButton(), theme.ToolbarPadding, theme.TabBarBackground, new Color(theme.PrimaryAccentColor, 175)); ApplicationController.Instance.KeepAwake = KeepAwake; systemWindow.ShowAsSystemWindow(); }
public override string ReadLine() { switch (state) { case State.passthrough: { string lineToSend = base.ReadLine(); if (lineToSend != null && lineToSend.StartsWith("M")) { if (lineToSend.StartsWith("M109")) // extruder set and wait temp { // send an M104 instead waitWhenCooling = false; lineToSend = "M104" + lineToSend.Substring(4); GCodeFile.GetFirstNumberAfter("S", lineToSend, ref targetTemp); extruderIndex = 0; GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruderIndex); if (targetTemp > ignoreRequestIfBelowTemp) { state = State.waitingForExtruderTemp; timeHaveBeenAtTemp.Reset(); } else { return("G4 P1000"); // 1 second } } else if (lineToSend.StartsWith("M190")) // bed set and wait temp { // send an M140 instead bool gotR = GCodeFile.GetFirstNumberAfter("R", lineToSend, ref targetTemp); bool gotS = GCodeFile.GetFirstNumberAfter("S", lineToSend, ref targetTemp); if (gotR || gotS) { if (targetTemp > ignoreRequestIfBelowTemp) { waitWhenCooling = gotR; lineToSend = "M140 S" + targetTemp.ToString(); state = State.waitingForBedTemp; timeHaveBeenAtTemp.Reset(); } else { return("G4 P1000"); // 1 second } } else { return("G4 P1000"); } } } return(lineToSend); } case State.waitingForExtruderTemp: { double extruderTemp = PrinterConnectionAndCommunication.Instance.GetActualExtruderTemperature((int)extruderIndex); bool tempWithinRange = extruderTemp >= targetTemp - sameTempRange && extruderTemp <= targetTemp + sameTempRange; if (tempWithinRange && !timeHaveBeenAtTemp.IsRunning) { timeHaveBeenAtTemp.Start(); } if (timeHaveBeenAtTemp.Elapsed.TotalSeconds > waitAfterReachTempTime || PrinterConnectionAndCommunication.Instance.PrintWasCanceled) { // switch to pass through and continue state = State.passthrough; return(base.ReadLine()); } else { // send a wait command return("G4 P1000"); // 1 second } } case State.waitingForBedTemp: { double bedTemp = PrinterConnectionAndCommunication.Instance.ActualBedTemperature; bool tempWithinRange; if (waitWhenCooling) { tempWithinRange = bedTemp >= targetTemp - sameTempRange && bedTemp <= targetTemp + sameTempRange; } else { tempWithinRange = bedTemp >= targetTemp - sameTempRange; } // Added R code for M190 if (tempWithinRange && !timeHaveBeenAtTemp.IsRunning) { timeHaveBeenAtTemp.Start(); } if (timeHaveBeenAtTemp.Elapsed.TotalSeconds > waitAfterReachTempTime || PrinterConnectionAndCommunication.Instance.PrintWasCanceled) { // switch to pass through and continue state = State.passthrough; return(base.ReadLine()); } else { // send a wait command return("G4 P1000"); // 1 second } } } return(null); }
public void PauseHandlingStreamTests() { int readX = 50; // Validate that the number parsing code is working as expected, specifically ignoring data that appears in comments // This is a regression that we saw in the Lulzbot Mini profile after adding macro processing. GCodeFile.GetFirstNumberAfter("X", "G1 Z10 E - 10 F12000 ; suck up XXmm of filament", ref readX); // did not change Assert.AreEqual(50, readX, "Don't change the x if it is after a comment"); // a comments that looks more like a valid line GCodeFile.GetFirstNumberAfter("X", "G1 Z10 E - 10 F12000 ; X33", ref readX); // did not change Assert.AreEqual(50, readX, "Don't change the x if it is after a comment"); // a line that should parse GCodeFile.GetFirstNumberAfter("X", "G1 Z10 E - 10 F12000 X33", ref readX); // did change Assert.AreEqual(33, readX, "not in a comment, do a change"); string[] inputLines = new string[] { "; the printer is moving normally", "G1 X10 Y10 Z10 E0", "G1 X10 Y10 Z10 E10", "G1 X10 Y10 Z10 E30", "; the printer pauses", "G91", "G1 Z10 E - 10 F12000 ; suck up XXmm of filament", "G90", "; the user moves the printer", "; the printer un-pauses", "G91", "G1 Z-10 E10.8 F12000", "G90", null, }; // We should go back to the above code when possible. It requires making pause part and move while paused part of the stream. // All communication should go through stream to minimize the difference between printing and controlling while not printing (all printing in essence). string[] expected = new string[] { "; the printer is moving normally", "G1 X10 Y10 Z10 E0", "G1 E10", "G1 E30", "; the printer pauses", "", // G91 is removed "G1 Z20 E20 F12000", // altered to be absolute "G90", "; the user moves the printer", "; the printer un-pauses", "", // G91 is removed "G1 Z10 E30.8", "G90", null, }; AggContext.StaticData = new FileSystemStaticData(TestContext.CurrentContext.ResolveProjectPath(4, "StaticData")); MatterControlUtilities.OverrideAppDataLocation(TestContext.CurrentContext.ResolveProjectPath(4)); var printer = new PrinterConfig(new PrinterSettings()); GCodeStream pauseHandlingStream = CreateTestGCodeStream(printer, inputLines, out List <GCodeStream> streamList); ValidateStreamResponse(expected, pauseHandlingStream); }
private void AddContentItem(FeedSectionData content) { switch (content.content_type) { case "headline": { break; // use the Golden Ratio to calculate an attractive size relative to the banner var image = new ImageBuffer(1520, (int)(170 / 1.618)); var imageWidget = new ResponsiveImageWidget(image) { Margin = new BorderDouble(5), Cursor = Cursors.Hand }; var graphics2D = image.NewGraphics2D(); image.SetRecieveBlender(new BlenderPreMultBGRA()); graphics2D.Clear(theme.AccentMimimalOverlay); // use the Golden Ratio to calculate an attractive size for the text relative to the text banner var pixelsPerPoint = 96.0 / 72.0; var goalPointSize = image.Height / pixelsPerPoint / 1.618; var printer = new TypeFacePrinter(content.text, goalPointSize); graphics2D.DrawString(content.text, image.Width / 2, image.Height / 2 + printer.TypeFaceStyle.EmSizeInPixels / 2, goalPointSize, Justification.Center, Baseline.BoundsTop, theme.TextColor); if (content.link != null) { imageWidget.Cursor = Cursors.Hand; imageWidget.Click += (s, e) => { if (e.Button == MouseButtons.Left) { ApplicationController.Instance.LaunchBrowser(content.link); } }; } this.AddChild(imageWidget); } break; case "banner_rotate": // TODO: make this make a carousel rather than add the first item and rotate between all the items var rand = new Random(); AddContentItem(content.banner_list[rand.Next(content.banner_list.Count)]); break; case "banner_image": { // Our banners seem to end with something like "=w1520-h170" // if present use that to get the right width and height int expectedWidth = 1520; GCodeFile.GetFirstNumberAfter("=w", content.image_url, ref expectedWidth); int expectedHeight = 170; GCodeFile.GetFirstNumberAfter("-h", content.image_url, ref expectedHeight); if ((content.theme_filter == "dark" && theme.IsDarkTheme) || (content.theme_filter == "light" && !theme.IsDarkTheme) || (content.theme_filter == "all")) { var image = new ImageBuffer(expectedWidth, expectedHeight); var imageWidget = new ResponsiveImageWidget(image) { Margin = new BorderDouble(5), Cursor = Cursors.Hand }; if (content.link != null) { imageWidget.Cursor = Cursors.Hand; imageWidget.Click += (s, e) => { if (e.Button == MouseButtons.Left) { ApplicationController.Instance.LaunchBrowser(content.link); } }; } imageWidget.Load += (s, e) => WebCache.RetrieveImageAsync(image, content.image_url, false, new BlenderPreMultBGRA()); this.AddChild(imageWidget); } } break; case "article_group": case "product_group": if (currentContentContainer == null) { currentContentContainer = new FlowLeftRightWithWrapping(); this.AddChild(currentContentContainer); } currentContentContainer.AddChild(new ExploreSection(content, theme)); break; } }
public PauseHandlingStream(PrintHostConfig printer, GCodeStream internalStream) : base(printer, internalStream) { // if we have a runout sensor, register to listen for lines to check it if (printer.Settings.GetValue <bool>(SettingsKey.filament_runout_sensor)) { printer.Connection.LineReceived += (s, line) => { if (line != null) { if (line.Contains("ros_")) { if (line.Contains("TRIGGERED")) { readOutOfFilament = true; } } if (line.Contains("pos_")) { double sensorDistance = 0; double stepperDistance = 0; if (GCodeFile.GetFirstNumberAfter("SENSOR:", line, ref sensorDistance)) { if (sensorDistance < -1 || sensorDistance > 1) { printer.Connection.FilamentPositionSensorDetected = true; } if (printer.Connection.FilamentPositionSensorDetected) { GCodeFile.GetFirstNumberAfter("STEPPER:", line, ref stepperDistance); var stepperDelta = Math.Abs(stepperDistance - positionSensorData.LastStepperDistance); // if we think we should have move the filament by more than 1mm if (stepperDelta > 1) { var sensorDelta = Math.Abs(sensorDistance - positionSensorData.LastSensorDistance); // check if the sensor data is within a tolerance of the stepper data var deltaRatio = sensorDelta / stepperDelta; if (deltaRatio < .5 || deltaRatio > 2) { // we have a reportable discrepancy set a runout state positionSensorData.ExtrusionDiscrepency++; if (positionSensorData.ExtrusionDiscrepency > 2) { readOutOfFilament = true; positionSensorData.ExtrusionDiscrepency = 0; } } else { positionSensorData.ExtrusionDiscrepency = 0; } // and record this position positionSensorData.LastSensorDistance = sensorDistance; positionSensorData.LastStepperDistance = stepperDistance; } } } } } }; } }