public static void Start(PrinterConfig printer, ThemeConfig theme) { // turn off print leveling PrintLevelingStream.AllowLeveling = false; var levelingContext = new ProbeCalibrationWizard(printer) { WindowTitle = $"{ApplicationController.Instance.ProductName} - " + "Probe Calibration Wizard".Localize() }; var probeCalibrationWizardWindow = DialogWindow.Show(new LevelingWizardRootPage(levelingContext) { WindowTitle = levelingContext.WindowTitle }); probeCalibrationWizardWindow.Closed += (s, e) => { // If leveling was on when we started, make sure it is on when we are done. PrintLevelingStream.AllowLeveling = true; probeCalibrationWizardWindow = null; // make sure we raise the probe on close if (printer.Settings.GetValue <bool>(SettingsKey.has_z_probe) && printer.Settings.GetValue <bool>(SettingsKey.use_z_probe) && printer.Settings.GetValue <bool>(SettingsKey.has_z_servo)) { // make sure the servo is retracted var servoRetract = printer.Settings.GetValue <double>(SettingsKey.z_servo_retracted_angle); printer.Connection.QueueLine($"M280 P0 S{servoRetract}"); } }; }
protected override IEnumerator <PrinterSetupWizardPage> GetWizardSteps() { var probePositions = new List <ProbePosition>(levelingPlan.ProbeCount); for (int j = 0; j < levelingPlan.ProbeCount; j++) { probePositions.Add(new ProbePosition()); } var levelingStrings = new LevelingStrings(printer.Settings); // If no leveling data has been calculated bool showWelcomeScreen = printer.Settings.Helpers.GetPrintLevelingData().SampledPositions.Count == 0 && !ProbeCalibrationWizard.UsingZProbe(printer); if (showWelcomeScreen) { yield return(new PrinterSetupWizardPage( this, levelingStrings.InitialPrinterSetupStepText, string.Format( "{0}\n\n{1}", "Congratulations on connecting to your printer. Before starting your first print we need to run a simple calibration procedure.".Localize(), "The next few screens will walk your through calibrating your printer.".Localize()))); } bool hasHeatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed); bool useZProbe = printer.Settings.Helpers.UseZProbe(); int zProbeSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); var secondsPerManualSpot = 10 * 3; var secondsPerAutomaticSpot = 3 * zProbeSamples; var secondsToCompleteWizard = levelingPlan.ProbeCount * (useZProbe ? secondsPerAutomaticSpot : secondsPerManualSpot); secondsToCompleteWizard += (hasHeatedBed ? 60 * 3 : 0); yield return(new PrinterSetupWizardPage( this, "Print Leveling Overview".Localize(), levelingStrings.WelcomeText(levelingPlan.ProbeCount, (int)Math.Round(secondsToCompleteWizard / 60.0)))); yield return(new HomePrinterPage( this, "Homing The Printer".Localize(), levelingStrings.HomingPageInstructions(useZProbe, hasHeatedBed), useZProbe)); // figure out the heating requirements double targetBedTemp = 0; double targetHotendTemp = 0; if (hasHeatedBed) { targetBedTemp = printer.Settings.GetValue <double>(SettingsKey.bed_temperature); } if (!useZProbe) { targetHotendTemp = printer.Settings.Helpers.ExtruderTemperature(0); } if (targetBedTemp > 0 || targetHotendTemp > 0) { string heatingInstructions = ""; if (targetBedTemp > 0 && targetHotendTemp > 0) { // heating both the bed and the hotend heatingInstructions = "Waiting for the bed to heat to ".Localize() + targetBedTemp + "°C\n" + "and the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n" + "\n" + "This will improve the accuracy of print leveling ".Localize() + "and ensure that no filament is stuck to your nozzle.".Localize() + "\n" + "\n" + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n" + "Avoid contact with your skin.".Localize(); } else if (targetBedTemp > 0) { // only heating the bed heatingInstructions = "Waiting for the bed to heat to ".Localize() + targetBedTemp + "°C.\n" + "This will improve the accuracy of print leveling.".Localize(); } else // targetHotendTemp > 0 { // only heating the hotend heatingInstructions += "Waiting for the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n" + "This will ensure that no filament is stuck to your nozzle.".Localize() + "\n" + "\n" + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n" + "Avoid contact with your skin.".Localize(); } yield return(new WaitForTempPage( this, "Waiting For Printer To Heat".Localize(), heatingInstructions, targetBedTemp, targetHotendTemp)); } double bedRadius = Math.Min(printer.Settings.GetValue <Vector2>(SettingsKey.bed_size).X, printer.Settings.GetValue <Vector2>(SettingsKey.bed_size).Y) / 2; double startProbeHeight = printer.Settings.GetValue <double>(SettingsKey.print_leveling_probe_start); int i = 0; foreach (var goalProbePosition in levelingPlan.GetPrintLevelPositionToSample()) { var validProbePosition = EnsureInPrintBounds(printer.Settings, goalProbePosition); if (printer.Settings.Helpers.UseZProbe()) { yield return(new AutoProbeFeedback( this, new Vector3(validProbePosition, startProbeHeight), string.Format( "{0} {1} {2} - {3}", $"{"Step".Localize()} {i + 1} {"of".Localize()} {levelingPlan.ProbeCount}:", "Position".Localize(), i + 1, "Auto Calibrate".Localize()), probePositions, i)); } else { yield return(new GetCoarseBedHeight( this, new Vector3(validProbePosition, startProbeHeight), string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "Low Precision".Localize()), probePositions, i, levelingStrings)); yield return(new GetFineBedHeight( this, string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "Medium Precision".Localize()), probePositions, i, levelingStrings)); yield return(new GetUltraFineBedHeight( this, string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "High Precision".Localize()), probePositions, i, levelingStrings)); } i++; } yield return(new LastPageInstructions( this, "Print Leveling Wizard".Localize(), useZProbe, probePositions)); }
public static bool NeedsToBeRun(PrinterConfig printer) { PrintLevelingData levelingData = printer.Settings.Helpers.GetPrintLevelingData(); var required = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_required_to_print); if (required && levelingData == null) { // need but don't have data return(true); } var enabled = printer.Settings.GetValue <bool>(SettingsKey.print_leveling_enabled); // check if leveling is turned on if (required && !enabled) { // need but not turned on return(true); } if (!required && !enabled) { return(false); } // check that there are no duplicate points var positionCounts = from x in levelingData.SampledPositions group x by x into g let count = g.Count() orderby count descending select new { Value = g.Key, Count = count }; foreach (var x in positionCounts) { if (x.Count > 1) { return(true); } } // check that the solution last measured is the currently selected solution if (printer.Settings.GetValue <LevelingSystem>(SettingsKey.print_leveling_solution) != levelingData.LevelingSystem) { return(true); } // check that the bed temperature at probe time was close enough to the current print bed temp double requiredLevelingTemp = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed) ? printer.Settings.GetValue <double>(SettingsKey.bed_temperature) : 0; // check that it is within 10 degrees if (Math.Abs(requiredLevelingTemp - levelingData.BedTemperature) > 10) { return(true); } // check that the number of points sampled is correct for the solution switch (levelingData.LevelingSystem) { case LevelingSystem.Probe3Points: if (levelingData.SampledPositions.Count != 3) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe7PointRadial: if (levelingData.SampledPositions.Count != 7) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe13PointRadial: if (levelingData.SampledPositions.Count != 13) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe100PointRadial: if (levelingData.SampledPositions.Count != 100) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe3x3Mesh: if (levelingData.SampledPositions.Count != 9) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe5x5Mesh: if (levelingData.SampledPositions.Count != 25) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.Probe10x10Mesh: if (levelingData.SampledPositions.Count != 100) // different criteria for what is not initialized { return(true); } break; case LevelingSystem.ProbeCustom: if (levelingData.SampledPositions.Count != LevelWizardCustom.ParseLevelingSamplePoints(printer).Count) { return(true); } break; default: throw new NotImplementedException(); } // All the above need to pass, as well as all rules defined in ProbeCalibrationWizard - any variance and we need to re-run return(ProbeCalibrationWizard.NeedsToBeRun(printer)); }
protected override IEnumerator <WizardPage> GetPages() { var levelingStrings = new LevelingStrings(); // If no leveling data has been calculated bool showWelcomeScreen = printer.Settings.Helpers.PrintLevelingData.SampledPositions.Count == 0 && !ProbeCalibrationWizard.UsingZProbe(printer); if (showWelcomeScreen) { yield return(new WizardPage( this, "Initial Printer Setup".Localize(), string.Format( "{0}\n\n{1}", "Congratulations on connecting to your printer. Before starting your first print we need to run a simple calibration procedure.".Localize(), "The next few screens will walk your through calibrating your printer.".Localize())) { WindowTitle = Title }); } // Switch to raw mode and construct leveling structures this.Initialize(); // var probePositions = new List<ProbePosition>(Enumerable.Range(0, levelingPlan.ProbeCount).Select(p => new ProbePosition())); var probePositions = new List <ProbePosition>(levelingPlan.ProbeCount); for (int j = 0; j < levelingPlan.ProbeCount; j++) { probePositions.Add(new ProbePosition()); } bool hasHeatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed); bool useZProbe = printer.Settings.Helpers.UseZProbe(); int zProbeSamples = printer.Settings.GetValue <int>(SettingsKey.z_probe_samples); // Build welcome text for Print Leveling Overview page string buildWelcomeText() { var secondsPerManualSpot = 10 * 3; var secondsPerAutomaticSpot = 3 * zProbeSamples; var secondsToCompleteWizard = levelingPlan.ProbeCount * (useZProbe ? secondsPerAutomaticSpot : secondsPerManualSpot); secondsToCompleteWizard += (hasHeatedBed ? 60 * 3 : 0); int numberOfSteps = levelingPlan.ProbeCount; int numberOfMinutes = (int)Math.Round(secondsToCompleteWizard / 60.0); if (hasHeatedBed) { return("{0}\n\n\t• {1}\n\t• {2}\n\t• {3}\n\t• {4}\n\t• {5}\n\n{6}\n\n{7}".FormatWith( "Welcome to the print leveling wizard. Here is a quick overview on what we are going to do.".Localize(), "Select the material you are printing".Localize(), "Home the printer".Localize(), "Heat the bed".Localize(), "Sample the bed at {0} points".Localize().FormatWith(numberOfSteps), "Turn auto leveling on".Localize(), "We should be done in approximately {0} minutes.".Localize().FormatWith(numberOfMinutes), "Click 'Next' to continue.".Localize())); } else { return("{0}\n\n\t• {1}\n\t• {2}\n\t• {3}\n\n{4}\n\n{5}".FormatWith( "Welcome to the print leveling wizard. Here is a quick overview on what we are going to do.".Localize(), "Home the printer".Localize(), "Sample the bed at {0} points".Localize().FormatWith(numberOfSteps), "Turn auto leveling on".Localize(), "We should be done in approximately {0} minutes.".Localize().FormatWith(numberOfMinutes), "Click 'Next' to continue.".Localize())); } } yield return(new WizardPage( this, "Print Leveling Overview".Localize(), buildWelcomeText()) { WindowTitle = Title }); yield return(new HomePrinterPage( this, "Homing The Printer".Localize(), levelingStrings.HomingPageInstructions(useZProbe, hasHeatedBed), useZProbe)); // if there is a level_x_carriage_markdown oem markdown page if (!string.IsNullOrEmpty(printer.Settings.GetValue(SettingsKey.level_x_carriage_markdown))) { yield return(GetLevelXCarriagePage(this, printer)); } // figure out the heating requirements double targetBedTemp = 0; double targetHotendTemp = 0; if (hasHeatedBed) { targetBedTemp = printer.Settings.GetValue <double>(SettingsKey.bed_temperature); } if (!useZProbe) { targetHotendTemp = printer.Settings.Helpers.ExtruderTargetTemperature(0); } if (targetBedTemp > 0 || targetHotendTemp > 0) { string heatingInstructions = ""; if (targetBedTemp > 0 && targetHotendTemp > 0) { // heating both the bed and the hotend heatingInstructions = "Waiting for the bed to heat to ".Localize() + targetBedTemp + "°C\n" + "and the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n" + "\n" + "This will improve the accuracy of print leveling ".Localize() + "and ensure that no filament is stuck to your nozzle.".Localize() + "\n" + "\n" + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n" + "Avoid contact with your skin.".Localize(); } else if (targetBedTemp > 0) { // only heating the bed heatingInstructions = "Waiting for the bed to heat to ".Localize() + targetBedTemp + "°C.\n" + "This will improve the accuracy of print leveling.".Localize(); } else // targetHotendTemp > 0 { // only heating the hotend heatingInstructions += "Waiting for the hotend to heat to ".Localize() + targetHotendTemp + "°C.\n" + "This will ensure that no filament is stuck to your nozzle.".Localize() + "\n" + "\n" + "Warning! The tip of the nozzle will be HOT!".Localize() + "\n" + "Avoid contact with your skin.".Localize(); } yield return(new WaitForTempPage( this, "Waiting For Printer To Heat".Localize(), heatingInstructions, targetBedTemp, new double[] { targetHotendTemp })); } double bedRadius = Math.Min(printer.Settings.GetValue <Vector2>(SettingsKey.bed_size).X, printer.Settings.GetValue <Vector2>(SettingsKey.bed_size).Y) / 2; double startProbeHeight = printer.Settings.GetValue <double>(SettingsKey.print_leveling_probe_start); int i = 0; var probePoints = levelingPlan.GetPrintLevelPositionToSample().ToList(); AutoProbePage autoProbePage = null; if (printer.Settings.Helpers.UseZProbe()) { autoProbePage = new AutoProbePage(this, printer, "Bed Detection", probePoints, probePositions); yield return(autoProbePage); } else { foreach (var goalProbePoint in probePoints) { if (wizardExited) { // Make sure when the wizard is done we turn off the bed heating printer.Connection.TurnOffBedAndExtruders(TurnOff.AfterDelay); if (printer.Settings.GetValue <bool>(SettingsKey.z_homes_to_max)) { printer.Connection.HomeAxis(PrinterConnection.Axis.XYZ); } yield break; } var validProbePosition = EnsureInPrintBounds(printer, goalProbePoint); { yield return(new GetCoarseBedHeight( this, new Vector3(validProbePosition, startProbeHeight), string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "Low Precision".Localize()), probePositions, i, levelingStrings)); yield return(new GetFineBedHeight( this, string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "Medium Precision".Localize()), probePositions, i, levelingStrings)); yield return(new GetUltraFineBedHeight( this, string.Format( "{0} {1} {2} - {3}", levelingStrings.GetStepString(levelingPlan.TotalSteps), "Position".Localize(), i + 1, "High Precision".Localize()), probePositions, i, levelingStrings)); } i++; } } // if we are not using a z-probe, reset the baby stepping at the successful conclusion of leveling if (!printer.Settings.GetValue <bool>(SettingsKey.use_z_probe)) { // clear the baby stepping so we don't save the old values babySteppingValue = 0; } yield return(new LastPageInstructions( this, "Print Leveling Wizard".Localize(), useZProbe, probePositions)); }