Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Nuclear Reactor Control - by meigrafd @ 16.08.2015
- This Script is used to automatically control a Nuclear-Reactor with a Robot.
- The Robot checks the Reactor-Inventory, push Coolant Cells into and replaces depleted Uran.
- It also monitores Reactor heat and drops Uran if it still heats up after shutdown to prevent explosion.
- Requires:
- OpenComputers >=1.5
- Setup Reactor like:
- https://app.box.com/s/fu5sqhgd19cf3vt6qu3j15r9lx7efjty
- Robot must be placed so the Reactor is in front of it!
- Bundled Cable ends to Robot.
- First Thermal Sensor turns Reactor off. Set this to max 1500.
- Second Thermal Sensor tells Robot to drop Uran Cells to prevent explosion. Set this to max 2500.
- (when Reactor was on it will still heat up after shutdown)
- For a little bit better Cooling and Blastprotection you also should add Water above the complete Reactor.
- As Robot you should use a Creative one because it doesnt use Power and you have enough space for Addons.
- Craft the Robot minimum with:
- - Inventory Controller Upgrade
- - Inventory Upgrade
- - Chunkloader Upgrade
- - Geolyzer Block
- - Screen (tier 1)
- - Keyboard
- - Disk Drive
- - Wireless Network Card (you should add this later and add instead an 'Card Container'-Upgrade (tier3))
- - Redstone Card (tier 2)
- - Internet Card (otherwise pastebin cmd doesnt work)
- - APU (Creative)
- - EEPROM (lua)
- - Hard Disk Drive
- - RAM (tier 2)
- NOTE: You must craft each Wireless Card yourself so it have an unique Modem-Address!
- Setup Reactor Inventory as (you only need to place all the Reactor Heat Vent. Robot does the rest):
- http://s2.postimage.org/5r41iiq15/Reactor_Setup.jpg
- (biggest Setup with 1120 EU/t)
- Install the Scripts as 'autorun.lua'
- Scroll down to: CONFIG - START
- --]]
- --[[ Internal values - DONT change! ]]
- local color = require("colors") -- http://ocdoc.cil.li/api:colors .. only works for bundled cables
- local component = require("component") -- http://ocdoc.cil.li/api:component
- local event = require("event") -- http://ocdoc.cil.li/api:event
- local robot = require("robot") -- http://ocdoc.cil.li/api:robot
- local side = require("sides") -- http://ocdoc.cil.li/api:sides
- local serial = require("serialization")
- local term = require("term") -- http://ocdoc.cil.li/api:term
- local ic = component.inventory_controller -- http://ocdoc.cil.li/component:inventory_controller
- local geo = component.geolyzer -- http://ocdoc.cil.li/component:geolyzer
- local gpu = component.gpu -- http://ocdoc.cil.li/component:gpu
- local rs = component.redstone
- local wlan = component.modem
- local wlanPort = 7331
- local version = 0.2
- reactorState = 'off'
- uranDropped = false
- thermalTriggered = false
- commandsexecdCount=1
- w,h = gpu.getResolution()
- serverAddress = nil
- wlan.open(wlanPort)
- ---[[ CONFIG - START ]]
- -- Chest Inventory Sides for which Items. Only valid sides: left, right, back, up, down
- -- NOTE: Only use one Chest for one Type of Item!
- -- Fastest for Coolant will be "up" or "down"
- -- Put a Chest below the Robot as Trash, where it drops all it takes out of Reactor.
- chestCoolant = "up"
- chestUran = "left"
- chestTrash = "down"
- chestReactor = "front"
- -- Wire Colors. Available Colors with Bundled Cable: http://computercraft.info/wiki/Colors_(API)#Colors
- wireReactor = color.green -- To turn Reactor on/off
- wireThermal1 = color.blue -- If Reactor Temperature gets >1500
- wireThermal2 = color.red -- If Reactor Temperature gets >2500
- -- Bundled Cable Side. Only valid sides: back, left, right
- wireSide = side.back
- local CheckEvery = 0.5 -- sec. Dont set too high! (but also not lower 0.5)
- local UseReactorSetup = 1
- --[[ Set to 1 or 2.
- 1 = Biggest with five Quad-Fuel-Rods in a row, twice = 1120EU/t. NOTE: heats much faster up!
- 2 = three Quad-Fuel-Rods in a row, twice = 640EU/t.
- --]]
- ---[[ CONFIG - END ]]
- --[[
- Required Reactor Inventory setup Table.
- first row from left to right, then the second row from left to right, etc.
- one row = 9 columns.
- NOTE: Not the exact Item-Name is used, just a match of e.g. *Coolant* so 10k or 60k Coolant Cells can be used,
- but better use 60k Coolant Cells instead of 10k.
- --]]
- if UseReactorSetup == 1 then
- -- 5 Quad-Fuel-Rods in a row, twice.
- RequiredReactorInventory = {
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Uran",
- "Uran",
- "Uran",
- "Uran",
- "Uran",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Uran",
- "Uran",
- "Uran",
- "Uran",
- "Uran",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent"
- }
- else
- -- only 3 Quad-Fuel-Rods in a row, twice
- RequiredReactorInventory = {
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Uran",
- "Uran",
- "Uran",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Uran",
- "Uran",
- "Uran",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Coolant Cell",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent",
- "Reactor Heat Vent"
- }
- end
- ---[[ functions ]]
- -- display text on terminal screen
- function draw_text_term(x, y, text)
- term.setCursor(x, y)
- term.write(text)
- end
- -- This function can be useful for sending/receiving messages via network.
- function encode(data)
- return serial.serialize(data)
- end
- function decode(data)
- status, result = pcall(serial.unserialize, data)
- return status, result
- end
- -- http://stackoverflow.com/questions/1426954/split-string-in-lua
- function split(pString, pPattern)
- local Table = {} -- NOTE: use {n = 0} in Lua-5.0
- local fpat = "(.-)" .. pPattern
- local last_end = 1
- local s, e, cap = pString:find(fpat, 1)
- while s do
- if s ~= 1 or cap ~= "" then
- table.insert(Table, cap)
- end
- last_end = e+1
- s, e, cap = pString:find(fpat, last_end)
- end
- if last_end <= #pString then
- cap = pString:sub(last_end)
- table.insert(Table, cap)
- end
- return Table
- end
- function stringMatch(text, find)
- if string.find(string.lower(text), string.lower(find)) then
- return true
- else
- return false
- end
- end
- function turn(side)
- if side == "left" then
- robot.turnLeft()
- elseif side == "right" then
- robot.turnRight()
- elseif side == "front" then
- robot.turnRight()
- robot.turnRight()
- elseif side == "back" then
- robot.turnLeft()
- robot.turnLeft()
- end
- end
- -- drop item in current robots slot to Trash
- function drop()
- if chestTrash == "down" then
- success = robot.dropDown()
- elseif chestTrash == "up" then
- success = robot.dropUp()
- elseif chestTrash == "left" then
- turn('left')
- success = robot.drop()
- turn('right')
- elseif chestTrash == "right" then
- turn('right')
- success = robot.drop()
- turn('left')
- end
- end
- function suck(side)
- local success = true
- if side == "up" then
- if not robot.suckUp(1) then
- success = false
- end
- elseif side == "down" then
- if not robot.suckDown(1) then
- success = false
- end
- elseif side == "left" then
- turn('left')
- if not robot.suck(1) then
- success = false
- end
- turn('right')
- elseif side == "right" then
- turn('right')
- if not robot.suck(1) then
- success = false
- end
- turn('left')
- end
- return success
- end
- -- verify reactor in front
- function verifyReactor()
- local data = geo.analyze(side.front)
- if stringMatch(data.name, "ReactorChamber") then
- return true
- else
- return false
- end
- end
- -- get coolant from chest and put into reactors toSlot
- function Coolant(toSlot)
- while (robot.count() > 0) do
- drop()
- end
- -- get coolant from chest
- local success = suck(chestCoolant)
- if success == false then
- print("WARNING: can't pick up Coolant!")
- changeReactorState('OFF', 'Coolant')
- if serverAddress ~= nil then
- wlan.send(serverAddress, wlanPort, 'MISSING:Coolant')
- end
- else
- -- verify reactor in front
- while verifyReactor() == false do
- turn('left')
- end
- -- put coolant into reactors toSlot
- success, reason = ic.dropIntoSlot(side.front, toSlot)
- commandsexecdCount = commandsexecdCount + 1
- end
- end
- -- get uran from chest and put into reactors toSlot
- function Uran(toSlot)
- while (robot.count() > 0) do
- drop()
- end
- -- get uran from chest
- local success = suck(chestUran)
- if success == false then
- print("WARNING: can't pick up Uran!")
- changeReactorState('OFF', 'Uran')
- if serverAddress ~= nil then
- wlan.send(serverAddress, wlanPort, 'MISSING:Uran')
- end
- else
- -- verify reactor in front
- while verifyReactor() == false do
- turn('left')
- end
- -- put uran into reactors toSlot
- success, reason = ic.dropIntoSlot(side.front, toSlot)
- commandsexecdCount = commandsexecdCount + 1
- end
- end
- function Depleted_Uran(fromSlot, replace)
- success = ic.suckFromSlot(side.front, fromSlot)
- while (robot.count() > 0) do
- drop()
- end
- -- only drop Uran from Reactor to Trash or replace it too?
- if replace == true then
- Uran(fromSlot)
- end
- commandsexecdCount = commandsexecdCount + 1
- end
- function checkInventory()
- draw_text_term(1, 1, "Checking Reactor Inventory..")
- local linecount = 1
- local allFine = true
- for Slot=1, #RequiredReactorInventory do
- local Item = RequiredReactorInventory[Slot]
- local found = false
- local depleted_uran = false
- local slotDetails = ic.getStackInSlot(side.front, Slot)
- if slotDetails ~= nil then
- if (stringMatch(slotDetails.label, Item) == true) then
- --draw_text_term(1, linecount, 'Slot#'..Slot..': '..Item)
- if (stringMatch(slotDetails.label, "depleted") == true) then
- depleted_uran = true
- else
- found = true
- end
- end
- end
- if depleted_uran == true then
- allFine = false
- linecount = linecount + 1
- -- does not meet the requirements. replace it!
- draw_text_term(1, linecount, 'Slot#'..Slot..': "Depleted Uran". Replacing it!')
- -- Replace Depleted Uran.
- Depleted_Uran(Slot, true)
- elseif found == false then
- allFine = false
- linecount = linecount + 1
- -- does not meet the requirements. replace it!
- draw_text_term(1, linecount, 'Slot#'..Slot..': "'..Item..'" not found!')
- -- Replace Item.
- if (stringMatch(Item, "Coolant") == true) then
- Coolant(Slot)
- elseif (stringMatch(Item, "Uran") == true) then
- Uran(Slot)
- end
- end
- end
- if allFine == true then
- draw_text_term(1, 2, "Nothing to do.")
- end
- end
- -- http://ocdoc.cil.li/component:redstone
- function changeReactorState(state, reason)
- reason = reason or ''
- if reason ~= '' then
- msg = "Changing Reactor State to: "..state.." coz: "..reason
- else
- msg = "Changing Reactor State to: "..state
- end
- draw_text_term(1, h-1, msg)
- if state == "ON" then
- if uranDropped == true then
- uranDropped = false
- end
- rs.setBundledOutput(wireSide, wireReactor, 255)
- else
- rs.setBundledOutput(wireSide, wireReactor, 0)
- end
- reactorState = state
- if (serverAddress ~= nil) then
- wlan.send(serverAddress, wlanPort, 'POWER:'..state)
- end
- end
- --[[ End functions ]]
- --[[ Main Script ]]
- term.clear()
- local linecount = 3
- draw_text_term(1, linecount, "Checking peripherals...")
- os.sleep(0.2)
- -- detect Robot
- local linecount = linecount + 2
- draw_text_term(2, linecount, "Checking Robot...")
- os.sleep(0.2)
- if not component.isAvailable("robot") then
- draw_text_term(2, (linecount + 1), "Error:", rgb.red, rgb.black)
- draw_text_term(2, (linecount + 2), "Can only run on robots")
- return
- else
- draw_text_term(40, linecount, "success")
- os.sleep(0.2)
- end
- -- detect Inventory Controller
- local linecount = linecount + 1
- draw_text_term(2, linecount, "Checking Inventory Controller...")
- os.sleep(0.2)
- if not component.isAvailable("inventory_controller") then
- draw_text_term(2, (linecount + 1), "Error:")
- draw_text_term(2, (linecount + 2), "Could find Inventory Controller")
- return
- else
- draw_text_term(40, linecount, "success")
- os.sleep(0.2)
- end
- --local dbAddress = false
- --for k,_ in component.list("database") do dbAddress = k break end
- draw_text_term(1, (linecount + 2), "Setup Complete!")
- os.sleep(1)
- draw_text_term(1, (linecount + 3), "Starting")
- robot.select(1)
- function messageReceived(event, localAddress, remoteAddress, port, senderDistance, message)
- -- Determine if message contains ':'
- if string.find(message, ":") then
- -- split message into a table
- msgTable = split(message, ":")
- if msgTable[1] == "POWER" then
- changeReactorState(msgTable[2], 'Server told')
- elseif (msgTable[1] == "PONG") and (msgTable[2] == "OK") then
- -- PING/PONG verificated
- serverAddress = remoteAddress
- wlan.send(serverAddress, wlanPort, 'OK')
- end
- -- message doesnt contain ':'
- else
- if (message == "PING") and (serverAddress == nil) then
- if UseReactorSetup == 1 then
- reactorPower = 1120
- else
- reactorPower = 640
- end
- wlan.send(serverAddress, wlanPort, 'PONG:'..reactorPower)
- end
- end
- end
- -- http://ocdoc.cil.li/component:signals
- event.listen("modem_message", messageReceived)
- -- all seems fine, start main loop
- while true do
- term.clear()
- -- check State of Thermal1
- if (rs.getBundledInput(wireSide, wireThermal1) > 0) then
- -- turn Reactor off
- changeReactorState('OFF', 'Thermal 1 triggered')
- thermalTriggered = true
- if serverAddress ~= nil then
- wlan.send(serverAddress, wlanPort, 'OVERHEAT:Thermal 1 triggered')
- end
- end
- -- check State of Thermal2
- if (rs.getBundledInput(wireSide, wireThermal2) > 0) then
- -- turn Reactor off
- changeReactorState('OFF', 'Thermal 2 triggered')
- thermalTriggered = true
- if serverAddress ~= nil then
- wlan.send(serverAddress, wlanPort, 'OVERHEAT:Thermal 2 triggered')
- end
- -- tell Robot to drop all Uran Cells to prevent explosion
- if uranDropped == false then
- draw_text_term(1, linecount+1, 'Dropping all Uran Cells to prevent explosion..')
- for i=1, #RequiredReactorInventory do
- if stringMatch(RequiredReactorInventory[i], "Uran") == true then
- Depleted_Uran(i, false)
- end
- end
- -- after drop cmd was exec make sure to not exec it again
- uranDropped = true
- end
- end
- if (thermalTriggered == true
- and rs.getBundledInput(wireSide, wireThermal1) == 0
- and rs.getBundledInput(wireSide, wireThermal2) == 0) then
- thermalTriggered = false
- changeReactorState('ON')
- end
- -- only check inventory when we didnt told robot to remove uran to prevent explosion..
- if (uranDropped == false) and (serverAddress ~= nil) then
- checkInventory()
- end
- os.sleep(CheckEvery)
- end
- --
- -- EOF
- --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement