This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Hocico's profile picture

Several Monitors in one program

Started by Hocico, 22 May 2017 - 10:19 PM
Hocico #1
Posted 23 May 2017 - 12:19 AM
Hello guys,

I'm about to write a program to automaticly control my 2 "BigReactors"-reactors. To do so, I've decided to start with the programming of the information-monitor-muliblocks. One for each reactor. To find again everything I need for it, when my server get crashed or deleted, I want to write both, the monitores and reactors, in one methode. And heres comes the issue:

The first monitor-multiblock works perctly fine. The second stays blank.



I've connected the computer via wires to the Monitores.

Cause I'm no pro in lua I don't know how to fix it. I've tried out several things but nothig worked :huh:/>


--Program to control reactors
--and its monitores



-------------Monitorsettings--------------------

---MonitorLeft
lsSide = "monitor_0"
screenX = 1

function pts(out)
  screenX = screenX + 1
  peripheral.call(lsSide, "write", out)
  peripheral.call(lsSide, "setCursorPos",1,screenX)
end

function ptc()
  screenX = 1
  peripheral.call(lsSide,"clear")
  peripheral.call(lsSide,"setCursorPos",1,screenX)
end

peripheral.call(lsSide,"setTextScale",3)

local reactor1 = peripheral.wrap("BigReactors-Reactor_2")

while true do
  ptc()
  pts("	Reactor 1 \n")
  local Running = reactor1.getActive()
  if Running==true then
	pts("Status  :\n".. "online")
  else
	pts("Status  :\n".. "offline")
  end
  pts("RF/t	:\n"..reactor1.getEnergyProducedLastTick())
  local eStored = reactor1.getEnergyStored()/1000
  pts("Loaded :\n"..eStored)
  pts("MB/t	:\n"..reactor1.getFuelConsumedLastTick())
  os.sleep(1)
end
--EndOfMonitorLeft

---MonitorRight
rsSide = "monitor_1"
screenX = 1

function pts(out)
  screenX = screenX + 1
  peripheral.call(rsSide, "write", out)
  peripheral.call(rsSide, "setCursorPos",1,screenX)
end

function ptc()
  screenX = 1
  peripheral.call(rsSide,"clear")
  peripheral.call(rsSide,"setCursorPos",1,screenX)
end

peripheral.call(rsSide,"setTextScale",3)

local reactor2 = peripheral.wrap("BigReactors-Reactor_3")

while true do
  ptc()
  pts("	Reactor 2 \n")
  local Running = reactor2.getActive()
  if Running==true then
	pts("Status  :\n".. "online")
  else
	pts("Status  :\n".. "offline")
  end
  pts("RF/t	:\n"..reactor2.getEnergyProducedLastTick())
  local eStored = reactor2.getEnergyStored()/1000
  pts("Loaded :\n"..eStored)
  pts("MB/t	:\n"..reactor2.getFuelConsumedLastTick())
  os.sleep(1)
end
--EndOfMonitorRight


---------------------------------------------------


--------------Reaktorcontrol----------------------




---------------------------------------------------


I guess the problem might be the


function pts(out)
  screenX = screenX + 1
  peripheral.call(rsSide, "write", out)
  peripheral.call(rsSide, "setCursorPos",1,screenX)
end

function ptc()
  screenX = 1
  peripheral.call(rsSide,"clear")
  peripheral.call(rsSide,"setCursorPos",1,screenX)
end

part of the –MonitorRight section, but I'm not sure about it :huh:/>

It would be nice if you could help me out a bit ^_^/>

Thanks a lot

oh, btw: For a better view, here you have the link to my Pastebinpost (premonition: it contains german words)
Edited on 22 May 2017 - 10:20 PM
KingofGamesYami #2
Posted 23 May 2017 - 12:29 AM
Your first while loop does not end so the second half of your code never executes. Combine everything into one loop.
Bomb Bloke #3
Posted 23 May 2017 - 12:50 AM
You can use peripheral.find() and tables to make such a combination easier:

--Program to control reactors
--and their monitors

--# Bundle peripherals into tables:
local monitors = {peripheral.find("monitor")}
local reactors = {peripheral.find("BigReactors-Reactor")}

--# If we have more monitors than reactors, discard some:
for i = #reactors + 1, #monitors do  --# If #reactors + 1 > #monitors, Lua skips this loop.
	monitors[i] = nil
end

for i = 1, #monitors do              --# For each entry in the monitors table,
	monitors[i].setTextScale(3)  --# ... change the text scale.
end

while true do
	for i = 1, #monitors do
		term.redirect(monitors[i])
		
		--# Getting values from peripheral functions is slow, doing it
		--# immediately before clearing the screen reduces flicker:
		local Running = reactors[i].getActive()
		local EPLT =    reactors[i].getEnergyProducedLastTick()
		local eStored = reactors[i].getEnergyStored()/1000
		local FCLT =    reactors[i].getFuelConsumedLastTick()
		
		term.clear()
		term.setCursorPos(1, 1)

		print(" Reactor " .. i .." \n")
		print("Status  :")
		if Running then print("online") else print("offline") end
		print("RF/t     :\n"..EPLT)
		print("Loaded :\n"..eStored)
		print("MB/t     :\n"..FCLT)
	end
	
	sleep(1)
end

Note that term.redirect() makes it much easier to work with monitors, removing the need for your pts() / ptc() functions.
Hocico #4
Posted 23 May 2017 - 02:02 AM
You can use peripheral.find() and tables to make such a combination easier:

--Program to control reactors
--and their monitors

--# Bundle peripherals into tables:
local monitors = {peripheral.find("monitor")}
local reactors = {peripheral.find("BigReactors-Reactor")}

--# If we have more monitors than reactors, discard some:
for i = #reactors + 1, #monitors do  --# If #reactors + 1 > #monitors, Lua skips this loop.
	monitors[i] = nil
end

for i = 1, #monitors do			  --# For each entry in the monitors table,
	monitors[i].setTextScale(3)  --# ... change the text scale.
end

while true do
	for i = 1, #monitors do
		term.redirect(monitors[i])
		
		--# Getting values from peripheral functions is slow, doing it
		--# immediately before clearing the screen reduces flicker:
		local Running = reactors[i].getActive()
		local EPLT =	reactors[i].getEnergyProducedLastTick()
		local eStored = reactors[i].getEnergyStored()/1000
		local FCLT =	reactors[i].getFuelConsumedLastTick()
		
		term.clear()
		term.setCursorPos(1, 1)

		print(" Reactor " .. i .." \n")
		print("Status  :")
		if Running then print("online") else print("offline") end
		print("RF/t	 :\n"..EPLT)
		print("Loaded :\n"..eStored)
		print("MB/t	 :\n"..FCLT)
	end
	
	sleep(1)
end

Note that term.redirect() makes it much easier to work with monitors, removing the need for your pts() / ptc() functions.

thanks for the code. It looks a lot more professional. And thats the thing :wacko:/>

I don't realy understand what I see there (or maybe its too late? 3:00am). I wrote it down 1:1 (except the parts beginning with –) and now the whole thing doesn't seem to work at all.

Well, I think I'll read this code again tomorrow :D/>

But anyways: thanks a lot. I'm sure I just made a foolish mistake.



Your first while loop does not end so the second half of your code never executes. Combine everything into one loop.

The while loop ends at

pts("Loaded :\n"..eStored)
  pts("MB/t	 :\n"..reactor1.getFuelConsumedLastTick())
  os.sleep(1)
end
--EndOfMonitorLeft
;)/>

Your idea, stupidly doesn't change anything :mellow:/>
But nonetheless: thank you, too :)/>

Good night guys
Edited on 23 May 2017 - 12:03 AM
Bomb Bloke #5
Posted 23 May 2017 - 02:11 AM
and now the whole thing doesn't seem to work at all.

So what DOES it do?

The while loop ends at:

The "end" statement sets the bounds of the code that will be looped, but the code underneath the loop won't run until the loop completes.

A "while true do" loop will never complete unless you use the "break" keyword, so the code underneath will never run.
Hocico #6
Posted 23 May 2017 - 04:07 PM
Hello again,

it took a while till I figgured out how to use the "break" statement, but I guess i have it now :D/>

both monitors are running correctly and stay up to date. :D/>

the first while loop never ends, to keep the program running and updated. Thanks again for the help guys !!

Edit:

local eStored = reactor1.getEnergyStored()/1000
is good to have the 1k dots, but causes the issue that the monitors write 10000 instead of 10.000.000. Is there a way to fix it? And may there be a way too, to fix that it shows me RF/t : 45.6534 (45RF and 0.6534) instead of RF/t : 45 ? It's a bit to detailed :P/>

and now the whole thing doesn't seem to work at all.

So what DOES it do?

a very good question^^ The program is running but both monitors stays black.
Edited on 23 May 2017 - 02:17 PM
KingofGamesYami #7
Posted 23 May 2017 - 07:48 PM
You can use math.floor to remove decimal points. Adding points is a bit harder, and requires more explanation than I am willing to type on my phone (my modem is fried atm).
Emma #8
Posted 24 May 2017 - 02:52 AM
The concept that a dot will appear after every third character starting from the right is enough to figure out how to add the dots. It's easier to treat the number as a string implementation wise and conceptually at this point because it eventually needs to be a string anyways to be drawn to the screen.

So essentially what needs to happen is that you loop from the end of the string to the front, adding a dot after each third character. You can do this with a special for loop like so:

local x = 123456789


local xs = tostring(x)

local exs = ""

for i = #xs - 2, 1, -3 do
exs = "." .. xs:sub(i, i + 2) .. exs
end

local pre = #xs % 3

exs = xs:sub(1, pre) .. exs:sub(pre > 0 and 1 or 2)

-- This part ^^ gets what we missed    /\
-- ....................................||......................
-- The second part decides if we need the seperating dot, if we
-- didn't miss anything (ie pre == 0) we don't need another dot

print(exs)
When executed this prints the following:

123.456.789

And you can easily wrap this in a function. Hope this helps :D/>
Edited on 24 May 2017 - 12:54 AM
Hocico #9
Posted 26 May 2017 - 10:43 PM
Thanks a lot again. It worked :-)
Hocico #10
Posted 31 May 2017 - 12:21 AM
hello again.

I have a new problem, very close to the upper problems (thats why I didn't want to spamm the forum with a new topic) ;)/>

I tried to use an EnderIO storagebank-multiblock to store the energy from the reactors.


local kondensator = peripheral.wrap("tile_blockcapacitorbank_name_0")
local kStored = kondensator.getEnergyStored()

but the program thows the error (here line 2) " attempt to index ? (a nil value) "

I read the linked errorreport and read the line with the error several times and checked it with other codes (line 94(Thermal Expansion Energy Cell)) and my own (line 85(BigReactors Reactor)), but I found no missspelling. So, I guess the command I tried to use on this multiblock does not exist.

can someone tell me what the command is to get the stored energy from the EnderIO-energystorage-multiblock (name: Capacitor Bank)? :huh:/>
Edited on 30 May 2017 - 10:23 PM
Bomb Bloke #11
Posted 31 May 2017 - 01:16 AM
The error is not telling you that "getEnergyStored" doesn't exist in the "kondensator" table. It's telling you that "kondensator" isn't a table, which means peripheral.wrap("tile_blockcapacitorbank_name_0") returned nil. Make sure "tile_blockcapacitorbank_name_0" is truly connected under that name - you may need to break / replace your modems, OpenPeripherals sometimes bugs out and forces you to rebuild your connections.
Hocico #12
Posted 31 May 2017 - 12:06 PM
The error is not telling you that "getEnergyStored" doesn't exist in the "kondensator" table. It's telling you that "kondensator" isn't a table, which means peripheral.wrap("tile_blockcapacitorbank_name_0") returned nil. Make sure "tile_blockcapacitorbank_name_0" is truly connected under that name - you may need to break / replace your modems, OpenPeripherals sometimes bugs out and forces you to rebuild your connections.

Disconnect and reconnect it from the network solved the problem. Thanks

Well….slowly but surely I feel like I'm an idiot. :wacko:/>

I have annother issue now, I can't deal with without your help :(/> (sory for that)



while true do

  local kondensator = peripheral.wrap("tile_blockcapacitorbank_name_0")
  local kStored = kondensator.getEnergyStored()
  local reactor1 = peripheral.wrap("BigReactors-Reactor_0")
  local reactor2 = peripheral.wrap("BigReactors-Reactor_1")
  local reStored = reactor1.getEnergyStored()

  switch (kStored)
    case "<=5000000" : reactor1.setActive(true)
    case "<=1000000" : reactor2.setActive(true)
    case ">=3000000" : reactor2.setActive(false)
  end
  
  if reStored >= 7500000 then
	 reactor1.setActive(false)
  end

  break
  end

This is the code for the reactorcontrol. It throws the error "function arguments expected" for the first "case"-line. I've googled in this forum an found something. But I can't see how this could help me out :unsure:/>
btw: It doesn't seem to matter if its "switch(kStored)" or "switch(kondensator.getEnergyStored())"
Edited on 31 May 2017 - 10:08 AM
KingofGamesYami #13
Posted 31 May 2017 - 03:13 PM
Switch statements do not exist.
Bomb Bloke #14
Posted 01 June 2017 - 01:04 AM
That is to say: use elseif instead.