2018-11-05 11:08:21 -08:00
/ *
2019-02-15 20:25:07 -08:00
Copyright ( c ) 2019 , Lars Brubaker , John Lewin
2018-11-05 11:08:21 -08:00
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
2019-01-18 09:49:38 -08:00
using System.Linq ;
2018-11-05 11:08:21 -08:00
using Markdig.Agg ;
using MatterHackers.Agg ;
using MatterHackers.Agg.UI ;
using MatterHackers.Localizations ;
2019-01-18 09:49:38 -08:00
using MatterHackers.MatterControl.CustomWidgets ;
2018-11-05 11:08:21 -08:00
using MatterHackers.MatterControl.PrinterCommunication ;
using MatterHackers.MatterControl.SlicerConfiguration ;
namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
{
public class UnloadFilamentWizard : PrinterSetupWizard
{
2019-02-05 11:22:22 -08:00
private int extruderIndex ;
2018-11-05 11:08:21 -08:00
2019-02-05 11:22:22 -08:00
public static void Start ( PrinterConfig printer , ThemeConfig theme , int extruderIndex )
2018-11-05 11:08:21 -08:00
{
// turn off print leveling
2019-02-05 11:22:22 -08:00
var levelingContext = new UnloadFilamentWizard ( printer , extruderIndex )
2018-11-05 11:08:21 -08:00
{
WindowTitle = $"{ApplicationController.Instance.ProductName} - " + "Unload Filament Wizard" . Localize ( )
} ;
2019-02-05 11:22:22 -08:00
var loadFilamentWizardWindow = DialogWindow . Show ( new PrinterSetupWizardRootPage ( levelingContext )
2018-11-05 11:08:21 -08:00
{
WindowTitle = levelingContext . WindowTitle
} ) ;
loadFilamentWizardWindow . Closed + = ( s , e ) = >
{
printer . Connection . TurnOffBedAndExtruders ( TurnOff . AfterDelay ) ;
} ;
}
2019-02-05 11:22:22 -08:00
public UnloadFilamentWizard ( PrinterConfig printer , int extruderIndex )
2018-11-05 11:08:21 -08:00
: base ( printer )
{
2019-02-05 11:22:22 -08:00
this . extruderIndex = extruderIndex ;
2018-11-05 11:08:21 -08:00
}
2019-02-15 20:46:07 -08:00
protected override IEnumerator < WizardPage > GetWizardSteps ( )
2018-11-05 11:08:21 -08:00
{
2019-02-07 14:28:22 -08:00
var extruderCount = printer . Settings . GetValue < int > ( SettingsKey . extruder_count ) ;
2019-02-15 08:56:45 -08:00
var levelingStrings = new LevelingStrings ( ) ;
2018-11-05 11:08:21 -08:00
var title = "Unload Material" . Localize ( ) ;
var instructions = "Please select the material you want to unload." . Localize ( ) ;
2019-02-07 14:28:22 -08:00
if ( extruderCount > 1 )
{
instructions = "Please select the material you want to unload from extruder {0}." . Localize ( ) . FormatWith ( extruderIndex + 1 ) ;
}
2018-11-05 11:08:21 -08:00
// select the material
2019-02-07 14:28:22 -08:00
yield return new SelectMaterialPage ( this , title , instructions , "Unload" . Localize ( ) , extruderIndex , false , false ) ;
2018-11-05 11:08:21 -08:00
var theme = ApplicationController . Instance . Theme ;
// wait for extruder to heat
{
2019-02-05 11:22:22 -08:00
var targetHotendTemp = printer . Settings . Helpers . ExtruderTargetTemperature ( extruderIndex ) ;
var temps = new double [ 4 ] ;
temps [ extruderIndex ] = targetHotendTemp ;
2018-11-05 11:08:21 -08:00
yield return new WaitForTempPage (
this ,
"Waiting For Printer To Heat" . Localize ( ) ,
2019-02-05 11:22:22 -08:00
( extruderCount > 1 ? "Waiting for hotend {0} to heat to " . Localize ( ) . FormatWith ( extruderIndex + 1 ) : "Waiting for the hotend to heat to " . Localize ( ) ) + targetHotendTemp + "°C.\n"
2018-11-05 11:08:21 -08:00
+ "This will ensure that filament is able to flow through the nozzle." . Localize ( ) + "\n"
+ "\n"
+ "Warning! The tip of the nozzle will be HOT!" . Localize ( ) + "\n"
+ "Avoid contact with your skin." . Localize ( ) ,
0 ,
2019-02-05 11:22:22 -08:00
temps ) ;
2018-11-05 11:08:21 -08:00
}
// show the unloading filament progress bar
{
2019-02-05 17:40:27 -08:00
int extruderPriorToUnload = printer . Connection . ActiveExtruderIndex ;
2019-02-05 11:22:22 -08:00
2018-11-05 11:08:21 -08:00
RunningInterval runningGCodeCommands = null ;
2019-02-15 20:46:07 -08:00
var unloadingFilamentPage = new WizardPage ( this , "Unloading Filament" . Localize ( ) , "" )
2018-11-05 11:08:21 -08:00
{
2019-02-15 20:25:07 -08:00
PageLoad = ( page ) = >
2018-11-05 11:08:21 -08:00
{
2019-02-15 20:25:07 -08:00
page . NextButton . Enabled = false ;
2018-11-05 11:08:21 -08:00
// add the progress bar
2018-11-06 09:27:25 -08:00
var holder = new FlowLayoutWidget ( )
{
Margin = new BorderDouble ( 3 , 0 , 0 , 10 ) ,
} ;
2018-11-05 11:08:21 -08:00
var progressBar = new ProgressBar ( ( int ) ( 150 * GuiWidget . DeviceScale ) , ( int ) ( 15 * GuiWidget . DeviceScale ) )
{
FillColor = theme . PrimaryAccentColor ,
BorderColor = theme . TextColor ,
BackgroundColor = Color . White ,
2018-11-06 09:27:25 -08:00
VAnchor = VAnchor . Center ,
2018-11-05 11:08:21 -08:00
} ;
var progressBarText = new TextWidget ( "" , pointSize : 10 , textColor : theme . TextColor )
{
AutoExpandBoundsToText = true ,
Margin = new BorderDouble ( 5 , 0 , 0 , 0 ) ,
2018-11-06 09:27:25 -08:00
VAnchor = VAnchor . Center ,
2018-11-05 11:08:21 -08:00
} ;
holder . AddChild ( progressBar ) ;
holder . AddChild ( progressBarText ) ;
2019-02-15 20:25:07 -08:00
page . ContentRow . AddChild ( holder ) ;
2018-11-05 11:08:21 -08:00
2019-02-05 11:22:22 -08:00
if ( extruderCount > 1 )
{
// reset the extruder that was active
printer . Connection . QueueLine ( $"T{extruderIndex}" ) ;
}
// reset the extrusion amount so this is easier to debug
printer . Connection . QueueLine ( "G92 E0" ) ;
2018-11-05 11:08:21 -08:00
// Allow extrusion at any temperature. S0 only works on Marlin S1 works on repetier and marlin
printer . Connection . QueueLine ( "M302 S1" ) ;
2018-11-29 13:41:24 -08:00
// send a dwell to empty out the current move commands
2018-11-05 11:08:21 -08:00
printer . Connection . QueueLine ( "G4 P1" ) ;
// put in a second one to use as a signal for the first being processed
printer . Connection . QueueLine ( "G4 P1" ) ;
// start heating up the extruder
printer . Connection . SetTargetHotendTemperature ( 0 , printer . Settings . GetValue < double > ( SettingsKey . temperature ) ) ;
var loadingSpeedMmPerS = printer . Settings . GetValue < double > ( SettingsKey . load_filament_speed ) ;
var loadLengthMm = Math . Max ( 1 , printer . Settings . GetValue < double > ( SettingsKey . unload_filament_length ) ) ;
var remainingLengthMm = loadLengthMm ;
var maxSingleExtrudeLength = 20 ;
Stopwatch runningTime = null ;
var expectedTimeS = loadLengthMm / loadingSpeedMmPerS ;
// push some out first
var currentE = printer . Connection . CurrentExtruderDestination ;
printer . Connection . QueueLine ( "G1 E{0:0.###} F600" . FormatWith ( currentE + 15 ) ) ;
runningGCodeCommands = UiThread . SetInterval ( ( ) = >
{
if ( printer . Connection . NumQueuedCommands = = 0 )
{
if ( runningTime = = null )
{
runningTime = Stopwatch . StartNew ( ) ;
}
2019-02-05 14:51:38 -08:00
if ( progressBar . RatioComplete < 1
| | remainingLengthMm > = . 001 )
2018-11-05 11:08:21 -08:00
{
var thisExtrude = Math . Min ( remainingLengthMm , maxSingleExtrudeLength ) ;
currentE = printer . Connection . CurrentExtruderDestination ;
printer . Connection . QueueLine ( "G1 E{0:0.###} F{1}" . FormatWith ( currentE - thisExtrude , loadingSpeedMmPerS * 60 ) ) ;
2019-02-05 11:22:22 -08:00
// make sure we wait for this command to finish so we can cancel the unload at any time without delay
printer . Connection . QueueLine ( "G4 P1" ) ;
2018-11-05 11:08:21 -08:00
remainingLengthMm - = thisExtrude ;
var elapsedSeconds = runningTime . Elapsed . TotalSeconds ;
progressBar . RatioComplete = Math . Min ( 1 , elapsedSeconds / expectedTimeS ) ;
progressBarText . Text = $"Unloading Filament: {Math.Max(0, expectedTimeS - elapsedSeconds):0}" ;
}
}
2018-11-13 16:52:23 -08:00
if ( progressBar . RatioComplete = = 1
2018-11-05 11:08:21 -08:00
& & remainingLengthMm < = . 001 )
{
2018-11-13 16:52:23 -08:00
UiThread . ClearInterval ( runningGCodeCommands ) ;
2019-02-15 20:25:07 -08:00
page . NextButton . InvokeClick ( ) ;
2018-11-05 11:08:21 -08:00
}
} ,
. 1 ) ;
} ,
2019-02-15 20:09:48 -08:00
PageClose = ( ) = >
2018-11-05 11:08:21 -08:00
{
2018-11-13 16:52:23 -08:00
UiThread . ClearInterval ( runningGCodeCommands ) ;
2018-11-05 11:08:21 -08:00
}
} ;
unloadingFilamentPage . Closed + = ( s , e ) = >
{
2018-11-13 16:52:23 -08:00
UiThread . ClearInterval ( runningGCodeCommands ) ;
2019-02-05 11:22:22 -08:00
if ( extruderCount > 1 )
{
// reset the extruder that was active
2019-02-05 17:40:27 -08:00
printer . Connection . QueueLine ( $"T{extruderPriorToUnload}" ) ;
2019-02-05 11:22:22 -08:00
}
printer . Connection . QueueLine ( "G92 E0" ) ;
2018-11-05 11:08:21 -08:00
} ;
yield return unloadingFilamentPage ;
}
// put up a success message
2019-02-05 11:22:22 -08:00
yield return new DoneUnloadingPage ( this , extruderIndex ) ;
2019-01-18 09:49:38 -08:00
}
}
2019-02-15 20:46:07 -08:00
public class DoneUnloadingPage : WizardPage
2019-01-18 09:49:38 -08:00
{
2019-02-05 11:22:22 -08:00
public DoneUnloadingPage ( PrinterSetupWizard setupWizard , int extruderIndex )
2019-01-18 09:49:38 -08:00
: base ( setupWizard , "Success" . Localize ( ) , "Success!\n\nYour filament should now be unloaded" . Localize ( ) )
{
var loadFilamentButton = new TextButton ( "Load Filament" . Localize ( ) , theme )
2018-11-05 11:08:21 -08:00
{
2019-01-18 09:49:38 -08:00
Name = "Load Filament" ,
BackgroundColor = theme . MinimalShade ,
} ;
loadFilamentButton . Click + = ( s , e ) = >
{
loadFilamentButton . Parents < SystemWindow > ( ) . First ( ) . Close ( ) ;
2019-02-07 14:28:22 -08:00
LoadFilamentWizard . Start ( printer , theme , extruderIndex , false ) ;
2018-11-05 11:08:21 -08:00
} ;
2019-01-18 12:13:31 -08:00
theme . ApplyPrimaryActionStyle ( loadFilamentButton ) ;
2018-11-05 11:08:21 -08:00
2019-01-18 12:13:31 -08:00
this . AddPageAction ( loadFilamentButton ) ;
2019-01-18 09:49:38 -08:00
}
2019-02-15 20:09:48 -08:00
public override void OnLoad ( EventArgs args )
2019-01-18 09:49:38 -08:00
{
2019-02-15 20:09:48 -08:00
this . ShowWizardFinished ( ) ;
base . OnLoad ( args ) ;
2018-11-05 11:08:21 -08:00
}
}
}