View difference between Paste ID: eaTTtFwJ and 6gUUv3Ng
SHOW: | | - or go back to the newest paste.
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
3+
--Made by MrJohnDowe
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