Extruders beyond 0 only have temperature
Removed ability to set material for extruders other than the first added settings for extruder 1-4 temp Refactored emulator (move classes to new files) Made the emulator support multiple extruders
This commit is contained in:
parent
d8089d8f7b
commit
ab2fa6e910
15 changed files with 376 additions and 249 deletions
|
|
@ -190,6 +190,14 @@ namespace MatterHackers.MatterControl.ActionBar
|
|||
protected override int ActualTemperature => (int)printer.Connection.GetActualHotendTemperature(hotendIndex);
|
||||
protected override int TargetTemperature => (int)printer.Connection.GetTargetHotendTemperature(hotendIndex);
|
||||
|
||||
string TemperatureKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return "temperature" + ((hotendIndex > 0 && hotendIndex < 4) ? hotendIndex.ToString() : "");
|
||||
}
|
||||
}
|
||||
|
||||
protected override GuiWidget GetPopupContent()
|
||||
{
|
||||
var widget = new IgnoredPopupWidget()
|
||||
|
|
@ -237,7 +245,7 @@ namespace MatterHackers.MatterControl.ActionBar
|
|||
int tabIndex = 0;
|
||||
var settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All);
|
||||
// TODO: make this be for the correct extruder
|
||||
var settingsData = SliceSettingsOrganizer.Instance.GetSettingsData(SettingsKey.temperature);
|
||||
var settingsData = SliceSettingsOrganizer.Instance.GetSettingsData(TemperatureKey);
|
||||
var row = SliceSettingsWidget.CreateItemRow(settingsData, settingsContext, printer, Color.Black, ref tabIndex);
|
||||
|
||||
container.AddChild(row);
|
||||
|
|
@ -271,14 +279,16 @@ namespace MatterHackers.MatterControl.ActionBar
|
|||
{
|
||||
if (e is StringEventArgs stringEvent)
|
||||
{
|
||||
var temp = printer.Settings.Helpers.ExtruderTemperature(hotendIndex);
|
||||
valueField.Value = temp;
|
||||
graph.GoalValue = temp;
|
||||
settingsRow.UpdateStyle();
|
||||
if (stringEvent.Data == SettingsKey.temperature
|
||||
&& heatToggle.Checked)
|
||||
if (stringEvent.Data == TemperatureKey)
|
||||
{
|
||||
SetTargetTemperature(temp);
|
||||
var temp = printer.Settings.Helpers.ExtruderTemperature(hotendIndex);
|
||||
valueField.Value = temp;
|
||||
graph.GoalValue = temp;
|
||||
settingsRow.UpdateStyle();
|
||||
if (heatToggle.Checked)
|
||||
{
|
||||
SetTargetTemperature(temp);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, ref unregisterEvents);
|
||||
|
|
@ -286,36 +296,43 @@ namespace MatterHackers.MatterControl.ActionBar
|
|||
UiThread.RunOnIdle(fillGraph);
|
||||
container.AddChild(graph);
|
||||
|
||||
// put in the material selector
|
||||
var presetsSelector = new PresetSelectorWidget(printer, string.Format($"{"Material".Localize()} {hotendIndex + 1}"), Color.Transparent, NamedSettingsLayers.Material, hotendIndex, true)
|
||||
if (hotendIndex == 0)
|
||||
{
|
||||
Margin = 0,
|
||||
BackgroundColor = Color.Transparent,
|
||||
HAnchor = HAnchor.Absolute,
|
||||
Width = 150
|
||||
};
|
||||
// put in the material selector
|
||||
var presetsSelector = new PresetSelectorWidget(printer, "Material".Localize(), Color.Transparent, NamedSettingsLayers.Material, true)
|
||||
{
|
||||
Margin = 0,
|
||||
BackgroundColor = Color.Transparent,
|
||||
HAnchor = HAnchor.Absolute,
|
||||
Width = 150
|
||||
};
|
||||
|
||||
presetsSelector.DropDownList.Name = "Hotend Preset Selector";
|
||||
presetsSelector.DropDownList.Name = "Hotend Preset Selector";
|
||||
|
||||
this.Width = 150;
|
||||
this.Width = 150;
|
||||
|
||||
// HACK: remove undesired item
|
||||
var label = presetsSelector.Children<TextWidget>().FirstOrDefault();
|
||||
label.Close();
|
||||
// HACK: remove undesired item
|
||||
var label = presetsSelector.Children<TextWidget>().FirstOrDefault();
|
||||
label.Close();
|
||||
|
||||
var pulldownContainer = presetsSelector.FindNamedChildRecursive("Preset Pulldown Container");
|
||||
if (pulldownContainer != null)
|
||||
{
|
||||
pulldownContainer.Padding = 0;
|
||||
var pulldownContainer = presetsSelector.FindNamedChildRecursive("Preset Pulldown Container");
|
||||
if (pulldownContainer != null)
|
||||
{
|
||||
pulldownContainer.Padding = 0;
|
||||
}
|
||||
|
||||
var dropList = presetsSelector.FindNamedChildRecursive("Material") as DropDownList;
|
||||
if (dropList != null)
|
||||
{
|
||||
dropList.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
container.AddChild(new SettingsItem("Material".Localize(), presetsSelector, enforceGutter: false));
|
||||
}
|
||||
|
||||
var dropList = presetsSelector.FindNamedChildRecursive("Material") as DropDownList;
|
||||
if (dropList != null)
|
||||
else // put in a temperature selector for the correct material
|
||||
{
|
||||
dropList.TextColor = Color.Black;
|
||||
}
|
||||
|
||||
container.AddChild(new SettingsItem("Material".Localize(), presetsSelector, enforceGutter: false));
|
||||
}
|
||||
|
||||
// put in the actual extruder controls
|
||||
bool shareTemp = printer.Settings.GetValue<bool>(SettingsKey.extruders_share_temperature);
|
||||
|
|
|
|||
|
|
@ -54,8 +54,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage.PrintLeveling
|
|||
public SelectMaterialPage(PrinterConfig printer, string pageDescription, string instructionsText)
|
||||
: base(printer, pageDescription, instructionsText)
|
||||
{
|
||||
int extruderIndex = 0;
|
||||
var materialSelector = new PresetSelectorWidget(printer, string.Format($"{"Material".Localize()} {extruderIndex + 1}"), Color.Transparent, NamedSettingsLayers.Material, extruderIndex);
|
||||
var materialSelector = new PresetSelectorWidget(printer, "Material".Localize(), Color.Transparent, NamedSettingsLayers.Material);
|
||||
materialSelector.BackgroundColor = Color.Transparent;
|
||||
materialSelector.Margin = new BorderDouble(0, 0, 0, 15);
|
||||
topToBottomControls.AddChild(materialSelector);
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ namespace MatterHackers.MatterControl.PrinterControls
|
|||
|
||||
if (macroData.showMaterialSelector)
|
||||
{
|
||||
int extruderIndex = 0;
|
||||
var materialSelector = new PresetSelectorWidget(printer, string.Format($"{"Material".Localize()} {extruderIndex + 1}"), Color.Transparent, NamedSettingsLayers.Material, extruderIndex);
|
||||
var materialSelector = new PresetSelectorWidget(printer, "Material".Localize(), Color.Transparent, NamedSettingsLayers.Material);
|
||||
materialSelector.BackgroundColor = Color.Transparent;
|
||||
materialSelector.Margin = new BorderDouble(0, 0, 0, 15);
|
||||
contentRow.AddChild(materialSelector);
|
||||
|
|
|
|||
|
|
@ -50,18 +50,11 @@ namespace MatterHackers.PrinterEmulator
|
|||
|
||||
private int recievedCount = 0;
|
||||
|
||||
// Instance reference allows test to access the most recently initialized emulator
|
||||
public static Emulator Instance { get; private set; }
|
||||
|
||||
// Dictionary of command and response callback
|
||||
private Dictionary<string, Func<string, string>> responses;
|
||||
|
||||
private bool shuttingDown = false;
|
||||
|
||||
public Heater HeatedBed { get; } = new Heater("HeatedBed") { CurrentTemperature = 26 };
|
||||
|
||||
public Heater Hotend { get; } = new Heater("Hotend1") { CurrentTemperature = 27 };
|
||||
|
||||
public Emulator()
|
||||
{
|
||||
Emulator.Instance = this;
|
||||
|
|
@ -86,29 +79,38 @@ namespace MatterHackers.PrinterEmulator
|
|||
{ "M20", ListSdCard },
|
||||
{ "M21", InitSdCard },
|
||||
{ "N", ParseChecksumLine },
|
||||
{ "T", SetExtruderIndex },
|
||||
};
|
||||
}
|
||||
|
||||
public event EventHandler ZPositionChanged;
|
||||
public event EventHandler ExtruderIndexChanged;
|
||||
|
||||
public event EventHandler ExtruderTemperatureChanged;
|
||||
|
||||
public event EventHandler FanSpeedChanged;
|
||||
|
||||
public double EPosition { get; private set; }
|
||||
public event EventHandler ZPositionChanged;
|
||||
|
||||
// Instance reference allows test to access the most recently initialized emulator
|
||||
public static Emulator Instance { get; private set; }
|
||||
|
||||
public Heater CurrentExtruder { get { return Extruders[ExtruderIndex]; } }
|
||||
public int ExtruderIndex { get; private set; }
|
||||
|
||||
public List<Heater> Extruders { get; private set; } = new List<Heater>()
|
||||
{
|
||||
new Heater("Hotend1") { CurrentTemperature = 27 }
|
||||
};
|
||||
|
||||
public double ExtruderGoalTemperature => this.Hotend.TargetTemperature;
|
||||
public double FanSpeed { get; private set; }
|
||||
|
||||
public bool HasHeatedBed { get; set; } = true;
|
||||
public Heater HeatedBed { get; } = new Heater("HeatedBed") { CurrentTemperature = 26 };
|
||||
public string PortName { get; set; }
|
||||
|
||||
public bool RunSlow { get; set; } = false;
|
||||
|
||||
public bool SimulateLineErrors { get; set; } = false;
|
||||
public double XPosition { get; private set; }
|
||||
|
||||
public bool HasHeatedBed { get; set; } = true;
|
||||
|
||||
public double YPosition { get; private set; }
|
||||
|
||||
public double ZPosition { get; private set; }
|
||||
|
|
@ -219,7 +221,7 @@ namespace MatterHackers.PrinterEmulator
|
|||
public string GetPosition(string command)
|
||||
{
|
||||
// position commands look like this: X:0.00 Y:0.00 Z0.00 E:0.00 Count X: 0.00 Y:0.00 Z:0.00 then an ok on the next line
|
||||
return $"X:{XPosition:0.00} Y: {YPosition:0.00} Z: {ZPosition:0.00} E: {EPosition:0.00} Count X: 0.00 Y: 0.00 Z: 0.00\nok\n";
|
||||
return $"X:{XPosition:0.00} Y: {YPosition:0.00} Z: {ZPosition:0.00} E: {CurrentExtruder.EPosition:0.00} Count X: 0.00 Y: 0.00 Z: 0.00\nok\n";
|
||||
}
|
||||
|
||||
public string ReportMarlinFirmware(string command)
|
||||
|
|
@ -231,9 +233,15 @@ namespace MatterHackers.PrinterEmulator
|
|||
public string ReturnTemp(string command)
|
||||
{
|
||||
// temp commands look like this: ok T:19.4 /0.0 B:0.0 /0.0 @:0 B@:0
|
||||
return $"ok T:{Hotend.CurrentTemperature:0.0} / {Hotend.TargetTemperature:0.0}"
|
||||
// Newline if HeatedBed is disabled otherwise HeatedBed stats
|
||||
+ ((!this.HasHeatedBed) ? "\n" : $" B: {HeatedBed.CurrentTemperature:0.0} / {HeatedBed.TargetTemperature:0.0}\n");
|
||||
string response = "ok";
|
||||
for(int i=0; i<Extruders.Count; i++)
|
||||
{
|
||||
string TString = (Extruders.Count == 1) ? "T" : $"T{i}";
|
||||
response += $" {TString}:{Extruders[i].CurrentTemperature:0.0} / {Extruders[i].TargetTemperature:0.0}";
|
||||
}
|
||||
// Newline if HeatedBed is disabled otherwise HeatedBed stats
|
||||
response += ((!this.HasHeatedBed) ? "\n" : $" B: {HeatedBed.CurrentTemperature:0.0} / {HeatedBed.TargetTemperature:0.0}\n");
|
||||
return response;
|
||||
}
|
||||
|
||||
public string SetFan(string command)
|
||||
|
|
@ -259,7 +267,10 @@ namespace MatterHackers.PrinterEmulator
|
|||
shuttingDown = true;
|
||||
|
||||
HeatedBed.Stop();
|
||||
Hotend.Stop();
|
||||
foreach (var extuder in Extruders)
|
||||
{
|
||||
extuder.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -362,16 +373,54 @@ namespace MatterHackers.PrinterEmulator
|
|||
return "ok\n";
|
||||
}
|
||||
|
||||
private string SetExtruderIndex(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
// T0, T1, T2 are the expected format
|
||||
var tIndex = command.IndexOf('T') + 1;
|
||||
var extruderIndex = command.Substring(tIndex);
|
||||
|
||||
ExtruderIndex = int.Parse(extruderIndex);
|
||||
ExtruderIndexChanged?.Invoke(this, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
return "ok\n";
|
||||
}
|
||||
|
||||
private string SetExtruderTemperature(string command)
|
||||
{
|
||||
try
|
||||
{
|
||||
// M104 S210 or M109 S[temp]
|
||||
var sIndex = command.IndexOf('S') + 1;
|
||||
var spaceIndex = command.IndexOf(" ", sIndex);
|
||||
var temp = (spaceIndex < 0) ? command.Substring(sIndex) : command.Substring(sIndex, spaceIndex - sIndex);
|
||||
|
||||
Hotend.TargetTemperature = int.Parse(temp);
|
||||
double index = 0;
|
||||
GetFirstNumberAfter("T", command, ref index);
|
||||
|
||||
double temp = 0;
|
||||
GetFirstNumberAfter("S", command, ref temp);
|
||||
|
||||
if (index > Extruders.Count - 1)
|
||||
{
|
||||
// increase the number of extruders
|
||||
var newList = new List<Heater>(Extruders.Count + 1);
|
||||
foreach(var extruder in Extruders)
|
||||
{
|
||||
newList.Add(extruder);
|
||||
}
|
||||
|
||||
for(int i=Extruders.Count+1; i<index+2; i++)
|
||||
{
|
||||
newList.Add(new Heater($"Hotend{i}") { CurrentTemperature = 27 });
|
||||
}
|
||||
Extruders = newList;
|
||||
}
|
||||
|
||||
Extruders[(int)index].TargetTemperature = temp;
|
||||
ExtruderTemperatureChanged?.Invoke(this, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
@ -411,7 +460,7 @@ namespace MatterHackers.PrinterEmulator
|
|||
}
|
||||
if (GetFirstNumberAfter("E", command, ref value))
|
||||
{
|
||||
EPosition = value;
|
||||
CurrentExtruder.EPosition = value;
|
||||
}
|
||||
|
||||
return "ok\n";
|
||||
|
|
@ -440,137 +489,17 @@ namespace MatterHackers.PrinterEmulator
|
|||
|
||||
return "ok\n";
|
||||
}
|
||||
|
||||
public class Heater
|
||||
{
|
||||
public static double IncrementAmount = 5.3;
|
||||
|
||||
public static int BounceAmount = (int)IncrementAmount / 2;
|
||||
|
||||
private bool shutdown = false;
|
||||
private double targetTemp;
|
||||
|
||||
private static int loopTimeInMs = 100;
|
||||
|
||||
private bool isDirty = true;
|
||||
public Heater(string identifier)
|
||||
{
|
||||
this.ID = identifier;
|
||||
|
||||
// Maintain temperatures
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.CurrentThread.Name = $"EmulatorHeator{identifier}";
|
||||
|
||||
var random = new Random();
|
||||
|
||||
double requiredLoops = 0;
|
||||
double incrementPerLoop = 0;
|
||||
|
||||
while (!shutdown)
|
||||
{
|
||||
if (this.Enabled
|
||||
&& targetTemp > 0)
|
||||
{
|
||||
if (this.isDirty)
|
||||
{
|
||||
requiredLoops = this.HeatUpTimeInSeconds * 1000 / loopTimeInMs;
|
||||
incrementPerLoop = TargetTemperature / requiredLoops;
|
||||
}
|
||||
|
||||
if (CurrentTemperature < targetTemp)
|
||||
{
|
||||
CurrentTemperature += incrementPerLoop;
|
||||
}
|
||||
else if (CurrentTemperature != targetTemp)
|
||||
{
|
||||
CurrentTemperature = targetTemp;
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(loopTimeInMs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private double _currentTemperature;
|
||||
public double CurrentTemperature
|
||||
{
|
||||
get => _currentTemperature;
|
||||
set
|
||||
{
|
||||
_currentTemperature = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private double _heatupTimeInSeconds = DefaultHeatUpTime;
|
||||
public double HeatUpTimeInSeconds
|
||||
{
|
||||
get => _heatupTimeInSeconds;
|
||||
set
|
||||
{
|
||||
_heatupTimeInSeconds = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _enabled;
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
if (_enabled != value)
|
||||
{
|
||||
_enabled = value;
|
||||
CurrentTemperature = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ID { get; }
|
||||
|
||||
public double TargetTemperature
|
||||
{
|
||||
get => targetTemp;
|
||||
set
|
||||
{
|
||||
if (targetTemp != value)
|
||||
{
|
||||
targetTemp = value;
|
||||
this.Enabled = this.targetTemp > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
shutdown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class EmulatorPortFactory : FrostedSerialPortFactory
|
||||
{
|
||||
override protected string GetDriverType() => "Emulator";
|
||||
public override IFrostedSerialPort Create(string serialPortName) => new Emulator();
|
||||
}
|
||||
|
||||
// EmulatorPort
|
||||
public partial class Emulator : IFrostedSerialPort
|
||||
{
|
||||
public bool RtsEnable { get; set; }
|
||||
public bool DtrEnable { get; set; }
|
||||
public int BaudRate { get; set; }
|
||||
|
||||
private Queue<string> sendQueue = new Queue<string>(new string[] { "Emulator v0.1\n" });
|
||||
private Queue<string> receiveQueue = new Queue<string>();
|
||||
|
||||
private AutoResetEvent receiveResetEvent;
|
||||
|
||||
private object receiveLock = new object();
|
||||
private Queue<string> receiveQueue = new Queue<string>();
|
||||
private AutoResetEvent receiveResetEvent;
|
||||
private object sendLock = new object();
|
||||
private Queue<string> sendQueue = new Queue<string>(new string[] { "Emulator v0.1\n" });
|
||||
public int BaudRate { get; set; }
|
||||
|
||||
public int BytesToRead
|
||||
{
|
||||
|
|
@ -585,10 +514,11 @@ namespace MatterHackers.PrinterEmulator
|
|||
}
|
||||
}
|
||||
|
||||
public int WriteTimeout { get; set; }
|
||||
public int ReadTimeout { get; set; }
|
||||
|
||||
public bool DtrEnable { get; set; }
|
||||
public bool IsOpen { get; private set; }
|
||||
public int ReadTimeout { get; set; }
|
||||
public bool RtsEnable { get; set; }
|
||||
public int WriteTimeout { get; set; }
|
||||
|
||||
public void Close()
|
||||
{
|
||||
|
|
@ -660,7 +590,7 @@ namespace MatterHackers.PrinterEmulator
|
|||
//Thread.Sleep(250);
|
||||
string emulatedResponse = GetCorrectResponse(receivedLine);
|
||||
|
||||
lock(sendLock)
|
||||
lock (sendLock)
|
||||
{
|
||||
sendQueue.Enqueue(emulatedResponse);
|
||||
}
|
||||
|
|
@ -679,9 +609,11 @@ namespace MatterHackers.PrinterEmulator
|
|||
sendQueue.Enqueue(line);
|
||||
}
|
||||
|
||||
public int Read(byte[] buffer, int offset, int count) => throw new NotImplementedException();
|
||||
|
||||
public string ReadExisting()
|
||||
{
|
||||
lock(sendLock)
|
||||
lock (sendLock)
|
||||
{
|
||||
return sendQueue.Dequeue();
|
||||
}
|
||||
|
|
@ -689,7 +621,7 @@ namespace MatterHackers.PrinterEmulator
|
|||
|
||||
public void Write(string receivedLine)
|
||||
{
|
||||
lock(receiveLock)
|
||||
lock (receiveLock)
|
||||
{
|
||||
receiveQueue.Enqueue(receivedLine);
|
||||
}
|
||||
|
|
@ -698,8 +630,6 @@ namespace MatterHackers.PrinterEmulator
|
|||
receiveResetEvent.Set();
|
||||
}
|
||||
|
||||
public int Read(byte[] buffer, int offset, int count) => throw new NotImplementedException();
|
||||
|
||||
public void Write(byte[] buffer, int offset, int count) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
33
PrinterEmulator/EmulatorPortFactory.cs
Normal file
33
PrinterEmulator/EmulatorPortFactory.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2015, Lars Brubaker
|
||||
// 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.
|
||||
|
||||
using MatterHackers.SerialPortCommunication.FrostedSerial;
|
||||
|
||||
namespace MatterHackers.PrinterEmulator
|
||||
{
|
||||
public class EmulatorPortFactory : FrostedSerialPortFactory
|
||||
{
|
||||
override protected string GetDriverType() => "Emulator";
|
||||
public override IFrostedSerialPort Create(string serialPortName) => new Emulator();
|
||||
}
|
||||
}
|
||||
140
PrinterEmulator/Heater.cs
Normal file
140
PrinterEmulator/Heater.cs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
// Copyright (c) 2015, Lars Brubaker
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MatterHackers.PrinterEmulator
|
||||
{
|
||||
public partial class Emulator
|
||||
{
|
||||
public class Heater
|
||||
{
|
||||
public static int BounceAmount = (int)IncrementAmount / 2;
|
||||
public static double IncrementAmount = 5.3;
|
||||
private static int loopTimeInMs = 100;
|
||||
private double _currentTemperature;
|
||||
private bool _enabled;
|
||||
private double _heatupTimeInSeconds = DefaultHeatUpTime;
|
||||
private bool isDirty = true;
|
||||
private bool shutdown = false;
|
||||
private double targetTemp;
|
||||
|
||||
public Heater(string identifier)
|
||||
{
|
||||
this.ID = identifier;
|
||||
|
||||
// Maintain temperatures
|
||||
Task.Run(() =>
|
||||
{
|
||||
Thread.CurrentThread.Name = $"EmulatorHeator{identifier}";
|
||||
|
||||
var random = new Random();
|
||||
|
||||
double requiredLoops = 0;
|
||||
double incrementPerLoop = 0;
|
||||
|
||||
while (!shutdown)
|
||||
{
|
||||
if (this.Enabled
|
||||
&& targetTemp > 0)
|
||||
{
|
||||
if (this.isDirty)
|
||||
{
|
||||
requiredLoops = this.HeatUpTimeInSeconds * 1000 / loopTimeInMs;
|
||||
incrementPerLoop = TargetTemperature / requiredLoops;
|
||||
}
|
||||
|
||||
if (CurrentTemperature < targetTemp)
|
||||
{
|
||||
CurrentTemperature += incrementPerLoop;
|
||||
}
|
||||
else if (CurrentTemperature != targetTemp)
|
||||
{
|
||||
CurrentTemperature = targetTemp;
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(loopTimeInMs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public double CurrentTemperature
|
||||
{
|
||||
get => _currentTemperature;
|
||||
set
|
||||
{
|
||||
_currentTemperature = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Enabled
|
||||
{
|
||||
get => _enabled;
|
||||
set
|
||||
{
|
||||
if (_enabled != value)
|
||||
{
|
||||
_enabled = value;
|
||||
CurrentTemperature = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public double EPosition { get; set; }
|
||||
|
||||
public double HeatUpTimeInSeconds
|
||||
{
|
||||
get => _heatupTimeInSeconds;
|
||||
set
|
||||
{
|
||||
_heatupTimeInSeconds = value;
|
||||
isDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public string ID { get; }
|
||||
|
||||
public double TargetTemperature
|
||||
{
|
||||
get => targetTemp;
|
||||
set
|
||||
{
|
||||
if (targetTemp != value)
|
||||
{
|
||||
targetTemp = value;
|
||||
this.Enabled = this.targetTemp > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
shutdown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,6 +60,8 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Emulator.cs" />
|
||||
<Compile Include="EmulatorPortFactory.cs" />
|
||||
<Compile Include="Heater.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
public DropDownList DropDownList;
|
||||
private string defaultMenuItemText = "- none -".Localize();
|
||||
private Button editButton;
|
||||
private int extruderIndex;
|
||||
private NamedSettingsLayers layerType;
|
||||
private PrinterConfig printer;
|
||||
private GuiWidget pullDownContainer;
|
||||
|
|
@ -53,7 +52,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
private bool whiteBackground;
|
||||
//For multiple materials
|
||||
|
||||
public PresetSelectorWidget(PrinterConfig printer, string label, Color accentColor, NamedSettingsLayers layerType, int extruderIndex, bool whiteBackground = false)
|
||||
public PresetSelectorWidget(PrinterConfig printer, string label, Color accentColor, NamedSettingsLayers layerType, bool whiteBackground = false)
|
||||
: base(FlowDirection.TopToBottom)
|
||||
{
|
||||
this.printer = printer;
|
||||
|
|
@ -72,7 +71,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
}
|
||||
}, ref unregisterEvents);
|
||||
|
||||
this.extruderIndex = extruderIndex;
|
||||
this.layerType = layerType;
|
||||
|
||||
this.HAnchor = HAnchor.Stretch;
|
||||
|
|
@ -126,7 +124,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
{
|
||||
if (ApplicationController.Instance.EditMaterialPresetsWindow == null)
|
||||
{
|
||||
string presetsID = printer.Settings.GetMaterialPresetKey(extruderIndex);
|
||||
string presetsID = printer.Settings.ActiveMaterialKey;
|
||||
if (string.IsNullOrEmpty(presetsID))
|
||||
{
|
||||
return;
|
||||
|
|
@ -139,7 +137,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
LayerType = NamedSettingsLayers.Material,
|
||||
SetAsActive = (materialKey) =>
|
||||
{
|
||||
printer.Settings.SetMaterialPreset(this.extruderIndex, materialKey);
|
||||
printer.Settings.ActiveMaterialKey = materialKey;
|
||||
},
|
||||
DeleteLayer = () =>
|
||||
{
|
||||
|
|
@ -152,7 +150,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
printer.Settings.SetMaterialPreset(extruderIndex, "");
|
||||
printer.Settings.ActiveMaterialKey = "";
|
||||
printer.Settings.MaterialLayers.Remove(layerToEdit);
|
||||
printer.Settings.Save();
|
||||
}
|
||||
|
|
@ -268,7 +266,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
{
|
||||
newLayer.Name = "Material" + printer.Settings.MaterialLayers.Count;
|
||||
printer.Settings.MaterialLayers.Add(newLayer);
|
||||
printer.Settings.SetMaterialPreset(this.extruderIndex, newLayer.LayerID);
|
||||
printer.Settings.ActiveMaterialKey = newLayer.LayerID;
|
||||
}
|
||||
|
||||
RebuildDropDownList();
|
||||
|
|
@ -282,7 +280,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
|
||||
if (layerType == NamedSettingsLayers.Material)
|
||||
{
|
||||
settingsKey = printer.Settings.GetMaterialPresetKey(extruderIndex);
|
||||
settingsKey = printer.Settings.ActiveMaterialKey;
|
||||
|
||||
printer.Settings.MaterialLayers.CollectionChanged += SettingsLayers_CollectionChanged;
|
||||
dropDownList.Closed += (s1, e1) =>
|
||||
|
|
@ -328,12 +326,12 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
|
||||
if (layerType == NamedSettingsLayers.Material)
|
||||
{
|
||||
if (activeSettings.GetMaterialPresetKey(extruderIndex) != item.Value)
|
||||
if (activeSettings.ActiveMaterialKey != item.Value)
|
||||
{
|
||||
// Restore deactivated user overrides by iterating the Material preset we're coming off of
|
||||
activeSettings.RestoreConflictingUserOverrides(activeSettings.MaterialLayer);
|
||||
|
||||
activeSettings.SetMaterialPreset(extruderIndex, item.Value);
|
||||
activeSettings.ActiveMaterialKey = item.Value;
|
||||
|
||||
// Deactivate conflicting user overrides by iterating the Material preset we've just switched to
|
||||
activeSettings.DeactivateConflictingUserOverrides(activeSettings.MaterialLayer);
|
||||
|
|
|
|||
|
|
@ -42,28 +42,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
|
||||
int numberOfHeatedExtruders = printer.Settings.Helpers.NumberOfHotEnds();
|
||||
|
||||
this.AddChild(new PresetSelectorWidget(printer, "Quality".Localize(), Color.Yellow, NamedSettingsLayers.Quality, 0));
|
||||
this.AddChild(new PresetSelectorWidget(printer, "Quality".Localize(), Color.Yellow, NamedSettingsLayers.Quality));
|
||||
this.AddChild(new GuiWidget(8, 0));
|
||||
|
||||
if (numberOfHeatedExtruders > 1)
|
||||
{
|
||||
List<Color> colorList = new List<Color>() { Color.Orange, Color.Violet, Color.YellowGreen };
|
||||
|
||||
for (int i = 0; i < numberOfHeatedExtruders; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
this.AddChild(new GuiWidget(8, 0));
|
||||
}
|
||||
int colorIndex = i % colorList.Count;
|
||||
Color color = colorList[colorIndex];
|
||||
this.AddChild(new PresetSelectorWidget(printer, string.Format("{0} {1}", "Material".Localize(), i + 1), color, NamedSettingsLayers.Material, i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.AddChild(new PresetSelectorWidget(printer, "Material".Localize(), Color.Orange, NamedSettingsLayers.Material, 0));
|
||||
}
|
||||
this.AddChild(new PresetSelectorWidget(printer, "Material".Localize(), Color.Orange, NamedSettingsLayers.Material));
|
||||
|
||||
this.Height = 60 * GuiWidget.DeviceScale;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -291,7 +291,19 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
public string GetMaterialPresetKey(int extruderIndex)
|
||||
public string ActiveMaterialKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetMaterialPresetKey(0);
|
||||
}
|
||||
internal set
|
||||
{
|
||||
SetMaterialPreset(0, value);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetMaterialPresetKey(int extruderIndex)
|
||||
{
|
||||
if (extruderIndex >= MaterialSettingsKeys.Count)
|
||||
{
|
||||
|
|
@ -301,7 +313,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
return MaterialSettingsKeys[extruderIndex];
|
||||
}
|
||||
|
||||
public void SetMaterialPreset(int extruderIndex, string materialKey)
|
||||
private void SetMaterialPreset(int extruderIndex, string materialKey)
|
||||
{
|
||||
if (extruderIndex >= PrinterCommunication.PrinterConnection.MAX_EXTRUDERS)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -130,6 +130,9 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
public const string write_regex = nameof(write_regex);
|
||||
public const string read_regex = nameof(read_regex);
|
||||
public const string temperature = nameof(temperature);
|
||||
public const string temperature1 = nameof(temperature1);
|
||||
public const string temperature2 = nameof(temperature2);
|
||||
public const string temperature3 = nameof(temperature3);
|
||||
public const string enable_retractions = nameof(enable_retractions);
|
||||
public const string use_z_probe = nameof(use_z_probe);
|
||||
public const string z_probe_samples = nameof(z_probe_samples);
|
||||
|
|
@ -196,21 +199,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration
|
|||
// Otherwise, use the SettingsLayers that is bound to this extruder
|
||||
if (extruderIndex < printerSettings.MaterialSettingsKeys.Count)
|
||||
{
|
||||
string materialKey = printerSettings.MaterialSettingsKeys[extruderIndex];
|
||||
PrinterSettingsLayer layer = printerSettings.GetMaterialLayer(materialKey);
|
||||
|
||||
if (layer != null)
|
||||
{
|
||||
string result = "0";
|
||||
if (layer.TryGetValue(SettingsKey.temperature, out result))
|
||||
{
|
||||
double value = 0;
|
||||
if (double.TryParse(result, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return printerSettings.GetValue<double>($"{SettingsKey.temperature}{extruderIndex}");
|
||||
}
|
||||
|
||||
// else return the normal settings cascade
|
||||
|
|
|
|||
|
|
@ -1606,6 +1606,33 @@
|
|||
"ShowIfSet": "!sla_printer",
|
||||
"DefaultValue": "200"
|
||||
},
|
||||
{
|
||||
"SlicerConfigName": "temperature1",
|
||||
"PresentationName": "Extruder 2 Temperature",
|
||||
"HelpText": "The target temperature the extruder will attempt to reach during the print.",
|
||||
"DataEditType": "POSITIVE_DOUBLE",
|
||||
"ExtraSettings": "°C",
|
||||
"ShowIfSet": "!sla_printer",
|
||||
"DefaultValue": "200"
|
||||
},
|
||||
{
|
||||
"SlicerConfigName": "temperature2",
|
||||
"PresentationName": "Extruder 3 Temperature",
|
||||
"HelpText": "The target temperature the extruder will attempt to reach during the print.",
|
||||
"DataEditType": "POSITIVE_DOUBLE",
|
||||
"ExtraSettings": "°C",
|
||||
"ShowIfSet": "!sla_printer",
|
||||
"DefaultValue": "200"
|
||||
},
|
||||
{
|
||||
"SlicerConfigName": "temperature3",
|
||||
"PresentationName": "Extruder 4 Temperature",
|
||||
"HelpText": "The target temperature the extruder will attempt to reach during the print.",
|
||||
"DataEditType": "POSITIVE_DOUBLE",
|
||||
"ExtraSettings": "°C",
|
||||
"ShowIfSet": "!sla_printer",
|
||||
"DefaultValue": "200"
|
||||
},
|
||||
{
|
||||
"SlicerConfigName": "extruder_wipe_temperature",
|
||||
"PresentationName": "Extruder Wipe Temperature",
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.WaitFor(() => fanChangedCount > 0, 15, 500);
|
||||
|
||||
// Assert expected temp targets and fan transitions
|
||||
Assert.AreEqual(0, (int) emulator.Hotend.TargetTemperature, "Unexpected target temperature - MC close should call Connection.Disable->TurnOffBedAndExtruders to shutdown heaters");
|
||||
Assert.AreEqual(0, (int) emulator.CurrentExtruder.TargetTemperature, "Unexpected target temperature - MC close should call Connection.Disable->TurnOffBedAndExtruders to shutdown heaters");
|
||||
Assert.AreEqual(0, (int) emulator.HeatedBed.TargetTemperature, "Unexpected target temperature - MC close should call Connection.Disable->TurnOffBedAndExtruders to shutdown heaters");
|
||||
Assert.AreEqual(1, fanChangedCount, "Unexpected fan speed change count - MC close should call Connection.Disable which shuts down fans via M106");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,21 +195,21 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
// assert the temp changed to a new temp
|
||||
Assert.AreEqual(hipsGoalTemp,(int) tempWidget.Value, "The goal temp should match the material temp");
|
||||
// and the printer heat is off
|
||||
Assert.AreEqual(0, (int) emulator.ExtruderGoalTemperature, "The printer should report the heaters are off");
|
||||
Assert.AreEqual(0, (int) emulator.CurrentExtruder.TargetTemperature, "The printer should report the heaters are off");
|
||||
|
||||
// turn on the heater
|
||||
testRunner.ClickByName("Toggle Heater");
|
||||
testRunner.Delay(2);
|
||||
|
||||
// assert the printer is heating
|
||||
Assert.AreEqual(hipsGoalTemp, (int)emulator.ExtruderGoalTemperature, "The printer should report the expected goal temp");
|
||||
Assert.AreEqual(hipsGoalTemp, (int)emulator.CurrentExtruder.TargetTemperature, "The printer should report the expected goal temp");
|
||||
|
||||
// turn off the heater
|
||||
testRunner.ClickByName("Toggle Heater");
|
||||
testRunner.Delay(2);
|
||||
|
||||
// assert the printer is off
|
||||
Assert.AreEqual(0, (int)emulator.ExtruderGoalTemperature, "The printer should report the heaters are off");
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature, "The printer should report the heaters are off");
|
||||
|
||||
// type in a temp when the heating is off
|
||||
testRunner.ClickByName("Temperature Input");
|
||||
|
|
@ -218,7 +218,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.Delay();
|
||||
|
||||
// assert the printer is off
|
||||
Assert.AreEqual(0, (int)emulator.ExtruderGoalTemperature);
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// and the heat toggle is showing on
|
||||
CheckBox heatToggle = testRunner.GetWidgetByName("Toggle Heater", out _) as CheckBox;
|
||||
|
|
@ -226,14 +226,14 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
|
||||
// turn it on
|
||||
testRunner.ClickByName("Toggle Heater");
|
||||
Assert.AreEqual(110, (int)emulator.ExtruderGoalTemperature);
|
||||
Assert.AreEqual(110, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// adjust when on
|
||||
testRunner.ClickByName("Temperature Input");
|
||||
testRunner.Type("104");
|
||||
testRunner.Type("{Enter}");
|
||||
testRunner.Delay();
|
||||
Assert.AreEqual(104, (int)emulator.ExtruderGoalTemperature);
|
||||
Assert.AreEqual(104, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
|
||||
// type in 0 and have the heater turn off
|
||||
testRunner.ClickByName("Temperature Input");
|
||||
|
|
@ -243,7 +243,7 @@ namespace MatterHackers.MatterControl.Tests.Automation
|
|||
testRunner.Delay();
|
||||
|
||||
// assert the printer is not heating
|
||||
Assert.AreEqual(0, (int)emulator.ExtruderGoalTemperature);
|
||||
Assert.AreEqual(0, (int)emulator.CurrentExtruder.TargetTemperature);
|
||||
// and the on toggle is showing off
|
||||
Assert.IsFalse(heatToggle.Checked);
|
||||
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ namespace MatterControl.Tests.MatterControl
|
|||
printerSettings.AutoSave = false;
|
||||
|
||||
// Disable active material/quality overrides
|
||||
printerSettings.SetMaterialPreset(0, "");
|
||||
printerSettings.ActiveMaterialKey = "";
|
||||
printerSettings.ActiveQualityKey = "";
|
||||
|
||||
// Validate just the OemLayer
|
||||
|
|
@ -481,7 +481,7 @@ namespace MatterControl.Tests.MatterControl
|
|||
{
|
||||
printer.RuleViolated = false;
|
||||
|
||||
printerSettings.SetMaterialPreset(0, layer.LayerID);
|
||||
printerSettings.ActiveMaterialKey = layer.LayerID;
|
||||
|
||||
// Validate the settings with this material layer active
|
||||
action(printer, printerSettings);
|
||||
|
|
@ -492,7 +492,7 @@ namespace MatterControl.Tests.MatterControl
|
|||
}
|
||||
}
|
||||
|
||||
printerSettings.SetMaterialPreset(0, "");
|
||||
printerSettings.ActiveMaterialKey = "";
|
||||
|
||||
// Validate quality layers
|
||||
foreach (var layer in printer.PrinterSettings.QualityLayers)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue