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 ;
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
{
2020-08-30 08:29:15 -07:00
private readonly int extruderIndex ;
2018-11-05 11:08:21 -08:00
2019-02-16 00:59:46 -08:00
public UnloadFilamentWizard ( PrinterConfig printer , int extruderIndex )
: base ( printer )
{
2019-03-19 18:14:03 -07:00
this . Title = "Unload Filament" . Localize ( ) ;
2019-02-16 13:55:27 -08:00
this . extruderIndex = extruderIndex ;
2019-02-16 09:11:20 -08:00
}
2019-03-20 15:38:54 -07:00
public override bool SetupRequired = > false ;
2019-03-20 17:05:31 -07:00
public override bool Visible = > true ;
public override bool Enabled = > true ;
2019-02-16 09:11:20 -08:00
public override void Dispose ( )
{
printer . Connection . TurnOffBedAndExtruders ( TurnOff . AfterDelay ) ;
2018-11-05 11:08:21 -08:00
}
2019-03-20 13:19:55 -07:00
protected override IEnumerator < WizardPage > GetPages ( )
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-16 00:44:35 -08:00
yield return new SelectMaterialPage ( this , title , instructions , "Unload" . Localize ( ) , extruderIndex , false , false )
{
2019-03-19 18:14:03 -07:00
WindowTitle = Title
2019-02-16 00:44:35 -08:00
} ;
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
}
2020-08-30 08:29:15 -07:00
var extrusionMultiplierStream = printer . Connection . ExtrusionMultiplierStream ;
var oldExtrusionMultiplier = extrusionMultiplierStream . ExtrusionRatio ;
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
{
2020-08-30 08:29:15 -07:00
extrusionMultiplierStream . ExtrusionRatio = 1 ;
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 ) ,
} ;
2020-08-05 10:07:40 -07:00
var progressBar = new ProgressBar ( 150 * GuiWidget . DeviceScale , 15 * GuiWidget . DeviceScale )
2018-11-05 11:08:21 -08:00
{
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
2019-02-22 10:08:46 -08:00
if ( extruderIndex = = 0 )
{
printer . Connection . SetTargetHotendTemperature ( 0 , printer . Settings . GetValue < double > ( SettingsKey . temperature ) ) ;
}
else
{
printer . Connection . SetTargetHotendTemperature ( extruderIndex , printer . Settings . GetValue < double > ( SettingsKey . temperature + extruderIndex . ToString ( ) ) ) ;
}
2018-11-05 11:08:21 -08:00
var loadingSpeedMmPerS = printer . Settings . GetValue < double > ( SettingsKey . load_filament_speed ) ;
2019-04-27 13:38:24 -07:00
var unloadLengthMm = Math . Max ( 1 , printer . Settings . GetValue < double > ( SettingsKey . unload_filament_length ) ) ;
var remainingLengthMm = unloadLengthMm ;
2018-11-05 11:08:21 -08:00
var maxSingleExtrudeLength = 20 ;
Stopwatch runningTime = null ;
2019-04-27 13:38:24 -07:00
var expectedTimeS = unloadLengthMm / loadingSpeedMmPerS ;
2018-11-05 11:08:21 -08:00
2019-04-27 13:38:24 -07:00
double currentE = 0 ;
2018-11-05 11:08:21 -08:00
runningGCodeCommands = UiThread . SetInterval ( ( ) = >
{
2019-04-27 13:38:24 -07:00
// wait until the printer has processed all our commands (including G92)
2018-11-05 11:08:21 -08:00
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
{
2020-08-30 08:29:15 -07:00
extrusionMultiplierStream . ExtrusionRatio = oldExtrusionMultiplier ;
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
}
2020-08-30 08:29:15 -07:00
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
}
2020-08-30 08:29:15 -07:00
public class DoneUnloadingPage : WizardPage
2019-01-18 09:49:38 -08:00
{
2020-08-30 08:29:15 -07:00
public DoneUnloadingPage ( PrinterSetupWizard setupWizard , int extruderIndex )
: base ( setupWizard , "Filament Unloaded" . Localize ( ) , "Success!\n\nYour filament should now be unloaded" . Localize ( ) )
2019-01-18 09:49:38 -08:00
{
2020-08-30 08:29:15 -07:00
var loadFilamentButton = new TextButton ( "Load Filament" . Localize ( ) , theme )
{
Name = "Load Filament" ,
BackgroundColor = theme . MinimalShade ,
} ;
loadFilamentButton . Click + = ( s , e ) = >
{
this . DialogWindow . ClosePage ( ) ;
2019-02-16 13:55:27 -08:00
2020-08-30 08:29:15 -07:00
DialogWindow . Show (
new LoadFilamentWizard ( printer , extruderIndex , showAlreadyLoadedButton : false ) ) ;
} ;
2018-11-05 11:08:21 -08:00
2020-08-30 08:29:15 -07:00
this . AcceptButton = loadFilamentButton ;
this . AddPageAction ( loadFilamentButton ) ;
}
2019-01-18 09:49:38 -08:00
2020-08-30 08:29:15 -07:00
public override void OnLoad ( EventArgs args )
{
this . ShowWizardFinished ( ) ;
base . OnLoad ( args ) ;
}
2018-11-05 11:08:21 -08:00
}
}
}