Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local component = require("component")
- local event = require("event")
- local term = require("term")
- local gpu = component.gpu
- local unicode= require("unicode")
- chaosMode = 0
- Mode = 2
- -- Inflow PID
- local proportional_field_error = 0
- local inflow_I_sum = 0
- local integral_field_error = 0
- local derivative_field_error = 0
- local inflow_D_last = 0
- local inflow_correction = 0
- -- Outflow PID
- local proportional_temp_error = 0
- local outflow_I_sum = 0
- local integral_temp_error = 0
- local derivative_temp_error = 0
- local outflow_D_last = 0
- local outflow_correction = 0
- -- Safety Checks
- if not component.isAvailable("draconic_reactor") then
- print("Reactor not connected. Please connect computer to reactor with an Adapter block.")
- os.exit()
- end
- reactor = component.draconic_reactor
- local fluxGates = {}
- for x,y in pairs(component.list("flux_gate")) do
- fluxGates[#fluxGates+1] = x
- end
- if #fluxGates < 2 then
- print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
- os.exit()
- end
- input_flux = component.proxy(fluxGates[1])
- output_flux = component.proxy(fluxGates[2])
- if not input_flux or not output_flux then
- print("Not enough flux gates connected; please connect inflow and outflow flux gates with Adapter blocks.")
- os.exit()
- end
- local info = reactor.getReactorInfo()
- -- AutoSet Gates
- reactor.chargeReactor()
- satOne = info.energySaturation
- fieldOne = info.fieldStrength
- input_flux.setFlowOverride(1.0)
- os.sleep(0.5)
- satTwo = info.energySaturation
- fieldTwo = info.fieldStrength
- input_flux.setFlowOverride(0.0)
- reactor.stopReactor()
- if satTwo == satOne or fieldTwo == fieldOne then
- local oldAddr = input_flux.address
- input_flux = component.proxy(output_flux.address)
- output_flux = component.proxy(oldAddr)
- end
- -- Functions
- function exit_msg(msg)
- term.clear()
- print(msg)
- os.exit()
- end
- function modify_temp(offset)
- local new_temp = idealTemp + offset
- if new_temp > 10000 then
- new_temp = 10000
- elseif new_temp < 2000 then
- new_temp = 2000
- end
- idealTemp = new_temp
- end
- function modify_field(offset)
- local new_strength = idealField + offset
- if new_strength > 100 then
- new_strength = 100
- elseif new_strength < 1 then
- new_strength = 1
- end
- idealField = new_strength
- end
- -- Buttons
- local adj_button_width = 19
- local temp_adjust_x_offset = 62
- local temp_adjust_y_offset = 2
- local field_adjust_x_offset = temp_adjust_x_offset + adj_button_width + 2
- local field_adjust_y_offset = 2
- local buttons = {
- start={
- x=2,
- y=20,
- width=18,
- height=1,
- text="Start",
- action=function()
- if safe then
- state = "Charging"
- reactor.chargeReactor()
- elseif shutting_down then
- state = "Active"
- reactor.activateReactor()
- end
- end,
- condition=function() return safe or shutting_down end
- },
- shutdown={
- x=2,
- y=20,
- width=18,
- height=1,
- text="Shutdown",
- action=function()
- cutoff_temp = 10001
- state = "Manual Shutdown"
- reactor.stopReactor()
- end,
- condition=function() return running end
- },
- chaosmode={
- x=2,
- y=22,
- width=18,
- height=1,
- text=" Chaos Mode",
- action=function()
- if chaosMode == 0 then
- chaosMode = 1
- cutoff_temp = 19750
- idealField = 100
- idealTemp = 40000
- elseif chaosMode == 1 then
- chaosMode = 0
- idealField = 25
- idealTemp = 8000
- end
- end,
- condition=function() return running end
- },
- Update={
- x=22,
- y=22,
- width=18,
- height=1,
- text="Update",
- action=function()
- reactor.stopReactor()
- os.execute("cd /home; pastebin get -f KiSBN88r dc14; cls; dc14")
- end,
- condition=function() return info.status ~= "running" and info.status ~= "warming_up" end
- },
- switch_gates={
- x=2,
- y=22,
- width=18,
- height=1,
- text="Swap Flux Gates",
- action=function()
- cutoff_temp = 10001
- oldAddr = input_flux.address
- input_flux = component.proxy(output_flux.address)
- output_flux = component.proxy(oldAddr)
- end,
- condition=function() return safe end
- },
- exit={
- x=158,
- y=1,
- width=3,
- height=1,
- text="X",
- action=function()
- event_loop = false
- os.execute("cls")
- end,
- },
- temp_up_max={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset,
- width=adj_button_width,
- height=1,
- text="Maximum",
- action=function() modify_temp(20000) end
- },
- temp_up_thousand={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+2,
- width=adj_button_width,
- height=1,
- text="+1000",
- action=function() modify_temp(1000) end
- },
- temp_up_hundred={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+4,
- width=adj_button_width,
- height=1,
- text="+100",
- action=function() modify_temp(100) end
- },
- temp_up_ten={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+6,
- width=adj_button_width,
- height=1,
- text="+10",
- action=function() modify_temp(10) end
- },
- temp_up_one={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+8,
- width=adj_button_width,
- height=1,
- text="+1",
- action=function() modify_temp(1) end
- },
- temp_down_thousand={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+18,
- width=adj_button_width,
- height=1,
- text="-1000",
- action=function() modify_temp(-1000) end
- },
- temp_down_max={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+20,
- width=adj_button_width,
- height=1,
- text="Minimum",
- action=function() modify_temp(-20000) end
- },
- temp_down_hundred={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+16,
- width=adj_button_width,
- height=1,
- text="-100",
- action=function() modify_temp(-100) end
- },
- temp_down_ten={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+14,
- width=adj_button_width,
- height=1,
- text="-10",
- action=function() modify_temp(-10) end
- },
- temp_down_one={
- x=temp_adjust_x_offset,
- y=temp_adjust_y_offset+12,
- width=adj_button_width,
- height=1,
- text="-1",
- action=function() modify_temp(-1) end
- },
- field_up_ten={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+3,
- width=adj_button_width,
- height=1,
- text="+10",
- action=function() modify_field(10) end
- },
- field_up_one={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+5,
- width=adj_button_width,
- height=1,
- text="+1",
- action=function() modify_field(1) end
- },
- field_up_tenth={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+7,
- width=adj_button_width,
- height=1,
- text="+0.1",
- action=function() modify_field(0.1) end
- },
- field_down_ten={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+17,
- width=adj_button_width,
- height=1,
- text="-10",
- action=function() modify_field(-10) end
- },
- field_down_one={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+15,
- width=adj_button_width,
- height=1,
- text="-1",
- action=function() modify_field(-1) end
- },
- field_down_tenth={
- x=field_adjust_x_offset,
- y=field_adjust_y_offset+13,
- width=adj_button_width,
- height=1,
- text="-0.1",
- action=function() modify_field(-0.1) end
- }
- }
- -- main code
- input_flux.setFlowOverride(0.0)
- output_flux.setFlowOverride(0.0)
- input_flux.setOverrideEnabled(true)
- output_flux.setOverrideEnabled(true)
- local condition = reactor.getReactorInfo()
- if not condition then
- print("Reactor not initialized, please ensure the stabilizers are properly laid out.")
- os.exit()
- end
- idealField = 15
- idealTemp = 8000
- cutoff_temp = 10001
- -- tweakable pid gains
- inflow_P_gain = 1
- inflow_I_gain = 0.04
- inflow_D_gain = 0.1
- outflow_P_gain = 500
- outflow_I_gain = 0.5
- outflow_II_gain = 0.0000003
- outflow_D_gain = 60000
- -- initialize main loop
- inflow_I_sum = 0
- inflow_D_last = 0
- outflow_I_sum = 0
- outflow_II_sum = 0
- outflow_D_last = 0
- state = "Standby"
- shutting_down = false
- if condition.temperature > 25 then
- state = "Cooling"
- end
- if condition.temperature > 2000 then
- state = "Active"
- end
- -- Possible states:
- --Standby
- --Charging
- --Active
- --Manual Shutdown
- --Emergency Shutdown
- --Cooling
- event_loop = true
- while event_loop do
- --gpu.setBackground(0x000000)
- --gpu.setForeground(0xFF0000)
- local info = reactor.getReactorInfo()
- if not component.isAvailable("draconic_reactor") then
- exit_msg("Reactor disconnected, exiting")
- end
- if not component.isAvailable("flux_gate") then
- exit_msg("Flux gates disconnected, exiting")
- end
- local inflow = 0.0
- local outflow = 0.0
- shutting_down = state == "Manual Shutdown" or state == "Emergency Shutdown"
- running = state == "Charging" or state == "Active"
- safe = state == "Standby" or state == "Cooling"
- if state == "Charging" then
- inflow = 200000.0
- if info.temperature > 2000 then
- reactor.activateReactor()
- state = "Active"
- end
- elseif state == "Cooling" then
- if info.temperature < 25 then
- state = "Standby"
- end
- inflow = 10.0
- outflow = 20.0
- elseif state == "Standby" then
- inflow = 10.0
- outflow = 20.0
- else
- -- adjust inflow rate based on field strength
- local field_error = (info.maxFieldStrength * (idealField / 100)) - info.fieldStrength
- local proportional_field_error = field_error * inflow_P_gain
- inflow_I_sum = inflow_I_sum + field_error
- local integral_field_error = inflow_I_sum * inflow_I_gain
- local derivative_field_error = (field_error - inflow_D_last) * inflow_D_gain
- inflow_D_last = field_error
- local inflow_correction = proportional_field_error + integral_field_error + derivative_field_error
- if inflow_correction < 0 then
- inflow_I_sum = inflow_I_sum - field_error
- end
- inflow = inflow_correction
- if not shutting_down then
- -- adjust outflow rate based on core temperature
- local temp_error = idealTemp - info.temperature
- local proportional_temp_error = temp_error * outflow_P_gain
- outflow_I_sum = outflow_I_sum + temp_error
- local integral_temp_error = outflow_I_sum * outflow_I_gain
- if math.abs(temp_error) < 100 then
- outflow_II_sum = outflow_II_sum + integral_temp_error
- else
- outflow_II_sum = 0
- end
- local second_integral_temp_error = outflow_II_sum * outflow_II_gain
- local derivative_temp_error = (temp_error - outflow_D_last) * outflow_D_gain
- outflow_D_last = temp_error
- local outflow_correction = proportional_temp_error + integral_temp_error + second_integral_temp_error + derivative_temp_error
- if outflow_correction < 0 then
- outflow_I_sum = outflow_I_sum - temp_error
- end
- outflow = outflow_correction
- if info.temperature > idealTemp then
- state = "Manual Shutdown"
- reactor.stopReactor()
- os.sleep(0.10)
- state = "Active"
- reactor.activateReactor()
- end
- -- cut off reactor in case of emergency
- if info.temperature > cutoff_temp then
- print("Reactor Too Hot, shutting down")
- outflow = 0.0
- new_strength = 50
- cutoff_temp = 10001
- state = "Emergency Shutdown"
- reactor.stopReactor()
- end
- if ((info.fieldStrength / info.maxFieldStrength) * 100) < 0.75 and chaosMode == 0 then
- print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
- outflow = 0.0
- new_strength = 50
- cutoff_temp = 10001
- state = "Emergency Shutdown"
- reactor.stopReactor()
- end
- if ((info.fieldStrength / info.maxFieldStrength) * 100) < 5 and chaosMode == 1 then
- print("Reactor Field Has Failed, Failsafe Activated, Shutting Down")
- outflow = 0.0
- new_strength = 50
- cutoff_temp = 10001
- state = "Emergency Shutdown"
- reactor.stopReactor()
- end
- if ((1 - info.fuelConversion / info.maxFuelConversion) * 100) < 12 then
- print("Reactor Fuel Low, Shutting Down")
- outflow = 0.0
- new_strength = 1
- cutoff_temp = 10001
- state = "Emergency Shutdown"
- reactor.stopReactor()
- end
- else
- if info.temperature < 2000 then
- state = "Cooling"
- end
- end
- end
- if state ~= "Active" and not shutting_down then
- inflow_I_sum = 0
- inflow_D_last = 0
- outflow_I_sum = 0
- outflow_II_sum = 0
- outflow_D_last = 0
- end
- if inflow < 0 then
- inflow = 0.0
- end
- if outflow < 0 then
- outflow = 0.0
- end
- input_flux.setFlowOverride(inflow)
- output_flux.setFlowOverride(outflow)
- -- displayVariables
- local deviation = idealField - ((info.fieldStrength / info.maxFieldStrength) * 100)
- local secondsToExpire = (info.maxFuelConversion - info.fuelConversion) / math.max(info.fuelConversionRate*0.00002, 0.00001)
- if info.fuelConversionRate > 249999 then
- fuelConversionRate = ((info.fuelConversionRate / (info.maxFuelConversion * 1000000)) * 2000)
- fuelMeasure = " %%/s"
- elseif info.fuelConversionRate > 999 then
- fuelConversionRate = (info.fuelConversionRate / 1000)
- fuelMeasure = " "..(unicode.char(956)).."b/t"
- elseif info.fuelConversionRate > 999999 then
- fuelConversionRate = (info.fuelConversionRate / 1000000)
- fuelMeasure = " mb/t"
- else
- fuelConversionRate = info.fuelConversionRate
- fuelMeasure = " nb/t"
- end
- -- Draw screen
- if term.isAvailable() then
- function modify_eff(offset)
- local eff = ((output_flux / input_flux) * 100)
- if eff > 100000 then
- eff = 1
- end
- end
- local left_margin = 2
- local spacing = 1
- local values = {
- "Draconic Control™ [v14-xPID | KiSBN88r]",
- " ",
- " Reactor Statistics",
- "┌───────────────────────────┬────────────────────────────┐",
- string.format("│Time Until Refuel: │ %5.0fd, %2.0fh, %2.0fm, %2.0fs │", secondsToExpire/86400, secondsToExpire /3600 % 24, secondsToExpire/60 % 60, secondsToExpire % 60),
- string.format("│Ideal Field: │ %7.3f%% │", idealField),
- string.format("│Current Field: │ %7.3f%% │", ((info.fieldStrength / info.maxFieldStrength) * 100)),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Fuel Remaining: │ %7.3f%% │", ((1 - info.fuelConversion / info.maxFuelConversion) * 100)),
- string.format("│Fuel Use Rate: │ %7.3f" .. fuelMeasure .. " │", fuelConversionRate),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Temperature │ %7.1f°c [%8.1f°f] │", info.temperature, ((info.temperature * 1.8) + 32)),
- string.format("│Ideal Temperature: │ %7.1f°c [%8.1f°f] │", idealTemp, ((idealTemp * 1.8) + 32)),
- "├───────────────────────────┼────────────────────────────┤",
- string.format("│Energy Input: │ %13.1f RF/t │", inflow),
- string.format("│Energy Output: │ %12.1f RF/t │", outflow),
- "└───────────────────────────┴────────────────────────────┘",
- " ",
- " "
- }
- local values2 = {
- " ",
- " ",
- " ",
- " [Reference Table]",
- " ┌─────────────┬─────────────┬─────────────┐",
- " │ Temperature │ Remaining │ Consumption │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 14000 │ 93.27 │ 91.90 │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 15000 │ 59.00 │ 123.5 │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 16000 │ 36.45 │ 161 │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 17000 │ 21.40 │ 204 │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 18000 │ 11.80 │ 251 │",
- " ├─────────────┼─────────────┼─────────────┤",
- " │ 19000 │ 03.89 │ 303 │",
- " └─────────────┴─────────────┴─────────────┘",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- string.format("Energy Saturation: %4.3f", info.energySaturation),
- string.format("Max Fuel [nb]: %4.3f", (info.maxFuelConversion * 1000000)),
- string.format("Fuel Remaining [nb]: %4.3f", ((info.maxFuelConversion - info.fuelConversion) * 1000000)),
- string.format("Current field drain is %g RF/t", info.fieldDrainRate),
- string.format("Field Deviation: " .. unicode.char(8776) .. deviation .. "%%"),
- string.format("Input Flux Gate: [" .. input_flux.address .. "] Set To: " .. inflow),
- string.format("Output Flux Gate: [" .. output_flux.address .. "] Set To: " .. outflow),
- " ",
- " PID Values",
- " ",
- string.format("I: P%12.1f, IS%12.1f, I%12.1f, D%12.1f, DL%12.1f, C%12.1f", proportional_field_error, inflow_I_sum, integral_field_error, derivative_field_error, inflow_D_last, inflow_correction),
- string.format("O: P%12.1f, IS%12.1f, I%12.1f, D%12.1f, DL%12.1f, C%12.1f", proportional_temp_error, outflow_I_sum, integral_temp_error, derivative_temp_error, outflow_D_last, outflow_correction),
- }
- term.clear()
- if Mode == 2 and Mode ~= 3 then
- for i, v in ipairs(values2) do
- term.setCursor(left_margin, i * spacing)
- term.write(v)
- end
- end
- if Mode ~= 3 then
- for i, v in ipairs(values) do
- term.setCursor(left_margin, i * spacing)
- term.write(v)
- end
- end
- -- Draw button values
- term.setCursor(temp_adjust_x_offset, temp_adjust_y_offset+10)
- term.write("Reactor Temperature")
- term.setCursor(field_adjust_x_offset+1, field_adjust_y_offset+10)
- term.write("Field Strength")
- -- Draw Buttons
- gpu.setForeground(0x000000)
- for bname, button in pairs(buttons) do
- if button.depressed then
- button.depressed = button.depressed - 1
- if button.depressed == 0 then
- button.depressed = nil
- end
- end
- if button.condition == nil or button.condition() then
- local center_color = 0xBBBBBB
- local highlight_color = 0xCCCCCC
- local lowlight_color = 0x808080
- if button.depressed then
- center_color = 0xAAAAAA
- highlight_color = 0x707070
- lowlight_color = 0xBBBBBB
- end
- gpu.setBackground(center_color)
- gpu.fill(button.x, button.y, button.width, button.height, " ")
- if button.width > 1 and button.height > 1 then
- gpu.setBackground(lowlight_color)
- gpu.fill(button.x+1, button.y+button.height-1, button.width-1, 1, " ")
- gpu.fill(button.x+button.width-1, button.y, 1, button.height, " ")
- gpu.setBackground(highlight_color)
- gpu.fill(button.x, button.y, 1, button.height, " ")
- gpu.fill(button.x, button.y, button.width, 1, " ")
- end
- gpu.setBackground(center_color)
- term.setCursor(button.x + math.floor(button.width / 2 - #button.text / 2), button.y + math.floor(button.height / 2))
- term.write(button.text)
- end
- end
- gpu.setBackground(0x676767)
- gpu.setForeground(0x220000)
- end
- -- Wait for next tick, or manual shutdown
- local event, id, op1, op2 = event.pull(0.05)
- if event == "interrupted" then
- if safe then
- break
- end
- elseif event == "touch" then
- -- Handle Button Presses
- local x = op1
- local y = op2
- for bname, button in pairs(buttons) do
- if (button.condition == nil or button.condition()) and x >= button.x and x <= button.x + button.width and y >= button.y and y <= button.y + button.height then
- button.action()
- button.depressed = 3
- end
- end
- end
- end
- term.clear()
Advertisement
Comments
-
- !!WARNING!!
- This program has a hard time compensating for modified power
- output values in your config. No Refunds. This is to be used
- on a world with stock configs, and is only functionally better
- than sMAT when using the chaos shard generation mode.
- !!WARNING!!
Add Comment
Please, Sign In to add comment
Advertisement