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));
        }
Example #4
0
        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));
        }