Advertisement
civilwargeeky

dynamoControl

Jun 16th, 2014
540
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.54 KB | None | 0 0
  1. --Designed to control dynamos feeding into an energy cell because they DONT limit themselves.
  2. --Designed to work with MFR rednet cable
  3. --Made by civilwargeeky
  4. local checkRate = 10
  5. local emptyPercent = 0.01
  6. local fullPercent = .95
  7. local favorFastCharge = false
  8. local enginesFile = "dynamoEngines"
  9. local peripheralsFile = "dynamoBatteries"
  10.  
  11.  
  12. local function isOn(engine)
  13.   if not engine.isColored then
  14.     return rs.getOutput(engine.side)
  15.   else
  16.     return colors.test(rs.getBundledOutput(side), engine.data)
  17.   end
  18. end
  19.  
  20.  
  21. local engines = {} --A table of engines. #1 is top priority and will be used first
  22. local function addEngine(rf, side, data, isColored) --Data is a number, either the redstone strength or the color.
  23.   isColored = false --Not yet supported
  24.   data = data or 15 --Default strength/color
  25.   local toRet = {rf = rf or 80, side = side, data = data, isColored = isColored}
  26.   toRet.isActive = isOn(toRet, color)
  27.   toRet.id = #engines + 1
  28.   engines[toRet.id] = toRet
  29. end
  30. local cells = {}
  31. local function addCell(side)
  32.   local toRet = {side = side, id = #cells+1}
  33.   toRet.handle = peripheral.wrap(side) or error("Peripheral "..side.." failed to wrap")
  34.   cells[toRet.id] = toRet
  35. end
  36.  
  37. do --This is the file reading portion
  38.   for a, current in pairs({{enginesFile,addEngine},{peripheralsFile,addCell}}) do
  39.     local file = fs.open(current[1],"r") or error("File not found, please use wizard or create "..current[1],0)
  40.     local input = file.readAll()
  41.     if not input or input == "" then error("File empty: "..current[1],0) end
  42.     for line in input:gmatch("[^\n]+") do --Seperates lines
  43.       if not (line:sub(1,2) == "--") then --If not comment
  44.         local toRet = {}
  45.         for entry in line:gmatch("[\"\'_%w]+") do --Matches sets of letters, numbers, quotes, and underscores
  46.           table.insert(toRet,tonumber(entry) or loadstring("return "..entry)()) --This gets numbers as numbers, but still allows non numbers
  47.         end
  48.         current[2](unpack(toRet)) --Makes a new engine/cell from the parameters
  49.  
  50.         --current[2](line) --Better Idea. This 'should' work
  51.       end
  52.     end
  53.   end
  54. end
  55.  
  56. local function engineAt(index)
  57.   if engines[index] then return engines[index] end
  58.   if index <= 0 then return engines[1]
  59.   elseif index > #engines then return engines[#engines] end
  60. end
  61.  
  62. --Program Part--
  63. local function getLocalStored(periph) return periph.getEnergyStored("west") end
  64. local function getLocalMax(periph) return periph.getMaxEnergyStored("west") end
  65.  
  66. local function getCellsInfo(fn) --Generic
  67.   local count = 0
  68.   for a, cell in pairs(cells) do
  69.     count = count + fn(cell.handle)
  70.   end
  71.   return count
  72. end
  73. local function getStored()
  74.   return getCellsInfo(getLocalStored)
  75. end
  76. local function getMax()
  77.   return getCellsInfo(getLocalMax)
  78. end
  79.  
  80. local function getRate(periph, period) --This is the main "waiting" part
  81.   local start = getStored(periph)
  82.   local timer, passed = os.startTimer(checkRate), false
  83.   repeat
  84.     local event, val1, val2 = os.pullEvent()
  85.     if val1 == timer then passed = true
  86.     elseif event == "char" then passed = true
  87.       if val1 == "q" then error("Program ended by user",0) end
  88.     end
  89.   until passed
  90.   local finish = getStored(periph)
  91.   print("Current rate: ",(finish-start)/period/20)
  92.   return (finish-start)/period/20
  93. end
  94.  
  95. local function getPercent(periph) return getStored(periph)/getMax(periph) end
  96.  
  97. local function turnOn(engine)
  98.   if engine.isActive then return false end
  99.   if not color then
  100.     rs.setAnalogOutput(engine.side, engine.data)
  101.   else --I don't care because screw MFR for breaking
  102.   end
  103.   print("Turning on engine ", engine.id)
  104.   engine.isActive = true
  105.   return engine.rf
  106. end
  107.  
  108. local function turnOff(engine)
  109.   if not engine.isActive then return false end
  110.   if not color then
  111.     local toSet = 0
  112.     for a, b in pairs(engines) do --This is for setting to the next analog engine
  113.       if b.side == engine.side then --If we use the same side for analog
  114.         if b.data >= engine.data then
  115.           b.isActive = false --We want to confirm that this one is off too
  116.         elseif b.data > toSet and b.isActive then --We want to turn the power to the next lowest engine
  117.           toSet = b.data
  118.         end
  119.       end
  120.     end
  121.     rs.setAnalogOutput(engine.side, toSet)
  122.   else --I don't care
  123.   end
  124.   print("Turning off engine ",engine.id)
  125.   engine.isActive = false
  126.   return engine.rf
  127. end
  128.  
  129. local function getOutput()
  130.   local toRet = 0
  131.   for a, b in pairs(engines) do
  132.     if b.isActive then
  133.       toRet = toRet + b.rf
  134.     end
  135.   end
  136.   return toRet
  137. end
  138. local function getMaxOutput()
  139.   local toRet = 0
  140.   for a,b in ipairs(engines) do toRet = toRet+b.rf end
  141.   return toRet
  142. end
  143.  
  144. for i=1, #engines do --Maybe make this smarter later. I don't want nonsequential engines on
  145.   turnOff(engineAt(i))
  146. end
  147.  
  148.  
  149. local index = 0 --The currently selected engine that is on
  150. local function addIndex() if index == #engines then return false end index = index+1 return true end
  151. local function subIndex() if index <= 0 then return false end index = index-1 return true end
  152.  
  153. while true do --MAIN LOOP
  154.   for i=1, term.getSize() do write("-") end
  155.   print("Starting loop")
  156.   print("Percent Charged: ",getPercent(cell))
  157.   local rate = getRate(cell, checkRate)
  158.   if getPercent(cell) < emptyPercent then rate = -5000 end --Assuming that the battery is empty
  159.   if rate == 0 then
  160.     print("Assuming battery at max, turning off to save power")
  161.     turnOff(engineAt(index))
  162.     subIndex()
  163.   elseif rate > 0 then
  164.     print("Battery charging")
  165.     if favorFastCharge then
  166.       if getPercent(cell) < fullPercent and favorFastCharge then
  167.         print("Less than full and want fast charge, adding engines")
  168.         while not( rate > (getMax(cell)-getStored(cell))*20*checkRate) and index ~= #engines and favorFastCharge do --Keep adding engines until the rate would instantly fill it, or until we are out of engines
  169.           addIndex()
  170.           rate = rate + (turnOn(engineAt(index)) or 0)
  171.         end
  172.       else
  173.         print("More than full, removing unnessesary enginess")
  174.         while rate > engineAt(index).rf do
  175.           rate = rate - (turnOff(engineAt(index)) or 0)
  176.           subIndex()
  177.         end
  178.       end
  179.     end
  180.   else
  181.     if not(getPercent(cell) > fullPercent) then
  182.     print("Battery draining, trying to stablize")
  183.       while rate < 0 and index ~= #engines and not(getPercent(cell) > fullPercent) do
  184.         addIndex()
  185.         rate = rate + (turnOn(engineAt(index)) or 0)
  186.       end
  187.     else
  188.       print("Battery draining, but full. It's fine")
  189.     end
  190.   end
  191.  
  192. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement