Пример #1
0
        /// <summary>
        /// Takes in distance values in units of mm.
        /// </summary>
        /// <param name="X"></param>
        /// <param name="Y"></param>
        /// <param name="Z"></param>
        /// <param name="E"></param>
        /// <param name="GCodeIndex"></param>
        /// <param name="MaterialModel"></param>
        public MovementModel(double X, double Y, double Z, double E, int GCodeIndex, MaterialModel MaterialModel, PrinterModel PrinterModel)
        {
            _materialModel = MaterialModel;
            _printerModel  = PrinterModel;

            //Record movement distances in steps.
            _x = X / _printerModel.AxisModelList[0].MmPerStep;
            _y = Y / _printerModel.AxisModelList[1].MmPerStep;
            _z = Z / _materialModel.PrintheadModel.AttachedZAxisModel.MmPerStep;
            if (_materialModel.PrintheadModel.PrintheadType == PrintheadType.Motorized)
            {
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)MaterialModel.PrintheadModel.PrintheadTypeModel;
                _e = E / motorizedPrintheadTypeModel.MmPerStep;
            }
            else
            {
                _e = 0;
            }

            _gCodeIndex = GCodeIndex;

            //Calculate total distance and speeds for this movement in steps / s.
            _totalDistance = Math.Sqrt(Math.Pow(_x, 2) + Math.Pow(_y, 2) + Math.Pow(_z, 2) + Math.Pow(_e, 2));
            CalculateSpeeds(MaterialModel);
        }
        /// <summary>
        /// Takes manual input parameters for a set motorized printhead command and outputs the command to the serial port.
        /// </summary>
        /// <param name="printheadName"></param>
        /// <param name="maxSpeed"></param>
        /// <param name="acceleration"></param>
        public void ProcessManualSetMotorizedPrintheadCommand(string printheadName, double maxSpeed, double acceleration)
        {
            try
            {
                List <string> outgoingMessagesList = new List <string>();

                PrintheadModel printheadModel = _printerModel.FindPrinthead(printheadName);
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)printheadModel.PrintheadTypeModel;

                int    printheadLimitPinID = (motorizedPrintheadTypeModel.AttachedLimitSwitchGPIOPinModel == null) ? GlobalValues.PinIDNull : motorizedPrintheadTypeModel.AttachedLimitSwitchGPIOPinModel.PinID;
                string setPrintheadString  = _writeSetPrintheadModel.WriteSetMotorDrivenPrinthead(motorizedPrintheadTypeModel.AttachedMotorStepGPIOPinModel.PinID, motorizedPrintheadTypeModel.AttachedMotorDirectionGPIOPinModel.PinID,
                                                                                                  motorizedPrintheadTypeModel.StepPulseTime, printheadLimitPinID, maxSpeed, acceleration, motorizedPrintheadTypeModel.MmPerStep);
                outgoingMessagesList.Add(setPrintheadString);

                //Send GCode for the Z Axis attached to the Printhead.
                AxisModel axisModel = printheadModel.AttachedZAxisModel;

                int    zAxisLimitPinID = (axisModel.AttachedLimitSwitchGPIOPinModel == null) ? GlobalValues.PinIDNull : axisModel.AttachedLimitSwitchGPIOPinModel.PinID;
                string setAxisString   = _writeSetAxisModel.WriteSetAxis(axisModel.AxisID, axisModel.AttachedMotorStepGPIOPinModel.PinID, axisModel.AttachedMotorDirectionGPIOPinModel.PinID,
                                                                         axisModel.StepPulseTime, zAxisLimitPinID, axisModel.MaxSpeed, axisModel.MaxAcceleration, axisModel.MmPerStep);

                //Retract Z Axis before changing Printheads.
                outgoingMessagesList.Add(SerialMessageCharacters.SerialCommandSetCharacter + "RetractZ");
                outgoingMessagesList.Add(setAxisString);
                _serialCommunicationOutgoingMessagesModel.QueueNextProspectiveOutgoingMessage(outgoingMessagesList);
            }
            catch (NullReferenceException e)
            {
                _errorListViewModel.AddError("", "Printhead or z actuator needs to be set in Printer Settings before setting printhead in Control Menu.");
            }
            catch
            {
                _errorListViewModel.AddError("", "Unknown error while setting valve printhead.");
            }
        }
        /// <summary>
        /// Processes the command for Axis movement and Printing.
        /// </summary>
        public List <ConvertedGCodeLine> ProcessG00Command(string[] repRapGCodeLine, MaterialModel currentMaterial)
        {
            //The return GCode.
            List <ConvertedGCodeLine> convertedGCodeLinesList = null;

            //Reads the GCode line and sets the fields in the coord classes.
            //If the printer is moving or printing, then proceed to convert the GCode line.
            if ((ReadCoord(repRapGCodeLine) == true) &&
                ((_parametersModel.XCoord.Changed == true) ||
                 (_parametersModel.YCoord.Changed == true) ||
                 (_parametersModel.ZCoord.Changed == true)))
            {
                //Does this RepRap line indicate printing?
                _parametersModel.IsPrinting = ((repRapGCodeLine[0] == "GX") || (_parametersModel.ERepRapCoord.PositiveChanged == true)) ? true : false; //To Do: Test is E retraction causes IsPrinting to be false.

                try
                {
                    int eModiPrintCoordIndex = _parametersModel.FindEModiPrintCoordIndex(currentMaterial.PrintheadModel);

                    //Check if a Motorized Printhead needs to retract or unretract.
                    if ((currentMaterial.PrintheadModel.PrintheadType == PrintheadType.Motorized) && (currentMaterial.PrintStyle == PrintStyle.Continuous))
                    {
                        //If a Motorized Printhead is in use, then retraction potentially needs to occur before the execution of the next command.
                        if ((_parametersModel.IsPrinting == false) & (_parametersModel.IsRetracted == false))
                        {
                            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel   = (MotorizedPrintheadTypeModel)currentMaterial.PrintheadModel.PrintheadTypeModel;
                            ContinuousPrintStyleModel   continuousPrintheadStyleModel = (ContinuousPrintStyleModel)currentMaterial.PrintStyleModel;
                            convertedGCodeLinesList = WriteG00.WriteMotorizedPrintWithoutMovement(-1 * continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance, motorizedPrintheadTypeModel.MmPerStep,
                                                                                                  motorizedPrintheadTypeModel.IsDirectionInverted, ref _parametersModel.ERepRapCoord.DeltaCoordRemainder, _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex]);
                            _parametersModel.IsRetracted = true;
                        }
                        //If a Motorized Printhead needs to print, then reversing the retraction potentially needs to occur before the execution of the next print command.
                        else if ((_parametersModel.IsPrinting == true) && (_parametersModel.IsRetracted))
                        {
                            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel   = (MotorizedPrintheadTypeModel)currentMaterial.PrintheadModel.PrintheadTypeModel;
                            ContinuousPrintStyleModel   continuousPrintheadStyleModel = (ContinuousPrintStyleModel)currentMaterial.PrintStyleModel;
                            convertedGCodeLinesList = WriteG00.WriteMotorizedPrintWithoutMovement(continuousPrintheadStyleModel.MotorizedDispenseRetractionDistance, motorizedPrintheadTypeModel.MmPerStep,
                                                                                                  motorizedPrintheadTypeModel.IsDirectionInverted, ref _parametersModel.ERepRapCoord.DeltaCoordRemainder, _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex]);
                            _parametersModel.IsRetracted = false;
                        }
                    }

                    //Write the movement or print command.
                    List <ConvertedGCodeLine> gCommand = SetWriteG00Command(
                        currentMaterial, _printerModel,
                        _parametersModel.ERepRapCoord, _parametersModel.XCoord, _parametersModel.YCoord, _parametersModel.ZCoord, _parametersModel.EModiPrintCoordList[eModiPrintCoordIndex]);
                    if (convertedGCodeLinesList == null)
                    {
                        convertedGCodeLinesList = gCommand;
                    }
                    else
                    {
                        convertedGCodeLinesList.AddRange(gCommand);
                    }
                }
                catch when(currentMaterial == null)  //Material unset.
                {
                    //Catching and error handling should have happened earlier.
                    convertedGCodeLinesList = null;
                }
        /// <summary>
        /// Takes manual input parameters for a set of commands for motorized printhead droplet printing and outputs the commands to the serial port.
        /// </summary>
        /// <param name="xDistance"></param>
        /// <param name="yDistance"></param>
        /// <param name="zDistance"></param>
        /// <param name="interpolateDistance"></param>
        /// <param name="eDispensePerDroplet"></param>
        public void ProcessManualMotorDropletPrintCommand(double xDistance, double yDistance, double zDistance, double interpolateDistance, double eDispensePerDroplet)
        {
            PrintheadModel printheadModel = _printerModel.FindPrinthead(_realTimeStatusDataModel.ActivePrintheadModel.Name);
            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)printheadModel.PrintheadTypeModel;
            double emmPerStep = motorizedPrintheadTypeModel.MmPerStep;
            RealTimeStatusMotorizedPrintheadModel realTimeStatusMotorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_realTimeStatusDataModel.ActivePrintheadModel;
            double    eMaxSpeed          = realTimeStatusMotorizedPrintheadModel.MaxSpeed;
            double    eAcceleration      = realTimeStatusMotorizedPrintheadModel.Acceleration;
            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 printString = GCodeLinesConverter.GCodeLinesListToString(
                WriteG00.WriteMotorizedDropletPrint(
                    emmPerStep, xmmPerStep, ymmPerStep, zmmPerStep,
                    eDispensePerDroplet, 0, xDistance, 0, yDistance, 0, zDistance,
                    _printerModel.AxisModelList[0].IsDirectionInverted, _printerModel.AxisModelList[1].IsDirectionInverted, zDirectionInverted, motorizedPrintheadTypeModel.IsDirectionInverted,
                    ref unused, ref unused, ref unused, ref unused,
                    null, new DropletModel(interpolateDistance)));

            _serialCommunicationOutgoingMessagesModel.QueueNextProspectiveOutgoingMessage(printString);
        }
        /// <summary>
        /// Set the new center as the origin (position 0) and adjust the max and min range around such.
        /// </summary>
        /// <param name="commandSet"></param>
        /// <returns></returns>
        private List <string> InterpretSetOrigin(string commandSet)
        {
            //Remove "*Origin" from the beginning of the string.
            commandSet = commandSet.Substring(6);

            if (commandSet.Contains("E"))
            {
                if (_realTimeStatusDataModel.ActivePrintheadType == PrintheadType.Motorized)
                {
                    RealTimeStatusMotorizedPrintheadModel realTimeStatusMotorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_realTimeStatusDataModel.ActivePrintheadModel;
                    MotorizedPrintheadTypeModel           motorizedPrintheadTypeModel           = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(realTimeStatusMotorizedPrintheadModel.Name).PrintheadTypeModel;

                    double previousEPosition = realTimeStatusMotorizedPrintheadModel.Position;

                    motorizedPrintheadTypeModel.MaxPosition       -= previousEPosition;
                    motorizedPrintheadTypeModel.MinPosition       -= previousEPosition;
                    realTimeStatusMotorizedPrintheadModel.Position = 0;
                }
            }

            if (commandSet.Contains("X"))
            {
                AxisModel xAxisModel = _printerModel.AxisModelList[0];

                double previousXPosition = _realTimeStatusDataModel.XRealTimeStatusAxisModel.Position;

                xAxisModel.MaxPosition -= previousXPosition;
                xAxisModel.MinPosition -= previousXPosition;
                _realTimeStatusDataModel.XRealTimeStatusAxisModel.Position = 0;
            }

            if (commandSet.Contains("Y"))
            {
                AxisModel yAxisModel = _printerModel.AxisModelList[1];

                double previousYPosition = _realTimeStatusDataModel.YRealTimeStatusAxisModel.Position;

                yAxisModel.MaxPosition -= previousYPosition;
                yAxisModel.MinPosition -= previousYPosition;
                _realTimeStatusDataModel.YRealTimeStatusAxisModel.Position = 0;
            }

            if (commandSet.Contains("Z"))
            {
                AxisModel zAxisModel = _printerModel.FindAxis(_realTimeStatusDataModel.ZRealTimeStatusAxisModel.Name);

                double previousZPosition = _realTimeStatusDataModel.ZRealTimeStatusAxisModel.Position;

                zAxisModel.MaxPosition -= previousZPosition;
                zAxisModel.MinPosition -= previousZPosition;
                _realTimeStatusDataModel.ZRealTimeStatusAxisModel.Position = 0;
            }

            OnCommandSetMinMaxPositionChanged();
            OnCommandSetMinMaxPositionChanged();

            //No commands to return.
            return(null);
        }
        /// <summary>
        /// Takes manual input parameters for a motor print without movement command and outputs the command to the serial port.
        /// </summary>
        /// <param name="eDistance"></param>
        public void ProcessManualMotorPrintWithoutMovementCommand(double eDistance)
        {
            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_realTimeStatusDataModel.ActivePrintheadModel.Name).PrintheadTypeModel;
            double emmPerStep = motorizedPrintheadTypeModel.MmPerStep;
            RealTimeStatusMotorizedPrintheadModel realTimeStatusMotorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_realTimeStatusDataModel.ActivePrintheadModel;

            double unused      = 0;
            string printString = GCodeLinesConverter.GCodeLinesListToString(
                WriteG00.WriteMotorizedPrintWithoutMovement(eDistance, emmPerStep, motorizedPrintheadTypeModel.IsDirectionInverted, ref unused, null));

            _serialCommunicationOutgoingMessagesModel.QueueNextProspectiveOutgoingMessage(printString);
        }
Пример #7
0
        /// <summary>
        /// Reads the coordinate values in a movement or print command.
        /// </summary>
        /// <param name="convertedGCodeLine"></param>
        /// <param name="gCodeIndex"></param>
        /// <param name="materialModel"></param>
        /// <returns></returns>
        private MovementModel ReadCoord(string convertedGCodeLine, int gCodeIndex, MaterialModel materialModel)
        {
            //G Commands from Converted GCode are in relative positions.
            string[] gCodePhrases = GCodeStringParsing.GCodeTo2DArr(convertedGCodeLine)[0];

            double xDistance = 0;
            double yDistance = 0;
            double zDistance = 0;
            double eDistance = 0;

            //Read the coordinates from the GCode.
            for (int phrase = 1; phrase < gCodePhrases.Length; phrase++)
            {
                switch (gCodePhrases[phrase][0])
                {
                case 'X':
                    int       xSteps     = (int)GCodeStringParsing.ParseDouble(gCodePhrases[phrase]);
                    AxisModel xAxisModel = _printerModel.AxisModelList[0];
                    xDistance = G00Calculator.StepsToDistance(xSteps, xAxisModel.MmPerStep, xAxisModel.IsDirectionInverted);
                    break;

                case 'Y':
                    int       ySteps     = (int)GCodeStringParsing.ParseDouble(gCodePhrases[phrase]);
                    AxisModel yAxisModel = _printerModel.AxisModelList[1];
                    yDistance = G00Calculator.StepsToDistance(ySteps, yAxisModel.MmPerStep, yAxisModel.IsDirectionInverted);
                    break;

                case 'Z':
                    int       zSteps     = (int)GCodeStringParsing.ParseDouble(gCodePhrases[phrase]);
                    AxisModel zAxisModel = _printerModel.FindAxis(materialModel.PrintheadModel.AttachedZAxisModel.Name);
                    zDistance = G00Calculator.StepsToDistance(zSteps, zAxisModel.MmPerStep, zAxisModel.IsDirectionInverted);
                    break;

                case 'E':
                    int eSteps = (int)GCodeStringParsing.ParseDouble(gCodePhrases[phrase]);
                    MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)materialModel.PrintheadModel.PrintheadTypeModel;
                    eDistance = G00Calculator.StepsToDistance(eSteps, motorizedPrintheadTypeModel.MmPerStep, motorizedPrintheadTypeModel.IsDirectionInverted);
                    break;

                default:
                    //Do nothing.
                    break;
                }
            }

            MovementModel movementModel = new MovementModel(xDistance, yDistance, zDistance, eDistance, gCodeIndex, materialModel, _printerModel);

            return(movementModel);
        }
        /// <summary>
        /// Record the parameters from a Set Motorized Printhead command.
        /// </summary>
        /// <param name="printheadName"></param>
        /// <param name="maxSpeed"></param>
        /// <param name="acceleration"></param>
        public void RecordSetMotorizedPrinthead(string printheadName, double maxSpeed, double acceleration)
        {
            _activePrintheadType = PrintheadType.Motorized;

            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(printheadName).PrintheadTypeModel;
            double mmPerStep = motorizedPrintheadTypeModel.MmPerStep;

            //Max speed is read as steps / s and acceleration is read as steps / s2.
            //These parameters are converted to this program's convention of mm / s and mm / s2.
            double convertedMaxSpeed     = maxSpeed * mmPerStep;
            double convertedAcceleration = acceleration * mmPerStep;

            _activePrintheadModel = new RealTimeStatusMotorizedPrintheadModel(printheadName, convertedMaxSpeed, convertedAcceleration);

            //Notify other classes.
            OnRecordSetMotorizedPrintheadExecuted(printheadName);
        }
Пример #9
0
        /// <summary>
        /// Calculate max speed and acceleration such that these values do not exceed the individual max speed and acceleration values of each Axis.
        /// </summary>
        /// <param name="materialModel"></param>
        private void CalculateSpeeds(MaterialModel materialModel)
        {
            //Store all distance and speed values in arrays for easy calculation later.
            double[] distanceArr = new double[4];
            distanceArr[0] = Math.Abs(_x);
            distanceArr[1] = Math.Abs(_y);
            distanceArr[2] = Math.Abs(_z);
            distanceArr[3] = Math.Abs(_e);
            double[] maxSpeedArr = new double[4];
            maxSpeedArr[0] = materialModel.XYPrintSpeed / _printerModel.AxisModelList[0].MmPerStep;
            maxSpeedArr[1] = materialModel.XYPrintSpeed / _printerModel.AxisModelList[1].MmPerStep;
            maxSpeedArr[2] = materialModel.ZPrintSpeed / _materialModel.PrintheadModel.AttachedZAxisModel.MmPerStep;
            double[] accelerationArr = new double[4];
            accelerationArr[0] = materialModel.XYPrintAcceleration / _printerModel.AxisModelList[0].MmPerStep;
            accelerationArr[1] = materialModel.XYPrintAcceleration / _printerModel.AxisModelList[1].MmPerStep;
            accelerationArr[2] = materialModel.ZPrintAcceleration / _materialModel.PrintheadModel.AttachedZAxisModel.MmPerStep;
            if (materialModel.PrintheadModel.PrintheadType == PrintheadType.Motorized)
            {
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)materialModel.PrintheadModel.PrintheadTypeModel;
                maxSpeedArr[3]     = motorizedPrintheadTypeModel.MaxSpeed / motorizedPrintheadTypeModel.MmPerStep;
                accelerationArr[3] = motorizedPrintheadTypeModel.MaxAcceleration / motorizedPrintheadTypeModel.MmPerStep;
            }
            else
            {
                maxSpeedArr[3]     = 0;
                accelerationArr[3] = 0;
            }

            //Calculate the maximum speeds and accelerations such that these values do not exceed the individual speed values of each Axis.
            for (int k = 0; k < 4; k++)
            {
                if (maxSpeedArr[k] != 0)
                {
                    double scaledMaxSpeed = maxSpeedArr[k] * _totalDistance / distanceArr[k];
                    _maxSpeed = (scaledMaxSpeed < _maxSpeed) ? scaledMaxSpeed : _maxSpeed;
                }

                if (accelerationArr[k] != 0)
                {
                    double scaledAcceleration = accelerationArr[k] * _totalDistance / distanceArr[k];
                    _acceleration = (scaledAcceleration < _acceleration) ? scaledAcceleration : _acceleration;
                }
            }
        }
        /// <summary>
        /// Record the parameters from a Motorized Printhead Print With Movement command.
        /// </summary>
        /// <param name="taskQueuedMessage"></param>
        /// <param name="eStepsTaken"></param>
        /// <param name="xStepsTaken"></param>
        /// <param name="yStepsTaken"></param>
        /// <param name="zStepsTaken"></param>
        public void RecordMotorizedPrintWithMovement(int eStepsTaken, int xStepsTaken, int yStepsTaken, int zStepsTaken)
        {
            if (_activePrintheadType == PrintheadType.Motorized)
            {
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_activePrintheadModel.Name).PrintheadTypeModel;
                double emmPerStep = motorizedPrintheadTypeModel.MmPerStep;
                double xmmPerStep = _printerModel.AxisModelList[0].MmPerStep;
                double ymmPerStep = _printerModel.AxisModelList[1].MmPerStep;
                double zmmPerStep = _printerModel.FindAxis(_zRealTimeStatusAxisModel.Name).MmPerStep;

                //Record data.
                RealTimeStatusMotorizedPrintheadModel motorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_activePrintheadModel;

                //Record positions.
                if (eStepsTaken != 0)
                {
                    motorizedPrintheadModel.Position         += (motorizedPrintheadTypeModel.IsDirectionInverted == false) ? (double)(eStepsTaken * emmPerStep) : (double)(eStepsTaken * -1 * emmPerStep);
                    motorizedPrintheadModel.LimitSwitchStatus = LimitSwitchStatus.NoLimit;
                }

                if (xStepsTaken != 0)
                {
                    _xRealTimeStatusAxisModel.Position         += (_printerModel.AxisModelList[0].IsDirectionInverted == false) ? (double)(xStepsTaken * xmmPerStep) : (double)(xStepsTaken * -1 * xmmPerStep);
                    _xRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.NoLimit;
                }

                if (yStepsTaken != 0)
                {
                    _yRealTimeStatusAxisModel.Position         += (_printerModel.AxisModelList[1].IsDirectionInverted == false) ? (double)(yStepsTaken * ymmPerStep) : (double)(yStepsTaken * -1 * ymmPerStep);
                    _yRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.NoLimit;
                }

                if (zStepsTaken != 0)
                {
                    _zRealTimeStatusAxisModel.Position         += (_printerModel.FindAxis(_zRealTimeStatusAxisModel.Name).IsDirectionInverted == false) ? (double)(zStepsTaken * zmmPerStep) : (double)(zStepsTaken * -1 * zmmPerStep);
                    _zRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.NoLimit;
                }

                //Notify other classes.
                OnRecordMotorizedPrintWithMovementExecuted();
            }
        }
        /// <summary>
        /// Record the parameters from a Motorized Printhead Print without Movement command.
        /// </summary>
        /// <param name="ePosition"></param>
        public void RecordMotorizedPrintWithoutMovement(double eStepsTaken)
        {
            if (_activePrintheadType == PrintheadType.Motorized)
            {
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_activePrintheadModel.Name).PrintheadTypeModel;
                double emmPerStep = motorizedPrintheadTypeModel.MmPerStep;

                //Record data.
                RealTimeStatusMotorizedPrintheadModel motorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_activePrintheadModel;

                if (eStepsTaken != 0)
                {
                    motorizedPrintheadModel.Position         += (motorizedPrintheadTypeModel.IsDirectionInverted == false) ? (double)(eStepsTaken * emmPerStep) : (double)(eStepsTaken * -1 * emmPerStep);
                    motorizedPrintheadModel.LimitSwitchStatus = LimitSwitchStatus.NoLimit;
                }

                //Notify other classes.
                OnRecordMotorizedPrintWithoutMovementExecuted();
            }
        }
        /// <summary>
        /// Takes manual input parameters for a motor print with movement command and outputs the command to the serial port.
        /// </summary>
        /// <param name="xDistance"></param>
        /// <param name="yDistance"></param>
        /// <param name="zDistance"></param>
        /// <param name="eDispensePerDistance"></param>
        public void ProcessManualMotorPrintWithMovementCommand(double xDistance, double yDistance, double zDistance, double eDispensePerDistance)
        {
            MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_realTimeStatusDataModel.ActivePrintheadModel.Name).PrintheadTypeModel;
            double    emmPerStep         = motorizedPrintheadTypeModel.MmPerStep;
            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 printString = GCodeLinesConverter.GCodeLinesListToString(
                WriteG00.WriteMotorizedContinuousPrint(emmPerStep, xmmPerStep, ymmPerStep, zmmPerStep,
                                                       eDispensePerDistance, xDistance, yDistance, zDistance,
                                                       _printerModel.AxisModelList[0].IsDirectionInverted, _printerModel.AxisModelList[1].IsDirectionInverted, zDirectionInverted, motorizedPrintheadTypeModel.IsDirectionInverted,
                                                       ref unused, ref unused, ref unused, ref unused,
                                                       null));

            _serialCommunicationOutgoingMessagesModel.QueueNextProspectiveOutgoingMessage(printString);
        }
        /// <summary>
        /// Returns converted GCode for the setting of Motor-Driven Printheads.
        /// </summary>
        /// <param name="printheadModel"></param>
        /// <returns></returns>
        public string WriteSetMotorDrivenPrinthead(PrintheadModel printheadModel)
        {
            string convertedGCode = "";

            if (printheadModel.PrintheadType == PrintheadType.Motorized)
            {
                MotorizedPrintheadTypeModel motorizedPrinthead = (MotorizedPrintheadTypeModel)printheadModel.PrintheadTypeModel;

                try
                {
                    int limitPin = GlobalValues.PinIDNull;
                    if (motorizedPrinthead.AttachedLimitSwitchGPIOPinModel != null)
                    {
                        limitPin = motorizedPrinthead.AttachedLimitSwitchGPIOPinModel.PinID;
                    }

                    convertedGCode = WriteSetMotorDrivenPrinthead(motorizedPrinthead.AttachedMotorStepGPIOPinModel.PinID, motorizedPrinthead.AttachedMotorDirectionGPIOPinModel.PinID, motorizedPrinthead.StepPulseTime,
                                                                  limitPin, motorizedPrinthead.MaxSpeed, motorizedPrinthead.MaxAcceleration, motorizedPrinthead.MmPerStep);
                }
                catch when(printheadModel == null)
                {
                    _parametersModel.ErrorReporterViewModel.ReportError("GCode Converter: Printer Unset", "Printhead Not Found");
                    convertedGCode = "";
                }
Пример #14
0
        /// <summary>
        /// Translates raw task queued message for a Set Motorized Printhead command into a readable phrase.
        /// Sets the Real Time Status based on the message.
        /// </summary>
        /// <param name="incomingMessage"></param>
        /// <returns></returns>
        public void InterpretSetMotorizedPrintheadQueued(string incomingMessage)
        {
            string taskQueuedMessage = "Set Motorized Printhead: ";       //Return string.
            string printheadName     = "Unknown Motorized Printhead";     //Name of the Printhead. Labelled as unknown if Axis cannot be found.

            double[] parameterValues = ParseDoubleArray(incomingMessage); //Array of numerical values in incomingMessage.

            int stepPin      = (int)parameterValues[0];
            int maxSpeed     = (int)parameterValues[4];
            int acceleration = (int)parameterValues[5];

            //Search for the PrintheadModel with the matching Step Pin ID then return the Printhead Name.
            foreach (PrintheadModel printheadModel in _printerModel.PrintheadModelList)
            {
                if (printheadModel.PrintheadType == PrintheadType.Motorized)
                {
                    MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)printheadModel.PrintheadTypeModel;
                    if ((int)stepPin == motorizedPrintheadTypeModel.AttachedMotorStepGPIOPinModel.PinID)
                    {
                        printheadName = printheadModel.Name;
                        break;
                    }
                }
            }

            taskQueuedMessage += printheadName;
            taskQueuedMessage += " S" + maxSpeed;
            taskQueuedMessage += " A" + acceleration;

            //Set Real Time Status parameters based on this incomingMessage.
            if (printheadName != "Unknown Motorized Printhead")
            {
                _realTimeStatusDataModel.RecordTaskQueued(taskQueuedMessage);
                _printerViewModel.FindPrinthead(printheadName).PrintheadStatus = PrintheadStatus.BeingSet;
            }
        }
        /// <summary>
        /// Record the parameters from a Limit Switch status message.
        /// </summary>
        /// <param name="xLimit"></param>
        /// <param name="yLimit"></param>
        /// <param name="zLimit"></param>
        /// <param name="eLimit"></param>
        /// <param name="xStepsTaken"></param>
        /// <param name="yStepsTaken"></param>
        /// <param name="zStepsTaken"></param>
        /// <param name="eStepsTaken"></param>
        public void RecordLimit(bool xLimit, bool yLimit, bool zLimit, bool eLimit, int xStepsTaken, int yStepsTaken, int zStepsTaken, int eStepsTaken)
        {
            //E
            if (_activePrintheadType == PrintheadType.Motorized)
            {
                //mm Per Step.
                MotorizedPrintheadTypeModel motorizedPrintheadTypeModel = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_activePrintheadModel.Name).PrintheadTypeModel;
                eStepsTaken = (motorizedPrintheadTypeModel.IsDirectionInverted == false) ? eStepsTaken : (-1 * eStepsTaken);
                double emmPerStep = motorizedPrintheadTypeModel.MmPerStep;

                //Update Position.
                RealTimeStatusMotorizedPrintheadModel realTimeStatusMotorizedPrintheadTypeModel = (RealTimeStatusMotorizedPrintheadModel)_activePrintheadModel;
                realTimeStatusMotorizedPrintheadTypeModel.Position += (double)(eStepsTaken * -1 * emmPerStep);

                //Update Max/Min Position and Limit.
                if (eLimit == true)
                {
                    if (eStepsTaken > 0)
                    {
                        motorizedPrintheadTypeModel.MaxPosition = realTimeStatusMotorizedPrintheadTypeModel.Position;
                        realTimeStatusMotorizedPrintheadTypeModel.LimitSwitchStatus = LimitSwitchStatus.UpperLimit;
                    }
                    else if (eStepsTaken < 0)
                    {
                        motorizedPrintheadTypeModel.MinPosition = realTimeStatusMotorizedPrintheadTypeModel.Position;
                        realTimeStatusMotorizedPrintheadTypeModel.LimitSwitchStatus = LimitSwitchStatus.LowerLimit;
                    }
                }
            }

            AxisModel xAxisModel = _printerModel.AxisModelList[0];
            AxisModel yAxisModel = _printerModel.AxisModelList[1];
            AxisModel zAxisModel = _printerModel.FindAxis(_zRealTimeStatusAxisModel.Name);

            //mm Per Step.
            double xmmPerStep = xAxisModel.MmPerStep;
            double ymmPerStep = yAxisModel.MmPerStep;
            double zmmPerStep = (zAxisModel != null) ? _printerModel.FindAxis(_zRealTimeStatusAxisModel.Name).MmPerStep : 0;

            //Record positions.
            if (xStepsTaken != 0)
            {
                xStepsTaken = (_printerModel.AxisModelList[0].IsDirectionInverted == false) ? xStepsTaken : (-1 * xStepsTaken);
                _xRealTimeStatusAxisModel.Position += (double)(xStepsTaken * xmmPerStep);
            }

            if (yStepsTaken != 0)
            {
                yStepsTaken = (_printerModel.AxisModelList[1].IsDirectionInverted == false) ? yStepsTaken : (-1 * yStepsTaken);
                _yRealTimeStatusAxisModel.Position += (double)(yStepsTaken * ymmPerStep);
            }

            if (zStepsTaken != 0)
            {
                zStepsTaken = (_printerModel.FindAxis(_zRealTimeStatusAxisModel.Name).IsDirectionInverted == false) ? zStepsTaken : (-1 * zStepsTaken);
                _zRealTimeStatusAxisModel.Position += (double)(zStepsTaken * zmmPerStep);
            }

            //Set Max Positions and Limits.
            if (xLimit == true)
            {
                if (xStepsTaken > 0)
                {
                    xAxisModel.MaxPosition = _xRealTimeStatusAxisModel.Position;
                    _xRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.UpperLimit;
                }
                else if (xStepsTaken < 0)
                {
                    xAxisModel.MinPosition = _xRealTimeStatusAxisModel.Position;
                    _xRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.LowerLimit;
                }
            }

            if (yLimit == true)
            {
                if (yStepsTaken > 0)
                {
                    yAxisModel.MaxPosition = _yRealTimeStatusAxisModel.Position;
                    _yRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.UpperLimit;
                }
                else if (yStepsTaken < 0)
                {
                    yAxisModel.MinPosition = _yRealTimeStatusAxisModel.Position;
                    _yRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.LowerLimit;
                }
            }

            if (zLimit == true)
            {
                if (zStepsTaken > 0)
                {
                    if (_shouldZCalibrate == true)
                    {
                        zAxisModel.MaxPosition = _zRealTimeStatusAxisModel.Position;
                        _shouldZCalibrate      = false;
                    }
                    _zRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.UpperLimit;
                }
                else if (zStepsTaken < 0)
                {
                    //The minimum Position of Z Axes are always zero.
                    //If the lower limit of a Z Axis is hit, then adjust the Max Position such that the range remains the same.
                    if (_shouldZCalibrate == true)
                    {
                        zAxisModel.MaxPosition = zAxisModel.MaxPosition + _zRealTimeStatusAxisModel.Position;
                        zAxisModel.MinPosition = 0;
                        _shouldZCalibrate      = false;
                    }
                    _zRealTimeStatusAxisModel.LimitSwitchStatus = LimitSwitchStatus.LowerLimit;
                }
            }

            //Notify other classes.
            OnRecordLimitExecuted();
        }
 public MotorizedPrintheadTypeViewModel(MotorizedPrintheadTypeModel MotorizedPrintheadTypeModel, GPIOPinListsViewModel GPIOPinListsViewModel) : base(MotorizedPrintheadTypeModel, GPIOPinListsViewModel)
 {
     _motorizedPrintheadTypeModel = MotorizedPrintheadTypeModel;
 }
        /// <summary>
        /// Sets the minimum and/or maximum position of actuator-based equipment as its current position.
        /// </summary>
        /// <param name="commandSet"></param>
        /// <returns></returns>
        private List <string> InterpretSetMinMaxPosition(string commandSet)
        {
            //Remove "*SetMinMaxPos" from the beginning of the command set.
            commandSet = commandSet.Substring(12);

            for (int index = 0; index < commandSet.Length; index++)
            {
                switch (commandSet[index])
                {
                case 'E':
                    if (_realTimeStatusDataModel.ActivePrintheadType == PrintheadType.Motorized)
                    {
                        //Set the current position as the parameter value.
                        RealTimeStatusMotorizedPrintheadModel realTimeStatusMotorizedPrintheadModel = (RealTimeStatusMotorizedPrintheadModel)_realTimeStatusDataModel.ActivePrintheadModel;
                        MotorizedPrintheadTypeModel           motorizedPrintheadTypeModel           = (MotorizedPrintheadTypeModel)_printerModel.FindPrinthead(_realTimeStatusDataModel.ActivePrintheadModel.Name).PrintheadTypeModel;
                        double ePreviousPosition = realTimeStatusMotorizedPrintheadModel.Position;
                        realTimeStatusMotorizedPrintheadModel.Position = ParseDouble(commandSet.Substring(index));
                        double ePositionDifference = realTimeStatusMotorizedPrintheadModel.Position - ePreviousPosition;

                        //Set the Min or Max Position property as the parameter value.
                        //Adjust the Min and Max positions such that the distance between Max and Min Position remains the same.
                        switch (commandSet[index + 1])
                        {
                        case 'N':
                            motorizedPrintheadTypeModel.MinPosition  = realTimeStatusMotorizedPrintheadModel.Position;
                            motorizedPrintheadTypeModel.MaxPosition += ePositionDifference;
                            break;

                        case 'M':
                            motorizedPrintheadTypeModel.MaxPosition  = realTimeStatusMotorizedPrintheadModel.Position;
                            motorizedPrintheadTypeModel.MinPosition += ePositionDifference;
                            break;

                        default:
                            //Set position value only.
                            //Do nothing here.
                            break;
                        }
                    }
                    break;

                case 'X':
                    //Set the current position as the parameter value.
                    RealTimeStatusAxisModel xRealTimeStatusAxisModel = _realTimeStatusDataModel.XRealTimeStatusAxisModel;
                    AxisModel xAxisModel        = _printerModel.AxisModelList[0];
                    double    xPreviousPosition = xRealTimeStatusAxisModel.Position;
                    xRealTimeStatusAxisModel.Position = ParseDouble(commandSet.Substring(index));
                    double xPositionDifference = xRealTimeStatusAxisModel.Position - xPreviousPosition;

                    //Set the Min or Max Position property as the parameter value.
                    //Adjust the Min and Max positions such that the distance between Max and Min Position remains the same.
                    switch (commandSet[index + 1])
                    {
                    case 'N':
                        xAxisModel.MinPosition  = xRealTimeStatusAxisModel.Position;
                        xAxisModel.MaxPosition += xPositionDifference;
                        break;

                    case 'M':
                        xAxisModel.MaxPosition  = xRealTimeStatusAxisModel.Position;
                        xAxisModel.MinPosition += xPositionDifference;
                        break;

                    default:
                        //Set position value only.
                        //Do nothing here.
                        break;
                    }
                    break;

                case 'Y':
                    //Set the current position as the parameter value.
                    RealTimeStatusAxisModel yRealTimeStatusAxisModel = _realTimeStatusDataModel.YRealTimeStatusAxisModel;
                    AxisModel yAxisModel        = _printerModel.AxisModelList[1];
                    double    yPreviousPosition = yRealTimeStatusAxisModel.Position;
                    yRealTimeStatusAxisModel.Position = ParseDouble(commandSet.Substring(index));
                    double yPositionDifference = yRealTimeStatusAxisModel.Position - yPreviousPosition;

                    //Set the Min or Max Position property as the parameter value.
                    //Adjust the Min and Max positions such that the distance between Max and Min Position remains the same.
                    switch (commandSet[index + 1])
                    {
                    case 'N':
                        yAxisModel.MinPosition  = yRealTimeStatusAxisModel.Position;
                        yAxisModel.MaxPosition += yPositionDifference;
                        break;

                    case 'M':
                        yAxisModel.MaxPosition  = yRealTimeStatusAxisModel.Position;
                        yAxisModel.MinPosition += yPositionDifference;
                        break;

                    default:
                        //Set position value only.
                        //Do nothing here.
                        break;
                    }
                    break;

                case 'Z':
                    //Set the current position as the parameter value.
                    RealTimeStatusAxisModel zRealTimeStatusAxisModel = _realTimeStatusDataModel.ZRealTimeStatusAxisModel;
                    AxisModel zAxisModel        = _printerModel.FindAxis(zRealTimeStatusAxisModel.Name);
                    double    zPreviousPosition = zRealTimeStatusAxisModel.Position;
                    zRealTimeStatusAxisModel.Position = ParseDouble(commandSet.Substring(index));
                    double zPositionDifference = zRealTimeStatusAxisModel.Position - zPreviousPosition;

                    //Set the Min or Max Position property as the parameter value.
                    //Adjust the Min and Max positions such that the distance between Max and Min Position remains the same.
                    switch (commandSet[index + 1])
                    {
                    case 'N':
                        zAxisModel.MinPosition  = zRealTimeStatusAxisModel.Position;
                        zAxisModel.MaxPosition += zPositionDifference;
                        break;

                    case 'M':
                        zAxisModel.MaxPosition  = zRealTimeStatusAxisModel.Position;
                        zAxisModel.MinPosition += zPositionDifference;
                        break;

                    default:
                        //Set position value only.
                        //Do nothing here.
                        break;
                    }

                    break;
                }
            }

            OnCommandSetPositionChanged();
            OnCommandSetMinMaxPositionChanged();

            //No commands to return.
            return(null);
        }
        /// <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);
            }