goldfiction

rotor script se

May 8th, 2019
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.     /*  
  2.     Script for automatic rotor stop when a solar panel or oxygen farm has high output.  
  3.     Version: 1.11
  4.     Sigurd Hansen
  5.    
  6.     This program vil autostart at compile. Use argument stop or start to manually override
  7.  
  8.     */  
  9.     #region Configuration  
  10.      
  11.     // HighPwrValue - Set this to your minimum power requirement in kW per panel. (Or oxygen L/min)  
  12.     const float HighPwrValue = 119.4f;  
  13.      
  14.     // NameOfSolar - Search for solar blocks or oxygen farms with this name.  
  15.     //  Maximum one item per array should be returned. Multiple arrays supported.  
  16.     const string NameOfSolar = "SolarMain";  
  17.      
  18.     // NameOfRotorX - Search for rotor blocks with this name. Maximum one item per array should be returned.  
  19.     //  Multiple arrays supported.  
  20.     const string NameOfRotorX = "RotorX";  
  21.      
  22.     // rotorspeed - Maximum speed of rotor. Will be dynamically adjusted down when close to target.  
  23.     //  Recommended value: Less that 1.0f due to ingame bug
  24.     const float rotorspeed = 0.8f;  
  25.  
  26.     // EnableTwoAxisMode - Enable dual axis mode.  
  27.     //  Recommended value: Depends on design.  
  28.     const bool EnableTwoAxisMode = true;  
  29.      
  30.     // NameOfRotorY - Search for this name for Y axis. Must only find Y axis rotors.  
  31.     //  Maximum one item per array should be returned. Multiple arrays supported.  
  32.     const string NameOfRotorY = "RotorY";  
  33.      
  34.     // EnableOxygenMode - Enables oxygen mode.  
  35.     const bool EnableOxygenMode = false;  
  36.      
  37.     // Auto set torque and braking torque to best practice value.  
  38.     //  Recommended value: true  
  39.     const bool ForceAutoTorque = true;
  40.  
  41.     // Enable LCD Output
  42.     const bool EnableLCD = true;
  43.     const string NameOfLCD = "LCDSolar";
  44.      
  45.     // Duplication  
  46.     // Applying rotor values to other rotors as well if set to true.  
  47.     //  If unsure, set all to false. Recommended value: Depends on design.  
  48.     const bool EnableDuplicateRotor1 = true;  
  49.     const bool EnableDuplicateRotor2 = true;  
  50.     const bool EnableDuplicateRotor3 = false;  
  51.      
  52.     // You might want to inverse some rotors, for example on the other side of the axis.  
  53.     //  If so, set the value to true. If unsure change later if rotors lock at wrong angle.  
  54.     const bool InverseDuplicateRotor1 = false;  
  55.     const bool InverseDuplicateRotor2 = true;  
  56.     const bool InverseDuplicateRotor3 = false;  
  57.      
  58.     // Enter the name of the source rotors you want to duplicate.  
  59.     const string NameOfDuplicateSource1 = "RotorY";  
  60.     const string NameOfDuplicateSource2 = "RotorY";  
  61.     const string NameOfDuplicateSource3 = "RotorF";  
  62.      
  63.     // Enter the name of the destination rotors you want to duplicate.  
  64.     //  The code will search for rotors. For example:  
  65.     //  Entering RotorZ will duplicate changes to RotorZa, RotorZB, RotorZQ and so forth.  
  66.     const string SearchForDuplicateDest1 = "RotorZ";  
  67.     const string SearchForDuplicateDest2 = "RotorH";  
  68.     const string SearchForDuplicateDest3 = "RotorG";  
  69.      
  70.     // Auto night mode (Beta)  
  71.     //  Turns off rotors if night is detected. Suboptimal axis towards sun might trigger night mode at daytime.  
  72.     //  Use at your own risk. Not recommended for ships.  
  73.     const bool AutoNightMode = false;
  74.      
  75.     // Trigger this timer at max power
  76.     const bool ControlCustomTimerAtMaxPower = false;
  77.     const string NameForCustomtriggerAtMaxPower = "Timertest1";
  78.      
  79.     // Trigger this timer at low power
  80.     const bool ControlCustomTimerAtLowPower = false;
  81.     const string NameForCustomtriggerAtLowPower = "Timertest2";
  82.    
  83.     // Changes below this line not recommended.  
  84.     //------------------------------------------------------------  
  85.     #endregion
  86.     // Quick fix to disable useless warnings
  87.     #pragma warning disable 0162
  88.     List<IMyTerminalBlock> solarBlocks = new List<IMyTerminalBlock>();  
  89.     List<IMyTerminalBlock> rotorBlocksX = new List<IMyTerminalBlock>();  
  90.     List<IMyTerminalBlock> rotorBlocksY = new List<IMyTerminalBlock>();  
  91.     List<IMyTerminalBlock> Rotors = new List<IMyTerminalBlock>();  
  92.     List<IMyTerminalBlock> SourceRotors = new List<IMyTerminalBlock>();  
  93.     List<IMyTerminalBlock> LcdBlocks = new List<IMyTerminalBlock>();
  94.     IMyTimerBlock timer2;
  95.     IMyTimerBlock timer3;
  96.     bool firstrun = true;  
  97.     bool nightmode = false;  
  98.     long lCount = 0;
  99.     int delayCount = 0;
  100.     string textToLCD = "";
  101.  
  102. public Program() {
  103.     Runtime.UpdateFrequency |= UpdateFrequency.Update100;
  104. }
  105.    
  106.     #region Main  
  107.     void Main(string argument)  
  108.     {  
  109.         if (firstrun) {
  110.             // Echo = text => {}; // Uncommenting this line might increase performance on servers. Will disable echo
  111.             GridTerminalSystem.SearchBlocksOfName(NameOfSolar, solarBlocks); // Search for Solar Blocks  
  112.             GridTerminalSystem.SearchBlocksOfName(NameOfRotorX, rotorBlocksX); // Search for Rotor Blocks  
  113.             GridTerminalSystem.SearchBlocksOfName(NameOfRotorY, rotorBlocksY); // Search for RotorY Blocks
  114.             if (EnableLCD) GridTerminalSystem.SearchBlocksOfName(NameOfLCD, LcdBlocks); // Search for LCD Blocks
  115.             if (solarBlocks.Count == 0) { throw new Exception("Cannot find solar panel. Check name and recompile."); }  
  116.             if (rotorBlocksX.Count == 0) { throw new Exception("Cannot find x-axis rotor blocks. Check name and recompile."); }  
  117.             if (rotorBlocksY.Count == 0 && EnableTwoAxisMode) { throw new Exception("Cannot find y-axis rotor blocks. Check name and recompile."); }  
  118.             if (rotorBlocksY.Count < rotorBlocksX.Count && EnableTwoAxisMode) {  
  119.                 int diff = rotorBlocksX.Count - rotorBlocksY.Count;  
  120.                 throw new Exception(diff + " Y-axis rotors missing. Fix and recompile.");  
  121.             }  
  122.             if (solarBlocks.Count > rotorBlocksX.Count) { throw new Exception("Too many solar panels found. Check solar panel names."); }  
  123.             Echo ("Init...\nX rotors: " + rotorBlocksX.Count.ToString() + "\nY rotors: " + rotorBlocksY.Count.ToString());  
  124.             Echo ("Solar panels/Oxygen farms: " + solarBlocks.Count.ToString());  
  125.             if (EnableTwoAxisMode) Echo ("Dual Axis mode enabled");  
  126.             if (EnableOxygenMode) Echo ("Oxygen Farm mode ON");  
  127.             if (EnableDuplicateRotor1 || EnableDuplicateRotor2 || EnableDuplicateRotor3) Echo ("Duplication activated.");
  128.             if (ControlCustomTimerAtMaxPower) timer2 = GridTerminalSystem.GetBlockWithName(NameForCustomtriggerAtMaxPower) as IMyTimerBlock;
  129.             if (ControlCustomTimerAtLowPower) timer3 = GridTerminalSystem.GetBlockWithName(NameForCustomtriggerAtLowPower) as IMyTimerBlock;
  130.  
  131.             firstrun = false;  
  132.         }
  133.             if (argument == "start") Runtime.UpdateFrequency |= UpdateFrequency.Update100;
  134.             else if (argument == "stop") Runtime.UpdateFrequency &= ~UpdateFrequency.Update100;
  135.             lCount++;
  136.             if (lCount == 3) {
  137.                 lCount = 0;
  138.             } else return;
  139.         textToLCD = "Auto aligning solar panels\n";
  140.         bool[] rotorOn = new bool[rotorBlocksX.Count]; // Stop or start rotor  
  141.         bool[] rotorLow = new bool[rotorBlocksX.Count]; // True when power is way to low  
  142.         bool[] rotorFineTune = new bool[rotorBlocksX.Count]; // Fine Tune, very slow rotor  
  143.         bool[] reverse = new bool[rotorBlocksX.Count]; // Reverse rotor    
  144.         bool[] rotorOnY = new bool[rotorBlocksY.Count]; // Stop or start rotor  
  145.        
  146.         bool containsFalse = false; // Dynamic timer management. Increase or decrease timer  
  147.         float pwr = 0f, lastPwr = 0f; // Current and last power reading  
  148.      
  149.         if (EnableOxygenMode) {  
  150.             for(int i = 0; i < solarBlocks.Count; i++) { // For each oxygen farm...  
  151.             var solar = solarBlocks[i] as IMyOxygenFarm; // Support for oxygen farm  
  152.             if(solar != null) { // Yes I am  
  153.                 GetOxygen(solar, ref pwr); // Get oxygen level, return into existing pwr variable  
  154.                 lastPwr = GetAndSetLastOxygen(solar, pwr); // Get and set last runs oxygen level  
  155.                 reverse[i] = (lastPwr < pwr || pwr == 0) ? false : true; // Change rotor direction  
  156.                 rotorOn[i] = (pwr <= HighPwrValue) ? true : false; // Turn on rotor  
  157.                 rotorLow[i] = (pwr < HighPwrValue/2) ? true : false; // Slow or fast rotor  
  158.                 rotorFineTune[i] = (pwr > HighPwrValue*10/11) ? true : false; // Fine tune rotor  
  159.                 }  
  160.             }  
  161.         }   else {  
  162.             for(int i = 0; i < solarBlocks.Count; i++) { // For each solar panel...  
  163.             var solar = solarBlocks[i] as IMySolarPanel; // I am a Solar Panel  
  164.             if(solar != null) { // Yes I am  
  165.                 GetPower(solar, ref pwr); // Get Power from solar panel, return into existing pwr variable  
  166.                 lastPwr = GetAndSetLastPwr(solar, pwr); // Get and set last runs power  
  167.                 reverse[i] = (lastPwr < pwr || pwr == 0) ? false : true; // Change rotor direction  
  168.                 rotorOn[i] = (pwr <= HighPwrValue) ? true : false; // Turn on rotor  
  169.                 rotorLow[i] = (pwr < HighPwrValue/2) ? true : false; // Slow or fast rotor  
  170.                 rotorFineTune[i] = (pwr > HighPwrValue*10/11) ? true : false; // Fine tune rotor  
  171.                 if (lastPwr == 0 && pwr == 0 && AutoNightMode || Me.TerminalRunArgument == "Nightmode") { // TEST  
  172.                     nightmode = true;  
  173.                 } else {  
  174.                     nightmode = false;  
  175.                 }  
  176.                 }  
  177.             }  
  178.         }  
  179.         if (nightmode) {  
  180.             Echo ("Night mode.");  
  181.             // Do other stuff  
  182.         }  
  183.          
  184.         for(int i = 0; i < rotorBlocksX.Count; i++) { // For each rotorX...  
  185.             IMyMotorStator rotor = rotorBlocksX[i] as IMyMotorStator; // I am a Rotor  
  186.             if(rotor != null) { // Yes I am  
  187.                 if (ForceAutoTorque) { // Force torque.
  188.                     rotor.BrakingTorque = float.MaxValue;
  189.                     rotor.Torque = 30000000f;  
  190.                 }  
  191.                 if (nightmode) {  
  192.                     TriggerRotor(rotor, false, false, ref containsFalse); // Stop rotor  
  193.                 } else {  
  194.                     SetRotorSpeed(rotor, rotorLow[i], rotorFineTune[i]); // Dynamic rotor speed  
  195.                     if (!rotorOn[i]) { // Turn off...  
  196.                         TriggerRotor(rotor, false, false, ref containsFalse); // Stop rotor  
  197.                     }           else if (rotorOn[i] && EnableTwoAxisMode && reverse[i]) { // Turn On, dual axis mode, and reverse  
  198.                         rotorOnY[i] = CheckAndUpdateRotorName(rotor);  
  199.                         if (rotorOnY[i]) {  
  200.                             TriggerRotor(rotor, false, false, ref containsFalse); // Y on, therefore X off.  
  201.                         }  
  202.  
  203.                         if (!rotorOnY[i]) {  
  204.                             TriggerRotor(rotor, true, reverse[i], ref containsFalse); // Y off, therefore X on, and reverse.  
  205.                         }  
  206.                     }   else if (rotorOn[i] && EnableTwoAxisMode && !reverse[i]) {  
  207.                         rotorOnY[i] = CheckAndUpdateRotorName(rotor);  
  208.                         if (!rotorOnY[i]) {  
  209.                             TriggerRotor(rotor, true, reverse[i], ref containsFalse); // Start rotor. Reverse if needed  
  210.                         }  
  211.                     }   else {  
  212.                         TriggerRotor(rotor, true, reverse[i], ref containsFalse); // Start rotor. Reverse if needed  
  213.                     }  
  214.                 }  
  215.             }  
  216.         }  
  217.      
  218.         if (EnableTwoAxisMode) {  
  219.             for(int i = 0; i < rotorBlocksY.Count; i++) { // For each rotorY...  
  220.                 IMyMotorStator rotor = rotorBlocksY[i] as IMyMotorStator; // I am a Rotor  
  221.                 if(rotor != null) { // Yes I am  
  222.                     if (ForceAutoTorque) {  
  223.                     rotor.BrakingTorque = float.MaxValue;
  224.                     rotor.Torque = 30000000f;
  225.                     }  
  226.                     if (nightmode) {  
  227.                         TriggerRotor(rotor, false, false, ref containsFalse); // Stop rotor  
  228.                     } else {  
  229.                         if (rotorOnY[i] == true) {  
  230.                             SetRotorSpeed(rotor, rotorLow[i], rotorFineTune[i]); // Dynamic rotor speed  
  231.                             TriggerRotor(rotor, true, reverse[i], ref containsFalse); // Start rotor Y. Reverse if needed  
  232.                         } else {  
  233.                             TriggerRotor(rotor, false, false, ref containsFalse);  
  234.                         }  
  235.                     }  
  236.                 }  
  237.             }  
  238.         }  
  239.      
  240.         // Duplicate stuff  
  241.     if (EnableDuplicateRotor3 && !containsFalse) { // Main rotors aligned, lets duplicate changes...    
  242.             RotorDuplicate(NameOfDuplicateSource3, SearchForDuplicateDest3, InverseDuplicateRotor3);    
  243.         }  
  244.         if (EnableDuplicateRotor2 && !containsFalse) { // Main rotors aligned, lets duplicate changes...  
  245.             RotorDuplicate(NameOfDuplicateSource2, SearchForDuplicateDest2, InverseDuplicateRotor2);  
  246.         }  
  247.         if (EnableDuplicateRotor1 && !containsFalse) { // Main rotors aligned, lets duplicate changes...  
  248.             RotorDuplicate(NameOfDuplicateSource1, SearchForDuplicateDest1, InverseDuplicateRotor1);  
  249.         }
  250.     if (!containsFalse && ControlCustomTimerAtMaxPower) { // Main rotors aligned, lets control a timer
  251.         delayCount = 0;
  252.         ControlTimer(timer2);
  253.         }
  254.     if (containsFalse && ControlCustomTimerAtLowPower){
  255.             delayCount++;
  256.             if (delayCount == 5) {
  257.                 delayCount = 0;
  258.                 ControlTimer(timer3);
  259.             }        
  260.         }
  261.     if (EnableLCD) PrintToLCD(textToLCD);
  262.     }
  263.  
  264.     #endregion       
  265.     #region Methods  
  266.  
  267.     void PrintToLCD(string text) {
  268.         if (EnableLCD) {
  269.             for(int i = 0; i < LcdBlocks.Count; i++) { // For each LCD...  
  270.                 IMyTextPanel LCD = LcdBlocks[i] as IMyTextPanel;
  271.                 LCD.WritePublicText(text, false);
  272.                 LCD.SetValue("FontSize", 0.9f);
  273.                 LCD.ShowPublicTextOnScreen();
  274.             }
  275.         }
  276.     }
  277.     void ControlTimer(IMyTimerBlock thistimer) {
  278.         thistimer.ApplyAction("TriggerNow");  
  279.     }
  280.      
  281.     void TriggerRotor(IMyMotorStator rotor, bool state, bool reverse, ref bool containsFalse) {  
  282.         if (!state) {  
  283.             rotor.ApplyAction("OnOff_Off"); // Stop rotor  
  284.         }   else {  
  285.             rotor.ApplyAction("OnOff_On"); // Start rotor  
  286.             containsFalse = true;
  287.             if (reverse) { rotor.ApplyAction("Reverse"); }  
  288.         }  
  289.     }  
  290.      
  291.     void GetPower(IMySolarPanel solar, ref float pwr) {  
  292.         pwr = solar.MaxOutput * 1000;
  293.         float test = pwr / HighPwrValue * 100f;
  294.         decimal test2 = Math.Round((decimal)test);
  295.         textToLCD += pwr.ToString() + " kWh (" + test2.ToString() + " %)\n";
  296.         Echo(pwr.ToString() + " kWh");  
  297.     }  
  298.  
  299.     void GetOxygen(IMyOxygenFarm solar, ref float pwr) {  
  300.         pwr = solar.GetOutput()* 1.8f;
  301.         Echo(pwr.ToString() + " L/min");
  302.     }  
  303.      
  304.     float RotorPosition(IMyMotorStator Rotor) {  
  305.         if (Rotor == null) {  
  306.             Echo( "Rotor not found. Returning 0");  
  307.             return 0;  
  308.         }  
  309.         return (float)Math.Round(Rotor.Angle * (180.0 / Math.PI), 0);
  310.     }
  311.      
  312.     void RotorDuplicate(string SourceRotorName, string RotorName, bool Inverse) {  
  313.         GridTerminalSystem.SearchBlocksOfName(SourceRotorName, SourceRotors); // Search for Solar Source Blocks  
  314.         IMyMotorStator SourceRotor = SourceRotors[0] as IMyMotorStator; // I am a Rotor  
  315.         float SetPosition = RotorPosition(SourceRotor);  
  316.         GridTerminalSystem.SearchBlocksOfName(RotorName, Rotors); // Search for Solar Blocks  
  317.         if (Rotors.Count == 0) {  
  318.             Echo("Cannot find any duplicate destination rotors.");  
  319.             return;  
  320.         }  
  321.         if (Inverse) {  
  322.             SetPosition = -SetPosition;  
  323.         }  
  324.         for(int i = 0; i < Rotors.Count; i++) { // For each rotor...  
  325.             IMyMotorStator Rotor = Rotors[i] as IMyMotorStator; // I am a Rotor  
  326.             float DestPosition = RotorPosition(Rotor);   
  327.             if (ForceAutoTorque) {  
  328.                 Rotor.BrakingTorque = float.MaxValue;    
  329.                 Rotor.Torque = 10000000f;  
  330.             }  
  331.             Rotor.SetValueFloat("LowerLimit",SetPosition);  
  332.             Rotor.SetValueFloat("UpperLimit",SetPosition);
  333.             textToLCD += "Duplication #" + i + ": ";
  334.             if (SetPosition == DestPosition) {  
  335.                 Rotor.TargetVelocityRPM = 0f;  
  336.                 Rotor.ApplyAction("OnOff_Off"); // Stop rotor
  337.                 textToLCD += "Locked\n";
  338.             } else if (SetPosition < DestPosition)  {  
  339.                 Rotor.ApplyAction("OnOff_On"); // Start rotor  
  340.                 Rotor.TargetVelocityRPM = -rotorspeed;
  341.                 textToLCD += "Running\n";
  342.             } else if (SetPosition > DestPosition)  {  
  343.                 Rotor.ApplyAction("OnOff_On"); // Start rotor  
  344.                 Rotor.TargetVelocityRPM = rotorspeed;
  345.                 textToLCD += "Running\n";
  346.             }  
  347.         }  
  348.     }  
  349.        
  350.     void SetRotorSpeed(IMyMotorStator rotor, bool fast, bool FineTune) {  
  351.         float SetTo = 0f;  
  352.         bool VelocityPositive = (rotor.TargetVelocityRPM > 0f) ? true : false; // True if positive velocity  
  353.         if (fast) { // Under half of required power from solar panel. Will increase speed  
  354.             SetTo = (VelocityPositive) ? rotorspeed : -rotorspeed;  
  355.         } else if (FineTune) { // Fine tune speed  
  356.                 SetTo = (VelocityPositive) ? rotorspeed/3.7f : -rotorspeed/3.7f;  
  357.         } else { // Not far from required power. Lower speed for increased accuracy  
  358.             SetTo = (VelocityPositive) ? rotorspeed/1.7f : -rotorspeed/1.7f;  
  359.         }  
  360.         rotor.TargetVelocityRPM = SetTo;  
  361.     }  
  362.        
  363.     float GetAndSetLastPwr(IMySolarPanel solar, float CurrentPower) {  
  364.         float OldPwr = 0f;  
  365.         string[] words = solar.CustomName.Split(':'); // Colon split words  
  366.         if (words.Length > 1) { // If there is data after colon  
  367.             if (!float.TryParse(words[1], out OldPwr)) { OldPwr = 0f;} // Try to get data into float variable  
  368.         }  
  369.         solar.CustomName = (words[0] + ":" + CurrentPower); // Set current power in solar panel name  
  370.         return OldPwr;  
  371.     }  
  372.     float GetAndSetLastOxygen(IMyOxygenFarm solar, float CurrentPower) {  
  373.         float OldPwr = 0f;  
  374.         string[] words = solar.CustomName.Split(':'); // Colon split words  
  375.         if (words.Length > 1) { // If there is data after colon  
  376.             if (!float.TryParse(words[1], out OldPwr)) { OldPwr = 0f;} // Try to get data into float variable  
  377.         }  
  378.         solar.CustomName = (words[0] + ":" + CurrentPower); // Set current power in solar panel name  
  379.         return OldPwr;  
  380.     }  
  381.      
  382.     bool CheckAndUpdateRotorName(IMyMotorStator rotor) {  
  383.         int OldCount = 0;  
  384.         string[] words = rotor.CustomName.Split(':'); // Colon split words  
  385.          if (words.Length > 1) {    // If there is data after colon  
  386.             if (!int.TryParse(words[1], out OldCount)) { OldCount = 0;} // Try to get data into int variable  
  387.         }  
  388.         int NewCount = OldCount + 1;  
  389.         if (OldCount > 6) {  
  390.             rotor.CustomName = (words[0] + ":0");  
  391.             return true;  
  392.             }  
  393.         else if (OldCount >= 3) {  
  394.             rotor.CustomName = (words[0] + ":" + NewCount); // Set current count in rotor name  
  395.             return true;  
  396.         } else {  
  397.             rotor.CustomName = (words[0] + ":" + NewCount); // Set current count in rotor name  
  398.             return false;  
  399.         }      
  400.     }  
  401.     #endregion
Add Comment
Please, Sign In to add comment