diff --git a/ConfigurationPage/PrintLeveling/PrintLevelPages.cs b/ConfigurationPage/PrintLeveling/PrintLevelPages.cs index dcf08054b..f8be6b81d 100644 --- a/ConfigurationPage/PrintLeveling/PrintLevelPages.cs +++ b/ConfigurationPage/PrintLeveling/PrintLevelPages.cs @@ -36,6 +36,7 @@ using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.VectorMath; using System; using System.Collections.Generic; +using System.Linq; namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling { @@ -335,12 +336,12 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling 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 probePositions[probePositionsBeingEditedIndex].position.z); - UiThread.RunOnIdle(() => container.nextButton.ClickButton(null)); + GCodeFile.GetFirstNumberAfter("Z:", currentEvent.Data, ref sampleRead); } else if (currentEvent.Data.StartsWith("Z:")) // smoothie G30 return code (looks like: 'Z:10.01') { @@ -349,8 +350,26 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling // smoothie returns the position relative to the start postion double reportedProbeZ = 0; GCodeFile.GetFirstNumberAfter("Z:", currentEvent.Data, ref reportedProbeZ); - probePositions[probePositionsBeingEditedIndex].position.z = reportedProbeZ - probeStartPosition.z; - UiThread.RunOnIdle(() => container.nextButton.ClickButton(null)); + sampleRead = probeStartPosition.z - reportedProbeZ; + } + + if (sampleRead != double.MinValue) + { + samples.Add(sampleRead); + + 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(() => container.nextButton.ClickButton(null)); + } } } } @@ -364,6 +383,9 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling base.OnClosed(e); } + readonly int NumberOfSamples = 5; + List samples = new List(); + public override void PageIsBecomingActive() { // always make sure we don't have print leveling turned on @@ -375,7 +397,10 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling PrinterConnectionAndCommunication.Instance.MoveAbsolute(PrinterConnectionAndCommunication.Axis.Z, probeStartPosition.z, feedRates.z); PrinterConnectionAndCommunication.Instance.MoveAbsolute(probeStartPosition, feedRates.x); - PrinterConnectionAndCommunication.Instance.SendLineToPrinterNow("G30"); // probe the current position + for (int i = 0; i < NumberOfSamples; i++) + { + PrinterConnectionAndCommunication.Instance.SendLineToPrinterNow("G30"); // probe the current position + } container.backButton.Enabled = false; container.nextButton.Enabled = false; diff --git a/PrinterCommunication/Io/PauseHandlingStream.cs b/PrinterCommunication/Io/PauseHandlingStream.cs index 8cf2f59ce..364087e76 100644 --- a/PrinterCommunication/Io/PauseHandlingStream.cs +++ b/PrinterCommunication/Io/PauseHandlingStream.cs @@ -28,34 +28,32 @@ either expressed or implied, of the FreeBSD Project. */ using MatterHackers.Agg; +using MatterHackers.GCodeVisualizer; +using MatterHackers.MatterControl.SlicerConfiguration; using MatterHackers.VectorMath; using System.Collections.Generic; -using System; -using MatterHackers.MatterControl.SlicerConfiguration; +using System.Diagnostics; using System.Linq; -using MatterHackers.GCodeVisualizer; namespace MatterHackers.MatterControl.PrinterCommunication.Io { public class PauseHandlingStream : GCodeStreamProxy { - object locker = new object(); - private List commandQueue = new List(); protected PrinterMove lastDestination = new PrinterMove(); - public PrinterMove LastDestination { get { return lastDestination; } } - PrinterMove moveLocationAtEndOfPauseCode; - - public override void SetPrinterPosition(PrinterMove position) - { - lastDestination = position; - internalStream.SetPrinterPosition(lastDestination); - } + private List commandQueue = new List(); + private object locker = new object(); + private PrinterMove moveLocationAtEndOfPauseCode; + private Stopwatch timeSinceLastEndstopRead = new Stopwatch(); public PauseHandlingStream(GCodeStream internalStream) : base(internalStream) { } + public enum PauseReason { UserRequested, PauseLayerReached, GCodeRequest, FillamentRunout } + + public PrinterMove LastDestination { get { return lastDestination; } } + public void Add(string line) { // lock queue @@ -65,37 +63,25 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io } } - private void InjectPauseGCode(string codeToInject) + public void DoPause(PauseReason pauseReason) { - codeToInject = GCodeProcessing.ReplaceMacroValues(codeToInject); - - codeToInject = codeToInject.Replace("\\n", "\n"); - string[] lines = codeToInject.Split('\n'); - - for (int i = 0; i < lines.Length; i++) + var pcc = PrinterConnectionAndCommunication.Instance; + switch (pauseReason) { - string[] splitOnSemicolon = lines[i].Split(';'); - string trimedLine = splitOnSemicolon[0].Trim().ToUpper(); - if (trimedLine != "") - { - this.Add(trimedLine); - } + case PauseReason.UserRequested: + // do nothing special + break; + + case PauseReason.PauseLayerReached: + case PauseReason.GCodeRequest: + pcc.PauseOnLayer.CallEvents(pcc, new PrintItemWrapperEventArgs(pcc.ActivePrintItem)); + break; + + case PauseReason.FillamentRunout: + pcc.FillamentRunout.CallEvents(pcc, new PrintItemWrapperEventArgs(pcc.ActivePrintItem)); + break; } - } - private bool PauseOnLayer(string layer) - { - int layerNumber; - - if (int.TryParse(layer, out layerNumber) && ActiveSliceSettings.Instance.Helpers.LayerToPauseOn().Contains(layerNumber)) - { - return true; - } - return false; - } - - public void DoPause() - { // Add the pause_gcode to the loadedGCode.GCodeCommandQueue string pauseGCode = ActiveSliceSettings.Instance.GetValue(SettingsKey.pause_gcode); @@ -108,21 +94,6 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io InjectPauseGCode("MH_PAUSE"); } - public void Resume() - { - // first go back to where we were after executing the pause code - Vector3 positionBeforeActualPause = moveLocationAtEndOfPauseCode.position; - InjectPauseGCode("G92 E{0:0.###}".FormatWith(moveLocationAtEndOfPauseCode.extrusion)); - Vector3 ensureAllAxisAreSent = positionBeforeActualPause + new Vector3(.01, .01, .01); - var feedRates = ActiveSliceSettings.Instance.Helpers.ManualMovementSpeeds(); - InjectPauseGCode("G1 X{0:0.###} Y{1:0.###} Z{2:0.###} F{3}".FormatWith(ensureAllAxisAreSent.x, ensureAllAxisAreSent.y, ensureAllAxisAreSent.z, feedRates.x + 1)); - InjectPauseGCode("G1 X{0:0.###} Y{1:0.###} Z{2:0.###} F{3}".FormatWith(positionBeforeActualPause.x, positionBeforeActualPause.y, positionBeforeActualPause.z, feedRates)); - - string resumeGCode = ActiveSliceSettings.Instance.GetValue(SettingsKey.resume_gcode); - InjectPauseGCode(resumeGCode); - InjectPauseGCode("M114"); // make sure we know where we are after this resume code - } - public override string ReadLine() { string lineToSend = null; @@ -145,6 +116,17 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io { return lineToSend; } + + // We got a line from the gcode we are sending check if we should queue a request for fillament runout + if (ActiveSliceSettings.Instance.GetValue(SettingsKey.fillament_runout_endstop) != "None") + { + // request to read the endstop state + if (!timeSinceLastEndstopRead.IsRunning || timeSinceLastEndstopRead.ElapsedMilliseconds > 5000) + { + PrinterConnectionAndCommunication.Instance.SendLineToPrinterNow("M119"); + timeSinceLastEndstopRead.Restart(); + } + } } else { @@ -157,12 +139,18 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io string layerNumber = lineToSend.Split(':')[1]; if (PauseOnLayer(layerNumber)) { - DoPause(); + DoPause(PauseReason.PauseLayerReached); } } - else if (lineToSend.StartsWith("M226") || lineToSend.StartsWith("@pause")) + else if (lineToSend.StartsWith("M226") + || lineToSend.StartsWith("@pause")) { - DoPause(); + DoPause(PauseReason.GCodeRequest); + lineToSend = ""; + } + else if (OutOfFillament()) + { + DoPause(PauseReason.FillamentRunout); lineToSend = ""; } else if (lineToSend == "MH_PAUSE") @@ -187,5 +175,64 @@ namespace MatterHackers.MatterControl.PrinterCommunication.Io return lineToSend; } + + public void Resume() + { + // first go back to where we were after executing the pause code + Vector3 positionBeforeActualPause = moveLocationAtEndOfPauseCode.position; + InjectPauseGCode("G92 E{0:0.###}".FormatWith(moveLocationAtEndOfPauseCode.extrusion)); + Vector3 ensureAllAxisAreSent = positionBeforeActualPause + new Vector3(.01, .01, .01); + var feedRates = ActiveSliceSettings.Instance.Helpers.ManualMovementSpeeds(); + InjectPauseGCode("G1 X{0:0.###} Y{1:0.###} Z{2:0.###} F{3}".FormatWith(ensureAllAxisAreSent.x, ensureAllAxisAreSent.y, ensureAllAxisAreSent.z, feedRates.x + 1)); + InjectPauseGCode("G1 X{0:0.###} Y{1:0.###} Z{2:0.###} F{3}".FormatWith(positionBeforeActualPause.x, positionBeforeActualPause.y, positionBeforeActualPause.z, feedRates)); + + string resumeGCode = ActiveSliceSettings.Instance.GetValue(SettingsKey.resume_gcode); + InjectPauseGCode(resumeGCode); + InjectPauseGCode("M114"); // make sure we know where we are after this resume code + } + + public override void SetPrinterPosition(PrinterMove position) + { + lastDestination = position; + internalStream.SetPrinterPosition(lastDestination); + } + + private void InjectPauseGCode(string codeToInject) + { + codeToInject = GCodeProcessing.ReplaceMacroValues(codeToInject); + + codeToInject = codeToInject.Replace("\\n", "\n"); + string[] lines = codeToInject.Split('\n'); + + for (int i = 0; i < lines.Length; i++) + { + string[] splitOnSemicolon = lines[i].Split(';'); + string trimedLine = splitOnSemicolon[0].Trim().ToUpper(); + if (trimedLine != "") + { + this.Add(trimedLine); + } + } + } + + private bool OutOfFillament() + { + if (ActiveSliceSettings.Instance.GetValue(SettingsKey.fillament_runout_endstop) != "None") + { + } + + return false; + } + + private bool PauseOnLayer(string layer) + { + int layerNumber; + + if (int.TryParse(layer, out layerNumber) && ActiveSliceSettings.Instance.Helpers.LayerToPauseOn().Contains(layerNumber)) + { + return true; + } + return false; + } } } \ No newline at end of file diff --git a/PrinterCommunication/PrinterConnectionAndCommunication.cs b/PrinterCommunication/PrinterConnectionAndCommunication.cs index eca65d3b8..8a1968a46 100644 --- a/PrinterCommunication/PrinterConnectionAndCommunication.cs +++ b/PrinterCommunication/PrinterConnectionAndCommunication.cs @@ -107,6 +107,10 @@ namespace MatterHackers.MatterControl.PrinterCommunication public RootedObjectEventHandler PrintFinished = new RootedObjectEventHandler(); + public RootedObjectEventHandler PauseOnLayer = new RootedObjectEventHandler(); + + public RootedObjectEventHandler FillamentRunout = new RootedObjectEventHandler(); + public RootedObjectEventHandler PrintingStateChanged = new RootedObjectEventHandler(); public RootedObjectEventHandler ReadLine = new RootedObjectEventHandler(); @@ -289,6 +293,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication ReadLineContainsCallBacks.AddCallbackToKey("Heater decoupled", PrinterReportsError); ReadLineContainsCallBacks.AddCallbackToKey("cold extrusion prevented", PrinterReportsError); ReadLineContainsCallBacks.AddCallbackToKey("Error:Thermal Runaway, system stopped!", PrinterReportsError); + ReadLineContainsCallBacks.AddCallbackToKey("Error:Heating failed", PrinterReportsError); // repetier temperature failures ReadLineContainsCallBacks.AddCallbackToKey("dry run mode", PrinterReportsError); @@ -1869,7 +1874,7 @@ namespace MatterHackers.MatterControl.PrinterCommunication return; } - pauseHandlingStream1.DoPause(); + pauseHandlingStream1.DoPause(PauseHandlingStream.PauseReason.UserRequested); } } diff --git a/SlicerConfiguration/Settings/SettingsHelpers.cs b/SlicerConfiguration/Settings/SettingsHelpers.cs index e5e558565..ea2806752 100644 --- a/SlicerConfiguration/Settings/SettingsHelpers.cs +++ b/SlicerConfiguration/Settings/SettingsHelpers.cs @@ -74,6 +74,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string filament_cost = nameof(filament_cost); public const string filament_density = nameof(filament_density); public const string filament_diameter = nameof(filament_diameter); + public const string fillament_runout_endstop = nameof(fillament_runout_endstop); public const string fill_density = nameof(fill_density); public const string fill_thin_gaps = nameof(fill_thin_gaps); public const string first_layer_extrusion_width = nameof(first_layer_extrusion_width); @@ -106,6 +107,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public const string print_leveling_enabled = nameof(print_leveling_enabled); public const string print_leveling_probe_start = nameof(print_leveling_probe_start); public const string print_leveling_required_to_print = nameof(print_leveling_required_to_print); + public const string print_leveling_solution = nameof(print_leveling_solution); public const string printer_name = nameof(printer_name); public const string publish_bed_image = nameof(publish_bed_image); public const string recover_first_layer_speed = nameof(recover_first_layer_speed); diff --git a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs index adc5ff7d1..89c710c8f 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMapingBase.cs @@ -59,13 +59,13 @@ namespace MatterHackers.MatterControl.SlicerConfiguration SettingsKey.com_port, SettingsKey.filament_cost, SettingsKey.filament_density, + SettingsKey.fillament_runout_endstop, SettingsKey.manual_probe_paper_width, SettingsKey.use_g30_for_bed_probe, SettingsKey.pause_gcode, - "print_leveling_method", SettingsKey.print_leveling_probe_start, SettingsKey.print_leveling_required_to_print, - "print_leveling_solution", + SettingsKey.print_leveling_solution, SettingsKey.recover_first_layer_speed, SettingsKey.recover_is_enabled, SettingsKey.recover_position_before_z_home, diff --git a/SlicerConfiguration/SlicerMapping/EngineMappingSlic3r.cs b/SlicerConfiguration/SlicerMapping/EngineMappingSlic3r.cs index 58d48524c..aa7656ea7 100644 --- a/SlicerConfiguration/SlicerMapping/EngineMappingSlic3r.cs +++ b/SlicerConfiguration/SlicerMapping/EngineMappingSlic3r.cs @@ -82,7 +82,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration "wipe_shield_distance", SettingsKey.heat_extruder_before_homing, "extruders_share_temperature", - "print_leveling_method", "solid_shell", "retractWhenChangingIslands", SettingsKey.perimeter_start_end_overlap, diff --git a/StaticData/SliceSettings/Layouts.txt b/StaticData/SliceSettings/Layouts.txt index 41e6b1b2b..b039d9051 100644 --- a/StaticData/SliceSettings/Layouts.txt +++ b/StaticData/SliceSettings/Layouts.txt @@ -311,6 +311,7 @@ Advanced has_power_control enable_network_printing enable_sailfish_communication + fillament_runout_endstop Behavior z_homes_to_max z_can_be_negative @@ -325,7 +326,6 @@ Advanced Print Leveling Machine Settings print_leveling_solution - print_leveling_method print_leveling_required_to_print Probe Settings print_leveling_probe_start diff --git a/StaticData/SliceSettings/Properties.json b/StaticData/SliceSettings/Properties.json index 4ddd1a0e6..27da3714a 100644 --- a/StaticData/SliceSettings/Properties.json +++ b/StaticData/SliceSettings/Properties.json @@ -1145,6 +1145,20 @@ "ReloadUiWhenChanged": true, "RebuildGCodeOnChange": false }, + { + "QuickMenuSettings": [ ], + "SetSettingsOnChange": [ ], + "SlicerConfigName": "fillament_runout_endstop", + "PresentationName": "Fillament Runout Endstop", + "HelpText": "Specifies the endstop (if any) that is used to detect filament runout. Closed state defines filament has runout. If runout is detected the printers pause G-Code is run.", + "DataEditType": "LIST", + "ExtraSettings": "None,X Min,X Max,Y Min,Y Max,Z Min,Z Max", + "ShowAsOverride": true, + "ResetAtEndOfPrint": false, + "DefaultValue": "None", + "ReloadUiWhenChanged": true, + "RebuildGCodeOnChange": false + }, { "QuickMenuSettings": [ ], "SetSettingsOnChange": [ ], diff --git a/StaticData/Translations/Master.txt b/StaticData/Translations/Master.txt index 419560d43..4e6884d5a 100644 --- a/StaticData/Translations/Master.txt +++ b/StaticData/Translations/Master.txt @@ -6037,3 +6037,12 @@ Translated:Note: Be sure the tip of the extruder is clean and the bed is clear. English:Use G30 For Probing Translated:Use G30 For Probing +English:Specifies the endstop (if any) that is used to detect filament runout. Closed state defines filament has runout. If runout is detected the printers pause G-Code is run. +Translated:Specifies the endstop (if any) that is used to detect filament runout. Closed state defines filament has runout. If runout is detected the printers pause G-Code is run. + +English:Fillament Runout Endstop +Translated:Fillament Runout Endstop + +English:Home the printer +Translated:Home the printer +