Пример #1
0
        public override string ReadLine()
        {
            string lineToSend = base.ReadLine();

            if (lineToSend != null &&
                lineToSend.EndsWith("; NO_PROCESSING"))
            {
                return(lineToSend);
            }

            if (lineToSend != null &&
                LineIsMovement(lineToSend))
            {
                PrinterMove currentMove = GetPosition(lineToSend, lastDestination);

                if (currentMove.HaveAnyPosition)
                {
                    ClampToPrinter(ref currentMove);
                    lineToSend = CreateMovementLine(currentMove, lastDestination);
                }
                lastDestination = currentMove;

                return(lineToSend);
            }

            return(lineToSend);
        }
Пример #2
0
        public override void SetPrinterPosition(PrinterMove outputPosition)
        {
            var outputWithLeveling = PrinterMove.Unknown;

            outputWithLeveling.CopyKnowSettings(outputPosition);

            if (LevelingActive &&
                outputPosition.PositionFullyKnown)
            {
                string expectedOutput      = CreateMovementLine(outputPosition);
                string doubleLeveledOutput = GetLeveledPosition(expectedOutput, outputPosition);

                PrinterMove doubleLeveledDestination = GetPosition(doubleLeveledOutput, PrinterMove.Unknown);
                PrinterMove deltaToLeveledPosition   = doubleLeveledDestination - outputPosition;

                this.inputUnleveled = outputPosition - deltaToLeveledPosition;

                // clean up settings that we don't want to be subtracted
                this.inputUnleveled.extrusion = outputPosition.extrusion;
                this.inputUnleveled.feedRate  = outputPosition.feedRate;

                internalStream.SetPrinterPosition(this.inputUnleveled);
            }
            else
            {
                this.inputUnleveled = outputPosition;
                internalStream.SetPrinterPosition(this.inputUnleveled);
            }
        }
Пример #3
0
        public override void SetPrinterPosition(PrinterMove outputPosition)
        {
            outputWithBabyStepping.CopyKnowSettings(outputPosition);

            // calculate our offset to pass on to internal streams
            inputNoBabyStepping           = outputWithBabyStepping;
            inputNoBabyStepping.position -= BabbyStepOffset;
            inputNoBabyStepping.position += extruderOffsets[Math.Min(extruderIndex, 4)];

            internalStream.SetPrinterPosition(inputNoBabyStepping);
        }
        public override string ReadLine()
        {
            var baseLine = base.ReadLine();

            if (baseLine == null)
            {
                return(null);
            }

            if (baseLine.EndsWith("; NO_PROCESSING"))
            {
                return(baseLine);
            }

            // if the line has no content don't process it
            if (baseLine.Length == 0 ||
                baseLine.Trim().Length == 0)
            {
                return(baseLine);
            }

            var lines = ProcessWriteRegEx(baseLine, printer);

            for (int i = lines.Count - 1; i >= 1; i--)
            {
                queueStream.Add(lines[i], true);
            }

            var lineToSend = lines[0];

            if (lineToSend != null &&
                LineIsMovement(lineToSend))
            {
                currentMove = GetPosition(lineToSend, currentMove);
            }

            // is it a position set?
            if (lineToSend.StartsWith("G92"))
            {
                GCodeFile.GetFirstNumberAfter("X", lineToSend, ref this.currentMove.position.X);
                GCodeFile.GetFirstNumberAfter("Y", lineToSend, ref this.currentMove.position.Y);
                GCodeFile.GetFirstNumberAfter("Z", lineToSend, ref this.currentMove.position.Z);
                GCodeFile.GetFirstNumberAfter("E", lineToSend, ref this.currentMove.extrusion);

                // tell the stream pipeline what the actual printer position is
                this.SetPrinterPosition(this.currentMove);
            }

            return(lineToSend);
        }
Пример #5
0
        public override string ReadLine()
        {
            if (!wroteLevelingStatus && LevelingActive)
            {
                wroteLevelingStatus = true;
                return("; Software Leveling Applied");
            }

            string lineToSend = base.ReadLine();

            if (lineToSend != null &&
                lineToSend.EndsWith("; NO_PROCESSING"))
            {
                return(lineToSend);
            }

            if (lineToSend == "; Software Leveling Applied")
            {
                gcodeAlreadyLeveled = true;
            }

            if (lineToSend != null &&
                LevelingActive &&
                !gcodeAlreadyLeveled)
            {
                if (LineIsMovement(lineToSend))
                {
                    PrinterMove currentUnleveledDestination = GetPosition(lineToSend, inputUnleveled);
                    var         leveledLine = GetLeveledPosition(lineToSend, currentUnleveledDestination);

                    // TODO: clamp to 0 - baby stepping - extruder z-offset, so we don't go below the bed (for the active extruder)

                    inputUnleveled = currentUnleveledDestination;

                    return(leveledLine);
                }
                else if (lineToSend.StartsWith("G29"))
                {
                    // remove G29 (machine prob bed) if we are running our own leveling.
                    lineToSend = base.ReadLine();                     // get the next line instead
                }
            }

            return(lineToSend);
        }
Пример #6
0
        public static PrinterMove GetPosition(string lineBeingSent, PrinterMove startPositionPosition)
        {
            if (lineBeingSent.StartsWith("G28") ||
                lineBeingSent.StartsWith("G29") ||
                lineBeingSent.StartsWith("G30"))
            {
                return(PrinterMove.Unknown);
            }

            PrinterMove currentDestination = startPositionPosition;

            GCodeFile.GetFirstNumberAfter("X", lineBeingSent, ref currentDestination.position.X);
            GCodeFile.GetFirstNumberAfter("Y", lineBeingSent, ref currentDestination.position.Y);
            GCodeFile.GetFirstNumberAfter("Z", lineBeingSent, ref currentDestination.position.Z);
            GCodeFile.GetFirstNumberAfter("E", lineBeingSent, ref currentDestination.extrusion);
            GCodeFile.GetFirstNumberAfter("F", lineBeingSent, ref currentDestination.feedRate);

            return(currentDestination);
        }
Пример #7
0
        public override string ReadLine()
        {
            string lineToSend = base.ReadLine();

            if (lineToSend != null &&
                lineToSend.EndsWith("; NO_PROCESSING"))
            {
                return(lineToSend);
            }

            if (lineToSend != null &&
                lineToSend.StartsWith("T"))
            {
                int extruder = 0;
                if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref extruder))
                {
                    extruderIndex = extruder;
                }
            }

            if (lineToSend != null &&
                LineIsMovement(lineToSend))
            {
                inputNoBabyStepping = GetPosition(lineToSend, inputNoBabyStepping);

                // it is a struct so this is making a new copy we con modify
                PrinterMove moveToSend = inputNoBabyStepping;
                moveToSend.position += BabbyStepOffset;
                moveToSend.position -= extruderOffsets[Math.Min(extruderIndex, 4)];

                if (moveToSend.HaveAnyPosition)
                {
                    lineToSend = CreateMovementLine(moveToSend, outputWithBabyStepping);
                }

                outputWithBabyStepping = moveToSend;

                return(lineToSend);
            }

            return(lineToSend);
        }
Пример #8
0
        public string CreateMovementLine(PrinterMove destination, PrinterMove start)
        {
            bool moveHasExtrusion = destination.extrusion != double.PositiveInfinity && destination.extrusion != start.extrusion;

            string command = (useG0ForMovement && !moveHasExtrusion) ? "G0 " : "G1 ";

            var sb = new StringBuilder(command);

            if (destination.position.X != start.position.X)
            {
                sb.AppendFormat("X{0:0.##} ", destination.position.X);
            }

            if (destination.position.Y != double.PositiveInfinity &&
                destination.position.Y != start.position.Y)
            {
                sb.AppendFormat("Y{0:0.##} ", destination.position.Y);
            }

            if (destination.position.Z != double.PositiveInfinity &&
                destination.position.Z != start.position.Z)
            {
                sb.AppendFormat("Z{0:0.###} ", destination.position.Z);
            }

            if (moveHasExtrusion)
            {
                sb.AppendFormat("E{0:0.###} ", destination.extrusion);
            }

            if (destination.feedRate != double.PositiveInfinity &&
                destination.feedRate != start.feedRate)
            {
                if (destination.feedRate > 0)
                {
                    sb.AppendFormat("F{0:0.##}", destination.feedRate);
                }
            }

            return(sb.ToString().Trim());
        }
Пример #9
0
        private string GetLeveledPosition(string lineBeingSent, PrinterMove currentDestination)
        {
            PrintLevelingData levelingData = printer.Settings.Helpers.PrintLevelingData;

            if (levelingData != null &&
                printer.Settings?.GetValue <bool>(SettingsKey.print_leveling_enabled) == true &&
                (lineBeingSent.StartsWith("G0 ") || lineBeingSent.StartsWith("G1 ")))
            {
                if (currentLevelingFunctions == null ||
                    currentProbeZOffset != printer.Settings.GetValue <Vector3>(SettingsKey.probe_offset) ||
                    !levelingData.SamplesAreSame(currentLevelingFunctions.SampledPositions))
                {
                    currentProbeZOffset      = printer.Settings.GetValue <Vector3>(SettingsKey.probe_offset);
                    currentLevelingFunctions = new LevelingFunctions(printer, levelingData);
                }

                lineBeingSent = currentLevelingFunctions.ApplyLeveling(lineBeingSent, currentDestination.position);
            }

            return(lineBeingSent);
        }
Пример #10
0
        private void ClampToPrinter(ref PrinterMove moveToSend)
        {
            var bounds = extruderBounds[printer.Connection.ActiveExtruderIndex];

            // clamp to each axis
            for (int i = 0; i < 3; i++)
            {
                if (moveToSend.position[i] < bounds.MinXYZ[i])
                {
                    moveToSend.position[i] = bounds.MinXYZ[i];
                    // If we clamp, than do not do any extrusion at all
                    moveToSend.extrusion = lastDestination.extrusion;
                }
                else if (moveToSend.position[i] > bounds.MaxXYZ[i])
                {
                    moveToSend.position[i] = bounds.MaxXYZ[i];
                    // If we clamp, than do not do any extrusion at all
                    moveToSend.extrusion = lastDestination.extrusion;
                }
            }
        }
        public override string ReadLine()
        {
            string lineToSend = internalStream.ReadLine();

            if (lineToSend != null &&
                lineToSend.EndsWith("; NO_PROCESSING"))
            {
                return(lineToSend);
            }

            if (lineToSend != null &&
                LineIsMovement(lineToSend))
            {
                PrinterMove currentMove = GetPosition(lineToSend, this.lastDestination);

                PrinterMove moveToSend = currentMove;
                // If we are on T1
                if (printer.Connection.ActiveExtruderIndex == 1)
                {
                    bool extrusionDelta  = currentMove.extrusion != this.lastDestination.extrusion;
                    bool xyPositionDelta = currentMove.position.X != this.lastDestination.position.X || currentMove.position.Y != this.lastDestination.position.Y;
                    // and there is both extrusion and position delta
                    if (extrusionDelta && xyPositionDelta)
                    {
                        // modify the speed by the T1 multiplier
                        moveToSend.feedRate *= t0Multiplier;
                    }
                }

                if (moveToSend.HaveAnyPosition)
                {
                    lineToSend = CreateMovementLine(moveToSend, this.lastDestination);
                }

                this.lastDestination = currentMove;
                return(lineToSend);
            }

            return(lineToSend);
        }
Пример #12
0
 public void CopyKnowSettings(PrinterMove copyFrom)
 {
     if (copyFrom.position.X != double.PositiveInfinity)
     {
         this.position.X = copyFrom.position.X;
     }
     if (copyFrom.position.Y != double.PositiveInfinity)
     {
         this.position.Y = copyFrom.position.Y;
     }
     if (copyFrom.position.Z != double.PositiveInfinity)
     {
         this.position.Z = copyFrom.position.Z;
     }
     if (copyFrom.extrusion != double.PositiveInfinity)
     {
         this.extrusion = copyFrom.extrusion;
     }
     if (copyFrom.feedRate != double.PositiveInfinity)
     {
         this.feedRate = copyFrom.feedRate;
     }
 }
Пример #13
0
 public override void SetPrinterPosition(PrinterMove position)
 {
     this.lastDestination.CopyKnowSettings(position);
     internalStream.SetPrinterPosition(lastDestination);
 }
Пример #14
0
        public override string ReadLine()
        {
            // Send any commands that are queue before moving on to the internal stream.
            string nextCommand = queuedCommands.ReadLine();

            if (nextCommand != null)
            {
                lastLine = nextCommand;
                return(nextCommand);
            }

            switch (RecoveryState)
            {
            // heat the extrude to remove it from the part
            case RecoveryState.RemoveHeating:
                // TODO: make sure we heat up all the extruders that we need to (all that are used)
                queuedCommands.Add("G21; set units to millimeters");
                queuedCommands.Add("M107; fan off");
                queuedCommands.Add("T0; set the active extruder to 0");
                queuedCommands.Add("G90; use absolute coordinates");
                queuedCommands.Add("G92 E0; reset the expected extruder position");
                queuedCommands.Add("M82; use absolute distance for extrusion");

                bool   hasHeatedBed = printer.Settings.GetValue <bool>(SettingsKey.has_heated_bed);
                double bedTemp      = printer.Settings.GetValue <double>(SettingsKey.bed_temperature);
                if (hasHeatedBed && bedTemp > 0)
                {
                    // start heating the bed
                    queuedCommands.Add($"M140 S{bedTemp}");
                }

                // heat up the extruder
                queuedCommands.Add("M109 S{0}".FormatWith(printer.Settings.Helpers.ExtruderTargetTemperature(0)));

                if (hasHeatedBed && bedTemp > 0)
                {
                    // finish heating the bed
                    queuedCommands.Add($"M190 S{bedTemp}");
                }

                RecoveryState = RecoveryState.Raising;
                lastLine      = "";
                return("");

            // remove it from the part
            case RecoveryState.Raising:
                // We don't know where the printer is for sure (it may have been turned off). Disable leveling until we know where it is.
                printer.Connection.AllowLeveling = false;
                queuedCommands.Add("M114 ; get current position");
                queuedCommands.Add("G91 ; move relative");
                queuedCommands.Add("G1 Z10 F{0}".FormatWith(printer.Settings.ZSpeed()));
                queuedCommands.Add("G90 ; move absolute");
                RecoveryState = RecoveryState.Homing;
                lastLine      = "";
                return("");

            // if top homing, home the extruder
            case RecoveryState.Homing:
                if (printer.Settings.GetValue <bool>(SettingsKey.z_homes_to_max))
                {
                    queuedCommands.Add("G28");
                }
                else
                {
                    // home x
                    queuedCommands.Add("G28 X0");
                    // home y
                    queuedCommands.Add("G28 Y0");
                    // move to the place we can home z from
                    Vector2 recoveryPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home);
                    queuedCommands.Add("G1 X{0:0.###}Y{1:0.###}F{2}".FormatWith(recoveryPositionXy.X, recoveryPositionXy.Y, printer.Settings.XSpeed()));
                    // home z
                    queuedCommands.Add("G28 Z0");
                }

                // We now know where the printer is re-enable print leveling
                printer.Connection.AllowLeveling = true;
                RecoveryState = RecoveryState.FindingRecoveryLayer;
                return("");

            // This is to recover printing if an out a filament occurs.
            // Help the user move the extruder down to just touching the part
            case RecoveryState.FindingRecoveryLayer:
                if (false)                         // help the user get the head to the right position
                {
                    // move to above the completed print
                    // move over a know good part of the model at the current top layer (extrude vertex from gcode)
                    // let the user move down until they like the height
                    // calculate that position and continue
                }
                else                         // we are resuming because of disconnect or reset, skip this
                {
                    RecoveryState = RecoveryState.SkippingGCode;
                    goto case RecoveryState.SkippingGCode;
                }

            case RecoveryState.SkippingGCode:
                // run through the gcode that the device expected looking for things like temp
                // and skip everything else until we get to the point we left off last time
                int commandCount = 0;
                boundsOfSkippedLayers = RectangleDouble.ZeroIntersection;
                while (internalStream.GCodeFile.PercentComplete(internalStream.LineIndex) < percentDone)
                {
                    string line = internalStream.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    commandCount++;

                    // make sure we don't parse comments
                    if (line.Contains(";"))
                    {
                        line = line.Split(';')[0];
                    }

                    lastDestination = GetPosition(line, lastDestination);

                    if (commandCount > 100)
                    {
                        boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy);
                    }

                    // check if the line is something we want to send to the printer (like a temp)
                    if (line.StartsWith("M109") ||                          // heat and wait extruder
                        line.StartsWith("M104") ||                                 // heat extruder
                        line.StartsWith("M190") ||                                 // heat and wait bed
                        line.StartsWith("M140") ||                                 // heat bed
                        line.StartsWith("T") ||                                 // switch extruder
                        line.StartsWith("M106") ||                                 // fan on
                        line.StartsWith("M107") ||                                 // fan off
                        line.StartsWith("G92"))                                    // set position
                    {
                        lastLine = line;

                        return(line);
                    }
                }

                RecoveryState = RecoveryState.PrimingAndMovingToStart;

                // make sure we always- pick up the last movement
                boundsOfSkippedLayers.ExpandToInclude(lastDestination.position.Xy);
                return("");

            case RecoveryState.PrimingAndMovingToStart:
            {
                if (printer.Settings.GetValue("z_homes_to_max") == "0")                                 // we are homed to the bed
                {
                    // move to the height we can recover printing from
                    Vector2 recoverPositionXy = printer.Settings.GetValue <Vector2>(SettingsKey.recover_position_before_z_home);
                    queuedCommands.Add(CreateMovementLine(new PrinterMove(new Vector3(recoverPositionXy.X, recoverPositionXy.Y, lastDestination.position.Z), 0, printer.Settings.ZSpeed())));
                }

                double extruderWidth = printer.Settings.GetValue <double>(SettingsKey.nozzle_diameter);
                // move to a position outside the printed bounds
                queuedCommands.Add(CreateMovementLine(new PrinterMove(
                                                          new Vector3(boundsOfSkippedLayers.Left - extruderWidth * 2, boundsOfSkippedLayers.Bottom + boundsOfSkippedLayers.Height / 2, lastDestination.position.Z),
                                                          0,
                                                          printer.Settings.XSpeed())));

                // let's prime the extruder
                queuedCommands.Add("G1 E10 F{0}".FormatWith(printer.Settings.EFeedRate(0))); // extrude 10
                queuedCommands.Add("G1 E9");                                                 // and retract a bit

                // move to the actual print position
                queuedCommands.Add(CreateMovementLine(new PrinterMove(lastDestination.position, 0, printer.Settings.XSpeed())));

                // reset the printer to know where the filament should be
                queuedCommands.Add("G92 E{0}".FormatWith(lastDestination.extrusion));
                RecoveryState = RecoveryState.PrintingSlow;
            }

                return("");

            case RecoveryState.PrintingSlow:
            {
                string lineToSend = internalStream.ReadLine();
                if (lineToSend == null)
                {
                    return(null);
                }

                if (!GCodeFile.IsLayerChange(lineToSend))
                {
                    // have not seen the end of this layer so keep printing slow
                    if (LineIsMovement(lineToSend))
                    {
                        PrinterMove currentMove = GetPosition(lineToSend, lastDestination);
                        PrinterMove moveToSend  = currentMove;

                        moveToSend.feedRate = recoverFeedRate;

                        lineToSend      = CreateMovementLine(moveToSend, lastDestination);
                        lastDestination = currentMove;
                        return(lineToSend);
                    }

                    lastLine = lineToSend;

                    return(lineToSend);
                }
            }

                // we only fall through to here after seeing the next "; Layer:"
                RecoveryState = RecoveryState.PrintingToEnd;
                return("");

            case RecoveryState.PrintingToEnd:
                return(internalStream.ReadLine());
            }

            return(null);
        }
Пример #15
0
        public override string ReadLine()
        {
            if (queuedCommands.Count > 0)
            {
                return(queuedCommands.Dequeue());
            }

            string lineToSend = base.ReadLine();

            if (lineToSend == null)
            {
                return(null);
            }

            if (lineToSend.EndsWith("; NO_PROCESSING"))
            {
                return(lineToSend);
            }

            var requestedToolForTempChange = -1;

            // if we see a temp command remember what heat we are setting
            if (lineToSend.StartsWith("M109") || lineToSend.StartsWith("M104"))
            {
                int toolTemp = 0;
                // get the temp we are setting
                GCodeFile.GetFirstNumberAfter("S", lineToSend, ref toolTemp);
                // set it to the tool we will be changing to
                requestedToolForTempChange = RequestedTool;
                // check if this command contains a tool specification
                GCodeFile.GetFirstNumberAfter("T", lineToSend, ref requestedToolForTempChange);

                if (!lineToSend.Contains("; INACTIVE_COOL_DOWN"))
                {
                    if (targetTemps[requestedToolForTempChange] != toolTemp)
                    {
                        targetTemps[requestedToolForTempChange] = toolTemp;
                    }
                }
            }

            // check if any of the heaters we will be switching to need to start heating
            ManageReHeating(lineToSend);

            if (lineToSend == completedBeforeGCodeString &&
                sendState != SendStates.Normal)
            {
                activeTool = RequestedTool;
                sendState  = SendStates.Normal;
                QueueAfterGCode();
            }

            var lineNoComment = lineToSend.Split(';')[0];

            if (lineNoComment == "G28" ||
                lineNoComment == "G28 Z0")
            {
                sendState     = SendStates.Normal;
                RequestedTool = activeTool = 0;
            }

            // if this command is a temperature change request
            if (requestedToolForTempChange != -1)
            {
                if (requestedToolForTempChange != activeTool)
                {
                    // For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not)
                    queuedCommands.Enqueue($"T{activeTool}");
                    var temp = GetNextToolTemp(requestedToolForTempChange);
                    if (temp > 0)
                    {
                        return($"{lineToSend.Substring(0, 4)} T{requestedToolForTempChange} S{temp}");
                    }
                    else                     // send the temp as requested
                    {
                        return(lineToSend);
                    }
                }

                // if we are waiting to switch to the next tool
                else if (activeTool != RequestedTool)
                {
                    // if this command does not include the extruder to switch to, than we need to switch before sending it
                    if (!lineNoComment.Contains("T"))
                    {
                        queuedCommands.Enqueue($"T{RequestedTool}");
                    }

                    // For smoothie, switch back to the extrude we were using before the temp change (smoothie switches to the specified extruder, marlin repetier do not)
                    queuedCommands.Enqueue($"T{activeTool}");
                    // then send the heat command
                    return(lineToSend);
                }
            }

            // if this is a tool change request
            else if (lineToSend.StartsWith("T"))
            {
                int changeCommandTool = -1;
                if (GCodeFile.GetFirstNumberAfter("T", lineToSend, ref changeCommandTool))
                {
                    if (changeCommandTool == activeTool)
                    {
                        if (sendState == SendStates.WaitingForMove)
                        {
                            // we have to switch back to our starting tool without a move
                            // change back to normal processing and don't change tools
                            sendState = SendStates.Normal;
                            var lastRequestedTool = RequestedTool;
                            // set the requested tool
                            RequestedTool = changeCommandTool;
                            // don't send the change are we are on the right tool now
                            return($"; switch back without move from T{lastRequestedTool} to T{activeTool}");
                        }
                    }
                    else                     // we are switching tools
                    {
                        if (sendState == SendStates.Normal)
                        {
                            sendState = SendStates.WaitingForMove;
                            // set the requested tool
                            RequestedTool = changeCommandTool;
                            // don't queue the tool change until after the before gcode has been sent
                            return($"; waiting for move on T{RequestedTool}");
                        }
                    }
                }
            }

            // if it is only an extrusion move
            if (sendState == SendStates.WaitingForMove &&
                activeTool != RequestedTool &&                 // is different than the last extruder set
                (lineNoComment.StartsWith("G0 ") || lineNoComment.StartsWith("G1 ")) &&                 // is a G1 or G0
                lineNoComment.Contains("E")                    // it is an extrusion move
                // and have no other position information
                && !lineNoComment.Contains("X") &&
                !lineNoComment.Contains("Y") &&
                !lineNoComment.Contains("Z"))
            {
                double ePosition = 0;

                if (GCodeFile.GetFirstNumberAfter("E", lineNoComment, ref ePosition))
                {
                    // switch extruders
                    queuedCommands.Enqueue($"T{RequestedTool}");

                    // if we know the current E position before the switch
                    // set the E value to the previous E value.
                    if (lastDestination.extrusion != double.PositiveInfinity)
                    {
                        // On Marlin E position is share between extruders and this code has no utility
                        // On Smoothie E is stored per extruder and this makes it behave the same as Marlin
                        queuedCommands.Enqueue($"G92 E{lastDestination.extrusion}");
                    }

                    // send the extrusion
                    queuedCommands.Enqueue(lineNoComment + " ; NO_PROCESSING");
                    // switch back
                    queuedCommands.Enqueue($"T{activeTool}");
                    lastDestination.extrusion = ePosition;
                    queuedCommands.Enqueue($"G92 E{lastDestination.extrusion}");
                    return("");
                }
            }

            if (QueueBeforeIfNeedToSwitchExtruders(lineToSend, lineNoComment))
            {
                return("");
            }

            if (LineIsMovement(lineToSend))
            {
                lastDestination = GetPosition(lineToSend, lastDestination);
            }

            return(lineToSend);
        }
        public override string ReadLine()
        {
            string lineToSend = null;

            // lock queue
            lock (locker)
            {
                if (commandQueue.Count > 0)
                {
                    lineToSend = commandQueue[0];
                    commandQueue.RemoveAt(0);
                }
            }

            if (lineToSend == null)
            {
                if (!printer.Connection.Paused)
                {
                    lineToSend = base.ReadLine();
                    if (lineToSend == null)
                    {
                        return(lineToSend);
                    }

                    if (lineToSend.EndsWith("; NO_PROCESSING"))
                    {
                        return(lineToSend);
                    }

                    // We got a line from the gcode we are sending check if we should queue a request for filament runout
                    if (printer.Settings.GetValue <bool>(SettingsKey.filament_runout_sensor))
                    {
                        // request to read the endstop state
                        if (!timeSinceLastEndstopRead.IsRunning || timeSinceLastEndstopRead.ElapsedMilliseconds > 5000)
                        {
                            printer.Connection.QueueLine("M119");
                            timeSinceLastEndstopRead.Restart();
                        }
                    }

                    lastSendTimeMs = UiThread.CurrentTimerMs;
                }
                else
                {
                    lineToSend = "";
                    // If more than 10 seconds have passed send a movement command so the motors will stay locked
                    if (UiThread.CurrentTimerMs - lastSendTimeMs > 10000)
                    {
                        printer.Connection.MoveRelative(PrinterAxis.X, .1, printer.Settings.Helpers.ManualMovementSpeeds().X);
                        printer.Connection.MoveRelative(PrinterAxis.X, -.1, printer.Settings.Helpers.ManualMovementSpeeds().X);
                        lastSendTimeMs = UiThread.CurrentTimerMs;
                    }
                }
            }

            if (GCodeFile.IsLayerChange(lineToSend))
            {
                int layerNumber = GCodeFile.GetLayerNumber(lineToSend);

                if (PauseOnLayer(layerNumber))
                {
                    this.DoPause(
                        PauseReason.PauseLayerReached,
                        // make the layer 1 based (the internal code is 0 based)
                        layerNumber + 1);
                }
            }
            else if (lineToSend.StartsWith("M226") ||
                     lineToSend.StartsWith("@pause"))
            {
                DoPause(PauseReason.GCodeRequest);
                lineToSend = "";
            }
            else if (lineToSend == "MH_PAUSE")
            {
                moveLocationAtEndOfPauseCode = LastDestination;

                if (printer.Connection.Printing)
                {
                    // remember where we were after we ran the pause gcode
                    printer.Connection.CommunicationState = CommunicationStates.Paused;
                }

                lineToSend = "";
            }
            else if (readOutOfFilament)
            {
                readOutOfFilament = false;
                DoPause(PauseReason.FilamentRunout);
                lineToSend = "";
            }

            // keep track of the position
            if (lineToSend != null &&
                LineIsMovement(lineToSend))
            {
                lastDestination = GetPosition(lineToSend, lastDestination);
            }

            return(lineToSend);
        }
 public override void SetPrinterPosition(PrinterMove position)
 {
     this.currentMove.CopyKnowSettings(position);
     internalStream.SetPrinterPosition(currentMove);
 }
Пример #18
0
 public override void SetPrinterPosition(PrinterMove position)
 {
 }
Пример #19
0
 public string CreateMovementLine(PrinterMove currentDestination)
 {
     return(CreateMovementLine(currentDestination, PrinterMove.Unknown));
 }
Пример #20
0
 /// <summary>
 /// Sends the printer position back up the stream pipe.
 /// </summary>
 /// <param name="position">The position as seen from down stream. Effectively what this stream will output after computation.</param>
 public abstract void SetPrinterPosition(PrinterMove position);
Пример #21
0
        public override string ReadLine()
        {
            if (movesToSend.Count == 0)
            {
                string lineToSend = base.ReadLine();

                if (lineToSend != null &&
                    lineToSend.EndsWith("; NO_PROCESSING"))
                {
                    return(lineToSend);
                }

                if (lineToSend != null &&
                    layerCount < 1 &&
                    GCodeFile.IsLayerChange(lineToSend))
                {
                    layerCount++;
                    if (layerCount == 1)
                    {
                        MaxSegmentLength = 5;
                    }
                }


                if (lineToSend != null &&
                    LineIsMovement(lineToSend))
                {
                    PrinterMove currentDestination = GetPosition(lineToSend, lastDestination);

                    if (currentDestination.FullyKnown)
                    {
                        PrinterMove deltaToDestination = currentDestination - lastDestination;
                        deltaToDestination.feedRate = 0;                         // remove the changing of the federate (we'll set it initially)
                        double lengthSquared = Math.Max(deltaToDestination.LengthSquared, deltaToDestination.extrusion * deltaToDestination.extrusion);
                        if (lengthSquared > MaxSegmentLength * MaxSegmentLength)
                        {
                            // create the line segments to send
                            double length = Math.Sqrt(lengthSquared);
                            int    numSegmentsToCutInto = (int)Math.Ceiling(length / MaxSegmentLength);

                            // segments = (((mm/min) / (60s/min))mm/s / s/segment)segments*mm / mm
                            double maxSegmentsCanTransmit = 1 / (((currentDestination.feedRate / 60) * maxSecondsPerSegment) / length);

                            int numSegmentsToSend = Math.Max(1, Math.Min(numSegmentsToCutInto, (int)maxSegmentsCanTransmit));

                            if (numSegmentsToSend > 1)
                            {
                                PrinterMove deltaForSegment = deltaToDestination / numSegmentsToSend;
                                PrinterMove nextPoint       = lastDestination + deltaForSegment;
                                nextPoint.feedRate = currentDestination.feedRate;
                                for (int i = 0; i < numSegmentsToSend; i++)
                                {
                                    lock (movesToSend)
                                    {
                                        movesToSend.Add(nextPoint);
                                    }

                                    nextPoint += deltaForSegment;
                                }

                                // send the first one
                                PrinterMove positionToSend = movesToSend[0];
                                lock (movesToSend)
                                {
                                    movesToSend.RemoveAt(0);
                                }

                                string altredLineToSend = CreateMovementLine(positionToSend, lastDestination);
                                lastDestination = positionToSend;
                                return(altredLineToSend);
                            }
                        }
                    }

                    lastDestination = currentDestination;
                }
                return(lineToSend);
            }
            else
            {
                PrinterMove positionToSend = movesToSend[0];
                lock (movesToSend)
                {
                    movesToSend.RemoveAt(0);
                }

                string lineToSend = CreateMovementLine(positionToSend, lastDestination);

                lastDestination = positionToSend;

                return(lineToSend);
            }
        }
Пример #22
0
        private void QueueAfterGCode()
        {
            string afterGcodeToQueue = "";

            switch (RequestedTool)
            {
            case 0:
                afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode).Replace("\\n", "\n");
                break;

            case 1:
                afterGcodeToQueue = printer.Settings.GetValue(SettingsKey.toolchange_gcode_1).Replace("\\n", "\n");
                break;
            }

            PrinterMove newToolMove     = GetPosition(postSwitchLine, PrinterMove.Unknown);
            var         newToolPosition = newToolMove.position;
            var         lineNoComment   = postSwitchLine.Split(';')[0];

            // if there is no extrusion we can move directly to the desired position after the extruder switch.
            // Otherwise we need to go to the last position to start the extrusion.
            if (!lineNoComment.Contains("E"))
            {
                newToolPosition.X = newToolPosition.X == double.PositiveInfinity ? preSwitchPosition.X : newToolPosition.X;
                newToolPosition.Y = newToolPosition.Y == double.PositiveInfinity ? preSwitchPosition.Y : newToolPosition.Y;
            }

            // no matter what happens with the x and y we want to set our z if we have one before
            newToolPosition.Z = newToolPosition.Z == double.PositiveInfinity ? preSwitchPosition.Z : newToolPosition.Z;

            // put together the output we want to send
            var gcode = new StringBuilder();

            // If the printer is heating, make sure we are at temp before switching extruders
            var nextToolTargetTemp      = targetTemps[RequestedTool];
            var currentPrinterTargeTemp = printer.Connection.GetTargetHotendTemperature(RequestedTool);

            if (currentPrinterTargeTemp > 0 &&
                printer.Connection.GetActualHotendTemperature(RequestedTool) < nextToolTargetTemp - 3)
            {
                // ensure our next tool is at temp (the one we are switching to)
                gcode.AppendLine($"M109 T{RequestedTool} S{nextToolTargetTemp}");
            }

            if (afterGcodeToQueue.Trim().Length > 0)
            {
                gcode.Append(printer.Settings.ReplaceMacroValues(afterGcodeToQueue));
            }

            // move to selected tool to the last tool position at the travel speed
            if (newToolPosition.X != double.PositiveInfinity &&
                newToolPosition.Y != double.PositiveInfinity)
            {
                gcode.AppendLine($"\n G1 X{newToolPosition.X}Y{newToolPosition.Y}F{printer.Settings.XSpeed()}");
            }

            // move to the z position
            if (newToolPosition.Z != double.PositiveInfinity)
            {
                gcode.AppendLine($"G1 Z{newToolPosition.Z}F{printer.Settings.ZSpeed()}");
            }

            // set the feedrate back to what was before we added any code
            if (preSwitchFeedRate != double.PositiveInfinity)
            {
                gcode.AppendLine($"G1 F{preSwitchFeedRate}");
            }

            // and queue the travel
            gcode.AppendLine(postSwitchLine);

            queuedCommandsStream.Add(gcode.ToString());
        }