/// <summary> /// Returns a set of commands for Axis movement that compensates for a new Printhead's offsets. /// Print speeds will be maximized before moving to offset. /// </summary> /// <param name="newPrinthead"></param> /// <param name="currentPrinthead"></param> /// <param name="zPosition">Relative position of the Z Axis before and after switching.</param> /// <param name="pauseBeforeActivating">Pauses the print sequence before lowering the Z actuator.</param> /// <returns></returns> private List <string> WriteMoveToOffset(PrintheadModel newPrinthead, PrintheadModel currentPrinthead, double zPosition, bool pauseBeforeActivating) { List <string> returnCommands = new List <string>(); AxisModel xAxisModel = _printerModel.AxisModelList[0]; AxisModel yAxisModel = _printerModel.AxisModelList[1]; AxisModel zAxisModel = newPrinthead.AttachedZAxisModel; double xMove = newPrinthead.XOffset - currentPrinthead.XOffset; double yMove = newPrinthead.YOffset - currentPrinthead.YOffset; double zMove = 0; if (newPrinthead.AttachedZAxisModel.Name != _realTimeStatusDataModel.ZRealTimeStatusAxisModel.Name) { //If a new Z actuator is requried. zMove = -1 * (newPrinthead.AttachedZAxisModel.MaxPosition - GlobalValues.LimitBuffer) + zPosition; } //Move to the X and Y offsets first to prevent bumping of print container walls. double unused = 0; if ((xMove != 0) || (yMove != 0)) { //Maximize movement speeds before moving to offset. returnCommands.Add(_writeSetAxisModel.WriteSetAxis(_printerModel.AxisModelList[0])); returnCommands.Add(_writeSetAxisModel.WriteSetAxis(_printerModel.AxisModelList[1])); returnCommands.Add(GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement(xAxisModel.MmPerStep, yAxisModel.MmPerStep, 0, xMove, yMove, 0, xAxisModel.IsDirectionInverted, yAxisModel.IsDirectionInverted, false, ref unused, ref unused, ref unused))); } //Pause before activating. if (pauseBeforeActivating == true) { returnCommands.Add(SerialMessageCharacters.SerialPrintPauseCharacter.ToString()); } //Move the Z offset after the X and Y positions are set. if (zMove != 0) { returnCommands.Add(_writeSetAxisModel.WriteSetAxis(newPrinthead.AttachedZAxisModel)); returnCommands.Add(GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement(0, 0, zAxisModel.MmPerStep, 0, 0, zMove, false, false, zAxisModel.IsDirectionInverted, ref unused, ref unused, ref unused))); } return(returnCommands); }
/// <summary> /// Generate commands for retracting a Z Axis. /// </summary> /// <param name="zAxisModel"></param> /// <returns></returns> private List <string> RetractZ(string commandSet, AxisModel zAxisModel) { List <string> returnCommands = new List <string>(); if (zAxisModel != null) { //Retract Z Axis.\ double unused = 0; bool zDirectionInverted = (zAxisModel != null) ? zAxisModel.IsDirectionInverted : false; if (commandSet.Contains("Limit")) //If CommandSet is "RetractZLimit", then hit the Limit Switch before returning to default position. { //Hit the Limti Switch. double retractDistance = 5000; string zRetract = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 1, 1, zAxisModel.MmPerStep, 0, 0, retractDistance, false, false, zDirectionInverted, ref unused, ref unused, ref unused)); returnCommands.Add(zRetract); //Move away from the Limit Switch to default position. string zMoveAwayFromLimit = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 0, 0, zAxisModel.MmPerStep, 0, 0, -1 * GlobalValues.LimitBuffer, false, false, zAxisModel.IsDirectionInverted, ref unused, ref unused, ref unused)); returnCommands.Add(zMoveAwayFromLimit); } else //If the CommandSet is "RetractZ", then move to default position without hitting the Limit Switch. { //Move to default position. double retractDistance = zAxisModel.MaxPosition - _realTimeStatusDataModel.ZRealTimeStatusAxisModel.Position - GlobalValues.LimitBuffer; string zRetract = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 1, 1, zAxisModel.MmPerStep, 0, 0, retractDistance, false, false, zDirectionInverted, ref unused, ref unused, ref unused)); returnCommands.Add(zRetract); } return(returnCommands); } return(null); }
/// <summary> /// Takes manual input parameters for a movement command and outputs the command to the serial port. /// </summary> /// <param name="xDistance"></param> /// <param name="yDistance"></param> /// <param name="zDistance"></param> public void ProcessManualMovementCommand(double xDistance, double yDistance, double zDistance) { double xmmPerStep = (xDistance != 0) ? _printerModel.AxisModelList[0].MmPerStep : double.MaxValue; double ymmPerStep = (yDistance != 0) ? _printerModel.AxisModelList[1].MmPerStep : double.MaxValue; AxisModel zAxisModel = _printerModel.FindAxis(_realTimeStatusDataModel.ZRealTimeStatusAxisModel.Name); double zmmPerStep = (zDistance != 0) ? _printerModel.FindAxis(zAxisModel.Name).MmPerStep : double.MaxValue; bool zDirectionInverted = (zAxisModel != null) ? zAxisModel.IsDirectionInverted : false; double unused = 0; string axesMovementString = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement(xmmPerStep, ymmPerStep, zmmPerStep, xDistance, yDistance, zDistance, _printerModel.AxisModelList[0].IsDirectionInverted, _printerModel.AxisModelList[1].IsDirectionInverted, zDirectionInverted, ref unused, ref unused, ref unused)); _serialCommunicationOutgoingMessagesModel.QueueNextProspectiveOutgoingMessage(axesMovementString); }
/// <summary> /// Interpret a center axes command set and return an array of commands. /// </summary> /// <param name="commandSet"></param> /// <returns></returns> private List <string> InterpretCenterAxes(string commandSet) { //Command set to be returned. List <string> returnCommands = new List <string>(); AxisModel xAxisModel = _printerModel.AxisModelList[0]; AxisModel yAxisModel = _printerModel.AxisModelList[1]; RealTimeStatusAxisModel xRealTimeStatusAxisModel = _realTimeStatusDataModel.XRealTimeStatusAxisModel; RealTimeStatusAxisModel yRealTimeStatusAxisModel = _realTimeStatusDataModel.YRealTimeStatusAxisModel; double xNewPosition = xRealTimeStatusAxisModel.Position; double yNewPosition = yRealTimeStatusAxisModel.Position; //mmPerStep for each actuator. double xmmPerStep = 0; double ymmPerStep = 0; //InvertDirection for each actuator. bool xInvertDirection = (xAxisModel.IsDirectionInverted == false) ? false : true; bool yInvertDirection = (yAxisModel.IsDirectionInverted == false) ? false : true; //Distances from the center. double xDistanceFromCenter = 0; double yDistanceFromCenter = 0; string[] gCodePhrases = GCodeStringParsing.GCodeTo2DArr(commandSet)[0]; foreach (string phrase in gCodePhrases) { switch (phrase[0]) { case 'X': xDistanceFromCenter = GCodeStringParsing.ParseDouble(phrase); break; case 'Y': yDistanceFromCenter = GCodeStringParsing.ParseDouble(phrase); break; default: //Do nothing. break; } } //Centering the actuator involves: // 1. Finding the median position directly in the center of the max and min position. // 2. Finding the distance between median position and the current position. // 3. Executing that difference worth of movement. if (commandSet.Contains("X")) { xNewPosition = (xAxisModel.MaxPosition - xAxisModel.MinPosition) / 2 + xAxisModel.MinPosition + xDistanceFromCenter; xmmPerStep = xAxisModel.MmPerStep; } if (commandSet.Contains("Y")) { yNewPosition = (yAxisModel.MaxPosition - yAxisModel.MinPosition) / 2 + yAxisModel.MinPosition + yDistanceFromCenter; ymmPerStep = yAxisModel.MmPerStep; } double unused = 0; returnCommands.Add(GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( xmmPerStep, ymmPerStep, 0, xNewPosition - xRealTimeStatusAxisModel.Position, yNewPosition - yRealTimeStatusAxisModel.Position, 0, xInvertDirection, yInvertDirection, false, ref unused, ref unused, ref unused))); return(returnCommands); }
/// <summary> /// Sends outgoing commands that retracts all Z Axes and moves X and Y Axes to the limit switches. /// </summary> public void Home(double xCalibrationSpeed, double yCalibrationSpeed, double zCalibrationSpeed, double xDistanceFromCenter, double yDistanceFromCenter) { try { //Retract Z Axes. RetractAllZ(zCalibrationSpeed); //Z Axes should be in default positions. AxisModel zAxisModel = _printerModel.ZAxisModelList[_printerModel.ZAxisModelList.Count - 1]; double zPosition = zAxisModel.MaxPosition - GlobalValues.LimitBuffer; _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(SerialMessageCharacters.SerialCommandSetCharacter + "SetMinMaxPos " + "Z" + zPosition); //Set X Axis to calibration speeds. AxisModel xAxis = _printerModel.AxisModelList[0]; int xLimitPinID = (xAxis.AttachedLimitSwitchGPIOPinModel == null) ? GlobalValues.PinIDNull : xAxis.AttachedLimitSwitchGPIOPinModel.PinID; string switchX = _writeSetAxisModel.WriteSetAxis(xAxis.AxisID, xAxis.AttachedMotorStepGPIOPinModel.PinID, xAxis.AttachedMotorDirectionGPIOPinModel.PinID, xAxis.StepPulseTime, xLimitPinID, xCalibrationSpeed, xAxis.MaxAcceleration, xAxis.MmPerStep); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(switchX); //Set Y Axis to max speeds. AxisModel yAxis = _printerModel.AxisModelList[1]; int yLimitPinID = (yAxis.AttachedLimitSwitchGPIOPinModel == null) ? GlobalValues.PinIDNull : yAxis.AttachedLimitSwitchGPIOPinModel.PinID; string switchY = _writeSetAxisModel.WriteSetAxis(yAxis.AxisID, yAxis.AttachedMotorStepGPIOPinModel.PinID, yAxis.AttachedMotorDirectionGPIOPinModel.PinID, yAxis.StepPulseTime, yLimitPinID, yCalibrationSpeed, yAxis.MaxAcceleration, yAxis.MmPerStep); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(switchY); //Hit the min and max limit switches on X. double unused = 0; string xPositive = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( xAxis.MmPerStep, 0, 0, 5000, 0, 0, xAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); string xNegative = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( xAxis.MmPerStep, 0, 0, -5000, 0, 0, xAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(xPositive); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(xNegative); //Move away from the limit switch. string xMoveAwayFromLimit = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( xAxis.MmPerStep, 0, 0, GlobalValues.LimitBuffer, 0, 0, xAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(xMoveAwayFromLimit); //Hit the min and max limit switches on Y. string yPositive = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 0, yAxis.MmPerStep, 0, 0, 5000, 0, yAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); string yNegative = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 0, yAxis.MmPerStep, 0, 0, -5000, 0, yAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(yPositive); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(yNegative); //Move away from the limit switch. string yMoveAwayFromLimit = GCodeLinesConverter.GCodeLinesListToString( WriteG00.WriteAxesMovement( 0, yAxis.MmPerStep, 0, 0, GlobalValues.LimitBuffer, 0, yAxis.IsDirectionInverted, false, false, ref unused, ref unused, ref unused)); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(yMoveAwayFromLimit); //Set X Axis to max speeds. string switchXMax = _writeSetAxisModel.WriteSetAxis(xAxis); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(switchXMax); //Set Y Axis to max speeds. string switchYMax = _writeSetAxisModel.WriteSetAxis(yAxis); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(switchYMax); //Center the X and Y actuators. _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(SerialMessageCharacters.SerialCommandSetCharacter + "Center X" + xDistanceFromCenter + " Y" + yDistanceFromCenter); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(SerialMessageCharacters.SerialCommandSetCharacter + "OriginXY"); //At the end, switch the Z actuator to the Printhead used at the beginning of the print. if (_realTimeStatusDataModel.ZRealTimeStatusAxisModel.Name != "Unset") { AxisModel zAxisFinalModel = _printerModel.FindAxis(_realTimeStatusDataModel.ZRealTimeStatusAxisModel.Name); int zFinalLimitPinID = (zAxisFinalModel.AttachedLimitSwitchGPIOPinModel == null) ? GlobalValues.PinIDNull : zAxisFinalModel.AttachedLimitSwitchGPIOPinModel.PinID; string switchZFinal = _writeSetAxisModel.WriteSetAxis(zAxisFinalModel.AxisID, zAxisFinalModel.AttachedMotorStepGPIOPinModel.PinID, zAxisFinalModel.AttachedMotorDirectionGPIOPinModel.PinID, zAxisFinalModel.StepPulseTime, zFinalLimitPinID, zCalibrationSpeed, zAxisFinalModel.MaxAcceleration, zAxisFinalModel.MmPerStep); _serialCommunicationOutgoingMessagesModel.AppendProspectiveOutgoingMessage(switchZFinal); } OnCalibrationBegun(); } catch { _errorListViewModel.AddError("", "Unkown error when homing"); } }
/// <summary> /// Processes the command of setting a printhead. /// </summary> public List <ConvertedGCodeLine> ProcessTCommand(string[] repRapLine, ref MaterialModel currentMaterial) { AxisModel xAxis = _printerModel.AxisModelList[0]; AxisModel yAxis = _printerModel.AxisModelList[1]; AxisModel zAxisCurrent = _printerModel.FindAxis(currentMaterial.PrintheadModel.AttachedZAxisModel.Name); //The return GCode. List <ConvertedGCodeLine> convertedGCodeLinesList = new List <ConvertedGCodeLine>(); //Finds the material that matches the TCommand. string repRapTCommand = repRapLine[0]; MaterialModel matchingMaterial = _printModel.FindMaterial(repRapTCommand); //Appends the converted GCode line with a command that sets the Printhead. //Also appends the converted GCode line with a command that sets the new Z Axis associated with the new Printhead. //Also appends the converted GCode line with commands that compensate for the new Printhead's offsets. try { //If the current Material is using a Motorized Printhead, retract it before switching Printheads. if (((currentMaterial.Name != "Unset") && //If this is not the first Material (currentMaterial.PrintheadModel.PrintheadType == PrintheadType.Motorized) && (currentMaterial.PrintheadModel.Name != matchingMaterial.PrintheadModel.Name) && //Do not execute retraction-related actions if no Printhead change occurs (_parametersModel.IsRetracted == false))) { MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)currentMaterial.PrintheadModel.PrintheadTypeModel; ContinuousPrintStyleModel continuousPrintheadStyleModel = (ContinuousPrintStyleModel)currentMaterial.PrintStyleModel; int eModiPrintCoordIndex = _parametersModel.FindEModiPrintCoordIndex(currentMaterial.PrintheadModel); convertedGCodeLinesList = WriteG00.WriteMotorizedPrintWithoutMovement(-1 * continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance, motorizedPrintheadTypeModel.MmPerStep, motorizedPrintheadTypeModel.IsDirectionInverted, ref _parametersModel.ERepRapCoord.DeltaCoordRemainder, _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex]); _parametersModel.IsRetracted = true; } //If a new Motorized Printhead is being set... //Finds the EModiPrintCoord corresponding to the given Printhead and sets the Minimum and Maximum Position values of the EModiPrintCoord. if (matchingMaterial.PrintheadModel.PrintheadType == PrintheadType.Motorized) { int eModiPrintCoordIndex = _parametersModel.FindEModiPrintCoordIndex(matchingMaterial.PrintheadModel); MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)matchingMaterial.PrintheadModel.PrintheadTypeModel; ContinuousPrintStyleModel continuousPrintheadStyleModel = (ContinuousPrintStyleModel)matchingMaterial.PrintStyleModel; //Sets new Min and Max Positions. _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex].MinPosition = motorizedPrintheadTypeModel.MinPosition; _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex].MaxPosition = motorizedPrintheadTypeModel.MaxPosition; //Sets the starting position of the new Motorized Printhead. //The starting position is the retracted state. //If this is the first Material, then retraction needs to occur to reach the starting retracted state. if (currentMaterial.Name == "Unset") //If this is the first Material. { //Retraction needs to occur to reach the starting retracted state. List <ConvertedGCodeLine> retractE = WriteG00.WriteMotorizedPrintWithoutMovement(-1 * continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance, motorizedPrintheadTypeModel.MmPerStep, motorizedPrintheadTypeModel.IsDirectionInverted, ref _parametersModel.ERepRapCoord.DeltaCoordRemainder, _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex]); if (retractE != null) { convertedGCodeLinesList.AddRange(retractE); } _parametersModel.ERepRapCoord.SetInitialCoord(continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance); _parametersModel.IsRetracted = true; } //If this is a new Motorized Printhead, then it is by default, retracted. if (currentMaterial.PrintheadModel.Name != matchingMaterial.PrintheadModel.Name) { _parametersModel.ERepRapCoord.SetInitialCoord(continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance); _parametersModel.IsRetracted = true; } } else { _parametersModel.IsRetracted = false; } //Set new Min and Max Positions for the X and Y Axes. //This is only relevant when the first Material is set. _parametersModel.SetNewXYZCoord('X', _parametersModel.XCoord.CurrentCoord, _printerModel.AxisModelList[0].MinPosition, _printerModel.AxisModelList[0].MaxPosition); _parametersModel.SetNewXYZCoord('Y', _parametersModel.YCoord.CurrentCoord, _printerModel.AxisModelList[1].MinPosition, _printerModel.AxisModelList[1].MaxPosition); //If the Z Axis does not need to be changed, then keep the same Min and Max Positions in the ZCoord. //If the Z Axis was switched, then set a new ZCoord Position assuming the Z Axis started from a retracted position and traversed its Offset. if (matchingMaterial.PrintheadModel.AttachedZAxisModel.Name != matchingMaterial.PrintheadModel.AttachedZAxisModel.Name) { AxisModel zAxisModel = _printerModel.FindAxis(matchingMaterial.PrintheadModel.AttachedZAxisModel.Name); double newZPosition = zAxisModel.MaxPosition - GlobalValues.LimitBuffer; _parametersModel.SetNewXYZCoord('Z', newZPosition, zAxisModel.MinPosition, zAxisModel.MaxPosition); } //Set new Droplet parameters if applicable. if (!((currentMaterial.Name == "Unset") || (currentMaterial == null)) && //If the current Material is set to Droplet... (currentMaterial.PrintStyle == PrintStyle.Droplet)) { //Execute movement for the remaining movement left in droplet movements. MaterialModel newMaterialParameter = (matchingMaterial.PrintStyle == PrintStyle.Droplet) ? matchingMaterial : null; double[] remainingDropletMovementArr = _parametersModel.ResetDropletPrintParameters(currentMaterial, newMaterialParameter); double unused = 0; List <ConvertedGCodeLine> remainingDropletMovement = WriteG00.WriteAxesMovement( xAxis.MmPerStep, yAxis.MmPerStep, zAxisCurrent.MmPerStep, remainingDropletMovementArr[0], remainingDropletMovementArr[1], remainingDropletMovementArr[2], xAxis.IsDirectionInverted, yAxis.IsDirectionInverted, zAxisCurrent.IsDirectionInverted, ref unused, ref unused, ref unused); if (remainingDropletMovement != null) { convertedGCodeLinesList.AddRange(remainingDropletMovement); } } else if (matchingMaterial.PrintStyle == PrintStyle.Droplet) //If the current Material is irrelevant and the new Material is set to Droplet... { _parametersModel.ResetDropletPrintParameters(null, matchingMaterial); } //Set the new Material. currentMaterial = matchingMaterial; //Command Set for switching Materials. //This Command Set will convert to the commands for retracting the Z Axis, switching Printheads, moving Offsets, and setting new movement speeds. string convertedGCodeLine = SerialMessageCharacters.SerialCommandSetCharacter + "SwitchMaterial "; //If applicable, pause the print sequence before switching to the next Material. if ((currentMaterial.Name != "Unset") && (currentMaterial.PauseBeforeDeactivating == true)) { convertedGCodeLine += "D"; } //If applicable pause the print sequence after switching printheads. if (matchingMaterial.PauseAfterActivating == true) { convertedGCodeLine += "A"; } if (convertedGCodeLine[convertedGCodeLine.Length - 1] != ' ') { convertedGCodeLine += " "; } convertedGCodeLine += '"' + matchingMaterial.Name + '"'; convertedGCodeLinesList.Add(new ConvertedGCodeLine(convertedGCodeLine)); } catch when((matchingMaterial == null) || (currentMaterial == null)) //Catch unset Material. { //Catching and error reporting should have happened earlier. _parametersModel.ErrorReporterViewModel.ReportError("G-Code Conversion Failed: Print Settings Incorrectly Set, Should Not Happen", "Material Null"); return(null); }