C# Skript Beispiel »

3D Drucker

davidson | 30.01.2021 | 1.3 | Stable | Skripte

Beschreibung:


Mit diesem Skript ist es möglich, eine Kombination aus Kolben und einem Schweißgerät als 3D-Drucker zu verwenden.

Basierend auf einer einfachen Einrichtung kannst Du Druck-Sequenzen erstellen, indem Du den Programmierbaren Block mit definierten Argumenten ausführen.
 Gültige Namen der Kolben:
- X
- x1
- KolbenX1
Du musst mindestens ein x, y oder z (je nach Achse) im Kolbennamen haben
      
Ein Argument wird folgendermaßen gebildet:
<Achsenname><Richtung[+/-]><Schritt>[,<Nächstes Argument für Sequenzen>,...]

Gültige Argumente sind zum Beispiel:
x+1  => bewegt den Drucker um 1 Schritt vorwärts auf der x-Achse
y-1  => bewegt den Drucker um 1 Schritt auf der y-Achse zurück
oder Sequenzen:
x+1,y+1,z+1,action|on,x+4,action|off,reset[,...]
               
Das Argument "reset" setzt alle Kolben auf Null zurück.

Optional kann ein LCD mit dem Namen "LCD Log" zur Protokollierung von Informationen verwendet werden
Argument "clearlog" löscht den Log-Bildschirm.

Im Skript kannst Du noch folgende Einstellungen vornehmen:

// Gib den Namen des Druckerkopf an, wird benötigt wenn Du das Argument "action" verwenden willst (kann ein Bohrer, Schweißer etc. sein)
string PrinterHeadBlockName = "";

// Standardwert zum Verringern/Erhöhen der Kolben, wird bei Argumenten der Form x+, x-, y+,y-, z+ und z- verwendet
float Schritt = 1.0F;

// Aus-/Einfahrgeschwindigkeit der Kolben
float Geschwindigkeit = 0.5F;

Am besten legst Du dir die verschiedenen Aktionen auf Knöpfe der Schaltkonsole. Dazu im Bedienfeld die Aktion der Knöpfe konfigurieren:
Programmierbarer Block > Ausführen > Gewünschtes Argument eingeben

Benötigt:

min 1 Kolben in jede Achsenrichtung (beliebig viele sind möglich)

Druckkopf (Bohrer, Schweißer o.ä.)

1x Programmierbarer Block

Schaltkonsole

Steam Workshop

Das Skript gibt es auch im Workshop: https://steamcommunity.com/sharedfiles/filedetails/?id=2376883341


Screenshots


Exemplarischer Aufbau - Drucker, Schaltkonsole und Log LCD

Schaltkonsole mit allen Befehlen für den Drucker

Aufbau des Druckers: Es sollten Kolben für alle Achsenrichtungen vorhanden sein. Die Anzahl ist nicht begrenzt.


Source Code


        /*
                #################################################################
                #  3D Printer Script                                                                                     #
                #  by Dav1dson  Visit us on www.spaceengineering.de                      &nbsp; #
                #################################################################

                Valid names of pistons:
                - X
                - x1
                - PistonX1
                At least, they must have an x, y or z (depending on the axis) in its names
                ----------------------------------------------------------------------------------------------------------------------
                An argument is build by:
                <axis-name><direction[+/-]><step>[,<next argument for sequences>,...]

                Valid arguments are fo example:
                - x+1
                   => will move printer 1 step forward on x-axis
                - y-1
                   => will move printer 1 step back on y-axis
                - or sequences:
                   x+1,y+1,z+1,action|on,x+4,action|off,reset[,...]
                ----------------------------------------------------------------------------------------------------------------------
                Argument "reset" turns all pistons back to zero
                ----------------------------------------------------------------------------------------------------------------------
                Optional an LCD with name ""LCD Log" can be used for Logging informations
                ----------------------------------------------------------------------------------------------------------------------
                Argument "clearlog" clears log
                ----------------------------------------------------------------------------------------------------------------------
       */

        // Set the name for the Printer block if u want to use the "action" argument (drill,welder etc)
        string PrinterHeadBlockName = "";
        // -----------------------------------------------------------------
        // default de-/increase value of pistons
        float Step = 1.0F;
        // -----------------------------------------------------------------
        // default de-/increase speed of pistons
        float Speed = 0.5F;
        // -----------------------------------------------------------------

        IMyTerminalBlock printerHeadBlock = null;
        public List<IMyTerminalBlock> PistonsX;
        public List<IMyTerminalBlock> PistonsY;
        public List<IMyTerminalBlock> PistonsZ;
        public IMyTextPanel panel;

        public List<string> Queue;

        public IMyPistonBase lastPiston = null;

        public bool isRunning = false;

        public Program()
        {
            try
            {
                Runtime.UpdateFrequency = UpdateFrequency.Update100;
                this.PistonsX = new List<IMyTerminalBlock>();
                this.PistonsY = new List<IMyTerminalBlock>();
                this.PistonsZ = new List<IMyTerminalBlock>();
                GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(PistonsX, x => x.CustomName.Contains("X") || x.CustomName.Contains("x"));
                GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(PistonsY, x => x.CustomName.Contains("Y") || x.CustomName.Contains("y"));
                GridTerminalSystem.GetBlocksOfType<IMyPistonBase>(PistonsZ, x => x.CustomName.Contains("Z") || x.CustomName.Contains("z"));
                panel = GridTerminalSystem.GetBlockWithName("LCD Log") as IMyTextPanel;
                if (PrinterHeadBlockName != "")
                {
                    printerHeadBlock = GridTerminalSystem.GetBlockWithName(PrinterHeadBlockName) as IMyTerminalBlock;
                }
                Queue = new List<string>();
            }
            catch (Exception e)
            {
                Echo(e.Message);
            }
        }

        public void Main(string argument, UpdateType updateType)
        {
            try
            {
                if (updateType == UpdateType.Update100)
                {
                    if (Queue.Count > 0)
                    {

                        if (!isRunning &&
                            (lastPiston == null ||
                            (lastPiston.Status != PistonStatus.Extending
                            && lastPiston.Status != PistonStatus.Retracting))
                            )
                        {
                            isRunning = true;
                            Log("Process " + Queue[0] + "...");
                            ProcessCommand(Queue[0]);
                            isRunning = false;
                            Queue.RemoveAt(0);
                            Runtime.UpdateFrequency = UpdateFrequency.Update100;
                        }
                    }
                    else
                    {
                        Runtime.UpdateFrequency = UpdateFrequency.None;
                        isRunning = false;
                    }
                }

                if (!isRunning && updateType == UpdateType.Trigger)
                {
                    if (argument == "reset")
                    {
                        isRunning = true;
                        this.Reset();
                        isRunning = false;
                    }
                    else if (argument == "clearlog")
                    {
                        isRunning = true;
                        if (panel != null)
                        {
                            panel.WriteText("", false);
                        }
                        isRunning = false;
                    }
                    else
                    {

                        string[] args = argument.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (string arg in args)
                        {
                            Queue.Add(arg);
                        }
                        Runtime.UpdateFrequency = UpdateFrequency.Update100;
                    }
                }
            }
            catch (Exception e)
            {
                Echo(e.Message);
            }
        }

        private bool ProcessCommand(string arg)
        {
            //Log("Argument: " + arg);
            // action for "printer head"
            if (arg.Length >= 7 && arg.Substring(0, 7) == "action|")
            {
                if (printerHeadBlock != null)
                {
                    string[] parts = arg.Split('|');
                    if (parts[1].ToLower() == "on")
                    {
                        printerHeadBlock.ApplyAction("OnOff_On");
                        Log("Block " + PrinterHeadBlockName + " turned on...");
                    }
                    else if (parts[1].ToLower() == "off")
                    {
                        printerHeadBlock.ApplyAction("OnOff_Off");
                        Log("Block " + PrinterHeadBlockName + " turned off...");
                    }
                    else
                    {
                        Log("Command " + parts[1] + " is unknown, possible values are: on, off");
                    }
                }
                else
                {
                    Log("Block " + PrinterHeadBlockName + " not found!");
                }
                return true;
            }
            // action reset all pistons
            else if (arg == "reset")
            {
                this.Reset();
                return true;
            }
            // move printer
            else
            {
                Log("Move: " + arg);
                int Direction = 1;
                string dir = "+";
                string axis;
                if (arg.Length == 2)
                {
                    axis = arg.Substring(0, 1).ToLower(); // x, y or z
                    dir = arg.Substring(1, 1); // - or +
                }
                else if (arg.Length >= 3)
                {
                    axis = arg.Substring(0, 1).ToLower(); // x, y or z
                    dir = arg.Substring(1, 1); // - or +
                    Step = float.Parse(arg.Substring(2)); // 1, 14 or 12.4
                }
                else
                {
                    throw new Exception("Invalid argument: " + arg);
                }
                if (dir == "-")
                {
                    Direction = -1;
                }
                else
                {
                    Direction = 1;
                }
                return this.SetNewPistonPosition(axis, Step, Direction);
            }
        }

        private bool SetNewPistonPosition(string axis, float step, int Direction)
        {
            float stepPerPiston;
            string dir = "forward";
            if (Direction == -1)
            {
                dir = "backward";
            }
            this.Log("Set " + axis + "-Axis " + step + " Step(s) " + dir);
            switch (axis)
            {
                case "x":
                    stepPerPiston = step / PistonsX.Count;
                    this.Log("Step per Piston:  " + stepPerPiston);
                    lastPiston = (IMyPistonBase)PistonsX[0];
                    foreach (IMyPistonBase piston in this.PistonsX)
                    {
                        float oldStepLower = piston.MinLimit;
                        float oldStepUpper = piston.MaxLimit;
                        float newStep = oldStepLower + (stepPerPiston * Direction);
                        if ((Direction == -1 && newStep >= piston.LowestPosition)
                            || (Direction == 1 && newStep <= piston.HighestPosition)
                            )
                        {
                            piston.MinLimit = newStep;
                            piston.MaxLimit = newStep;
                            piston.Velocity = (Speed * Direction);
                        }
                        lastPiston = piston;
                    }
                    break;
                case "y":
                    stepPerPiston = step / PistonsY.Count;
                    this.Log("Step per Piston:  " + stepPerPiston);
                    lastPiston = (IMyPistonBase)PistonsY[0];
                    foreach (IMyPistonBase piston in this.PistonsY)
                    {
                        float oldStepLower = piston.MinLimit;
                        float oldStepUpper = piston.MaxLimit;
                        float newStep = oldStepLower + (stepPerPiston * Direction);
                        if ((Direction == -1 && newStep >= piston.LowestPosition)
                            || (Direction == 1 && newStep <= piston.HighestPosition)
                            )
                        {
                            piston.MinLimit = newStep;
                            piston.MaxLimit = newStep;
                            piston.Velocity = (Speed * Direction);
                        }
                        lastPiston = piston;
                    }
                    break;
                case "z":
                    stepPerPiston = step / PistonsZ.Count;
                    this.Log("Step per Piston:  " + stepPerPiston);
                    lastPiston = (IMyPistonBase)PistonsZ[0];
                    foreach (IMyPistonBase piston in this.PistonsZ)
                    {
                        float oldStepLower = piston.MinLimit;
                        float oldStepUpper = piston.MaxLimit;
                        float newStep = oldStepLower + (stepPerPiston * Direction);
                        if ((Direction == -1 && newStep >= piston.LowestPosition)
                           || (Direction == 1 && newStep <= piston.HighestPosition)
                           )
                        {
                            piston.MinLimit = newStep;
                            piston.MaxLimit = newStep;
                            piston.Velocity = (Speed * Direction);
                        }
                        lastPiston = piston;
                    }
                    break;
            }
            Log($"{lastPiston.CustomName}: {lastPiston.Status}");
            return true;
        }

        private void Log(string message)
        {
            if (panel != null)
            {
                panel.WriteText(message + Environment.NewLine, true);
            }
        }

        private void Reset()
        {
            Log("Reset all Pistons");
            foreach (IMyPistonBase piston in this.PistonsX)
            {
                piston.MinLimit = 0;
                piston.MaxLimit = 0;
                piston.Velocity = (Speed * -1);
            }
            foreach (IMyPistonBase piston in this.PistonsY)
            {
                piston.MinLimit = 0;
                piston.MaxLimit = 0;
                piston.Velocity = (Speed * -1);
            }
            foreach (IMyPistonBase piston in this.PistonsZ)
            {
                piston.MinLimit = 0;
                piston.MaxLimit = 0;
                piston.Velocity = (Speed * -1);
            }
        }