Advertisement
Armitige

reactorControl

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