ardittristan

another big reactor

May 4th, 2015
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.75 KB | None | 0 0
  1. --[[
  2. Big Reactors controller script
  3. Uses wired modems to connect to computer control port on reactor
  4. Prefers monitor connection (also via wired modem) for local display and potentially control
  5. Uses wireless modem channel to send status and accept control commands from central system
  6. If present, wireless modem must be on top of the computer
  7. Note:  Do not connect more than one reactor to the same controlling computer
  8. ]]--
  9.  
  10. -- Global settings
  11. -- This reactor ID
  12. reactorID = 2
  13.  
  14. -- Wireless channels
  15. wcStatus = 100
  16. wcCtl = 110
  17.  
  18. -- Minimum control rod setting - This is to prevent longer 'hunt' times to optimize temperature
  19. -- Note:  This setting will be adjusted automatically as the reactor runs, but is not saved through restarts
  20. crmin = 0
  21.  
  22. -- Start pushing in control rods when temperature climbs above this temp
  23. tempmax = 995
  24. tempmin = 940
  25.  
  26. -- Start pushing in control rods when stored energy climbs above this percent
  27. --  Control rods will scale from crmin to 100%, starting from this %
  28. storpct = 30
  29.  
  30. -- There should be no need to edit code below this line
  31.  
  32.  
  33.  
  34. -- Utility function - return a wrapped variable for a specific peripheral
  35. function wrapThis(thing)
  36.   local wrapped, i = nil, 0
  37.   while wrapped == nil and i <= 100 do
  38.     wrapped = peripheral.wrap(thing.."_"..i)
  39.       i = i + 1
  40.     end
  41.  
  42.     if wrapped == nil then
  43.       return nil
  44.     else
  45.       return wrapped
  46.     end
  47. end
  48.  
  49. -- Collect statistics for Local display and remote send
  50. function getStats()
  51.   local curTemp = r.getFuelTemperature()
  52.   local curFuel = r.getFuelAmount()
  53.   local maxFuel = r.getFuelAmountMax()
  54.   local curRF   = r.getEnergyStored()
  55.   local ctlRod  = r.getControlRodLevel(0)
  56.   local curFuelPct = curFuel/maxFuel*100
  57.   local curRFPct = curRF/100000
  58.   local curRFGen = r.getEnergyProducedLastTick()
  59.     local active = r.getActive()
  60.  
  61.   -- Round values
  62.   curRFPct = math.floor((curRFPct*10))/10
  63.   curFuelPct = math.floor((curFuelPct*10))/10
  64.   curRFGen = math.floor(curRFGen)
  65.  
  66.   return curTemp, curFuelPct, curRFPct, curRFGen, ctlRod, active
  67. end
  68.  
  69. -- Local status display
  70. function displayStatus()
  71.   if mon == nil then
  72.     return
  73.   end
  74.   local curTemp, curFuelPct, curRFPct, curRFGen, ctlRod, active = getStats()
  75.   mon.clear()
  76.   mon.setCursorPos(1,1)
  77.   mon.write("Temp: "..curTemp)
  78.   mon.setCursorPos(1,2)
  79.   mon.write("Fuel: "..curFuelPct.."%")
  80.   mon.setCursorPos(1,3)
  81.   mon.write("Energy: "..curRFPct.."%")
  82.   mon.setCursorPos(1,4)
  83.   mon.write("RF Gen: "..curRFGen)
  84.   mon.setCursorPos(1,5)
  85.   mon.write("Control Rod: "..ctlRod.."%")
  86.   mon.setCursorPos(1,6)
  87.   mon.write("Min Control Rod: "..crmin.."%")
  88.   mon.setCursorPos(1,7)
  89.   if active then
  90.     mon.write("Active")
  91.   else
  92.     mon.write("Shutdown")
  93.   end
  94. end
  95.  
  96. -- Transmit current system stats on wireless channel
  97. function txStatus()
  98.   if modem == nil then
  99.     return
  100.   end
  101.   local curTemp, curFuelPct, curRFPct, curRFGen, ctlRod, active = getStats()
  102.   local updateStr = "R:"..reactorID.." T:"..curTemp.." F:"..curFuelPct.." E:"..curRFPct.." G:"..curRFGen.." C:"..ctlRod.." S:"..crmin
  103.   if active then
  104.     updateStr = updateStr.." A:true"
  105.   else
  106.     updateStr = updateStr.." A:false"
  107.   end
  108.   modem.transmit(wcStatus, wcCtl, updateStr)
  109. end
  110.  
  111.  
  112. function main()
  113.   if tonumber(args[1]) ~= nil then
  114.     reactorID = tonumber(args[1])
  115.   end
  116.   print("Initializing reactor "..reactorID.." control...")
  117.   print("Max Temp: "..tempmax)
  118.   print("Control rod minimum: "..crmin.."%")
  119.   print("Target Energy level: "..storpct.."%")
  120.  
  121.   -- Initialize connections to peripherals
  122.   if initConnections() == false then
  123.     return false
  124.   end
  125.  
  126.   -- Start the reactor
  127.   startup()
  128.  
  129.   -- Start our monitoring and control loop
  130.   running = true
  131.   local loopCount = 1
  132.   os.startTimer(1)
  133.   while running do
  134.     local e, p1, p2, p3, p4, p5 = os.pullEvent()
  135.  
  136.     if e == "key" then
  137.       if p1 == 16 then -- 'q' key
  138.         running = false
  139.       elseif p1 == 13 then -- '=/+' key
  140.         crmin = crmin + 10
  141.       elseif p1 == 12 then -- '-' key
  142.         crmin = crmin - 10
  143.       elseif p1 == 18 then -- 'e'
  144.         r.setActive(false)
  145.       elseif p1 == 19 then -- 'r'
  146.         r.setActive(true)
  147.       end
  148.     elseif e == "modem_message" and p2 == wcCtl then
  149.       local rid, cmd = string.gmatch(p4, "%S+")
  150.       if rid == reactorID then
  151.         if cmd == 'stop' then
  152.           r.setActive(false)
  153.         elseif cmd == 'start' then
  154.           r.setActive(true)
  155.         elseif cmd == 'crminup' then
  156.           crmin = crmin + 10
  157.         elseif cmd == 'crmindown' then
  158.           crmin = crmin - 10
  159.         end
  160.       end
  161.     elseif e == "timer" then
  162.       os.startTimer(1)
  163.     end
  164.  
  165.     -- Constrain the control rod settings
  166.     if crmin < 0 then
  167.       crmin = 0
  168.     elseif crmin > 100 then
  169.       crmin = 100
  170.     end
  171.  
  172.     -- Run reactor controls every 10 cycles - this allows for some time for things to stabilize after each adjustment
  173.     if loopCount > 10 then
  174.       manageReactor()
  175.       loopCount = 1
  176.     end
  177.  
  178.     -- Update the displays after every loop
  179.     displayStatus()
  180.     txStatus()
  181.     loopCount = loopCount + 1
  182.   end
  183.   cleanup()
  184.   return true
  185. end
  186.  
  187. -- Initialize connections to peripherals.   Only return false if we can't talk to the reactor
  188. function initConnections()
  189.   -- Connect to reactor
  190.   r = wrapThis("BigReactors-Reactor")
  191.   if r == nil then
  192.     print("No reactor found")
  193.     return false
  194.   end
  195.  
  196.   -- Check to see if we have a valid reactor
  197.   if r.getConnected() == false then
  198.     print("Reactor not connected")
  199.     return false
  200.   end
  201.  
  202.   -- Connect monitor
  203.   mon = wrapThis("monitor")
  204.   if mon == nil then
  205.     print("No monitor found, full status display disabled")
  206.   else
  207.     -- Start things off with current status
  208.     displayStatus()
  209.   end
  210.  
  211.   -- Connect wireless network - wireless modem needs to be on top
  212.   modem = peripheral.wrap("top")
  213.   if modem == nil then
  214.     print("No wireless modem found.  No remote status/control enabled")
  215.   else
  216.     txStatus()
  217.     -- Open control channel
  218.     modem.open(wcCtl)
  219.   end
  220.   return true
  221. end
  222.  
  223. -- Configure initial control rod settings and activate reactor
  224. function startup()
  225.   -- Verify initial control rod state and activate reactor (if needed)
  226.   local curTemp, curFuelPct, curRFPct, curRFGen, ctlRod, active = getStats()
  227.   if ctlRod < crmin then
  228.     r.setAllControlRodLevels(crmin)
  229.   end
  230.   if active == false then
  231.     r.setActive(true)
  232.   end
  233. end
  234.  
  235. -- Cleanup reactor before exiting
  236. --   Note:  This will shutdown the reactor to avoid having the reactor run without supervision
  237. function cleanup()
  238.   r.setActive(false)
  239. end
  240.  
  241. -- Adjust reactor status based on temperature, energy level and control rod settings
  242. function manageReactor()
  243.  
  244.   local cRT  = r.getControlRodLevel(0)
  245.  
  246.   -- First, if the control rods are lower than our minimum setting, just bump it up
  247.   if cRT < crmin then
  248.     r.setAllControlRodLevels(crmin)
  249.   end
  250.  
  251.  
  252.   local curTemp, curFuelPct, curRFPct, curRFGen, ctlRod, active = getStats()
  253.   ctlSet = ctlRod
  254.   ctTargR = 0
  255.  
  256.   -- If the reactor stored energy is above the target, start pushing the control rods in - scale from crmin to 100
  257.   --   Better to run the reactor at 50% stable than turn it full on/off to maintain energy reserve?
  258.   --   Scale insertion speed based on how far above the target we are? - similar to temp adjustments
  259.   --   Figure out the target control rod setting based on energy storage
  260.   if curRFPct > storpct then
  261.     ctScale = 100 - crmin
  262.     esScale = 100 - storpct
  263.     esLvl = curRFPct - storpct
  264.     esMult = esLvl / esScale
  265.     ctTargR = ctScale * esMult + crmin
  266.     ctTargR = math.floor(ctTargR)
  267.   end
  268.  
  269.   -- Look for control rod insertion, adjust and return if matched
  270.  
  271.   -- If the reactor temp is too high, start pushing the control rods in - continue if matched
  272.   if curTemp > tempmax then
  273.     local dT = curTemp - tempmax
  274.     if dT > 100 then
  275.       dR = 15
  276.     elseif dT > 30 then
  277.       dR = 10
  278.     elseif dT > 20 then
  279.       dR = 5
  280.     elseif dT > 10 then
  281.       dR = 2
  282.     elseif dT > 5 then
  283.       dR = 1
  284.     end
  285.     ctlSet = ctlRod + dR
  286.   end
  287.  
  288.   -- Apply energy load adjustment
  289.   if ctTargR > ctlSet then
  290.     ctlSet = ctTargR
  291.   end
  292.  
  293.   -- If we are pushing the control rods in, then we need to do that here and then return - Note - a hot and charged reactor will scale control rods very quickly
  294.   if ctlSet > 100 then
  295.     ctlSet = 100
  296.   end
  297.   if ctlSet > ctlRod then
  298.     r.setAllControlRodLevels(ctlSet)
  299.     return
  300.   end
  301.  
  302.   -- If the reactor temp is too low, retract control rods
  303.   if curTemp < tempmin then
  304.     local dT = tempmin - curTemp
  305.     if dT > 100 then
  306.       dR = 15
  307.     elseif dT > 70 then
  308.       dR = 10
  309.     elseif dT > 40 then
  310.       dR = 5
  311.     elseif dT > 20 then
  312.       dR = 2
  313.     elseif dT > 10 then
  314.       dR = 1
  315.     end
  316.     ctlSet = ctlSet - dR
  317.   end
  318.  
  319.   -- Apply energy load adjustment
  320.   if ctTargR > ctlSet then
  321.     ctlSet = ctTargR
  322.   end
  323.  
  324.   -- Retract control rods
  325.   if ctlSet < crmin then
  326.     ctlSet = crmin
  327.   end
  328.   if ctlSet <= ctlRod then
  329.     r.setAllControlRodLevels(ctlSet)
  330.   end
  331. end
  332.  
  333. args = {...}
  334. main()
Advertisement
Add Comment
Please, Sign In to add comment