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

Script waits longer than defined in os.sleep

Started by BlackStar, 30 August 2014 - 03:47 PM
BlackStar #1
Posted 30 August 2014 - 05:47 PM
Hello,
I am currently starting out using ComputerCraft.
At the moment I am trying to set up a computer that monitors my energy storage (Thermal Expansion Energycells) using open peripherals in FTB Monster.

Most of the code I have currently is copied from different tutorials and adjusted to the needs of my System as I don't have good knowledge of lua.
code: http://pastebin.com/7sXChvBD (Will be kept up to date)

The code is supposed to constantly check my energy and if neccessary activate a Netherstar Generator.

The problem I have is, that although I have specified my sleep timers as 2 times 0.25 seconds if the generator is running, to keep my display up to date and 0.5 seconds when it is not running, It takes far longer to execute. (The times were initially doubled, I cut them in half for testing purposes)
As it is now, While the generator is running, It takes 3 seconds to proceed the countdown by 1 second. So it updates my screen every 1.5 seconds. While the generator is not running, it updates roughly every 2 seconds.
I wouldn't care about the long update times, but the countdown should be accurate, as It can only start the generator again once it is finished.

The sleep timer are in lines: 144, 176, 194

The game is running at 20 TPS, so this is not causing the long delays.

I hope someone can help me with the problem, thanks in advance
MKlegoman357 #2
Posted 30 August 2014 - 08:16 PM
I think there was a lag issue when a lot of peripherals are connected with long-distance wires (wired modems). In your case you are getting information from 12 cells, try something like this to test how much it takes to get information from the energy cells:


...

local start = os.clock()

for j=#storageUnits,1,-1 do
  storageUnit = storageUnits[j]
  capacity = capacity + net.callRemote(storageUnit["id"], "getMaxEnergyStored", "unknown")
  amount = amount + net.callRemote(storageUnit["id"], "getEnergyStored", "unknown")    
end

print("Getting info took: ", os.clock() - start, " seconds")

...
BlackStar #3
Posted 30 August 2014 - 09:19 PM
I added that code at the end of my program and it output 1.2 seconds, does that mean it just takes to long to get all the information? I don't think distance should be an issue, since I only used 19 cables to connect all cells and my monitor.

Do I have to use less cells or would wireless modems improve the situation?
flaghacker #4
Posted 30 August 2014 - 09:33 PM
Wireless modems don't work for peripherals.

I think the problem is that the methods from openperipherals yield internally.
I don't think there's anything you can do about this, except maybe coroutines.
BlackStar #5
Posted 30 August 2014 - 10:01 PM
Could you maybe explain what you mean by coroutines? As I said, I'm still a beginner and don't know all of this stuff (yet :D/> )

Something I thought about that might help would be to use if statements, since I know how the energy flows inside my "battery" So for example if the second cell Is full, all following cells are bound to be full as well. I think I will try this tomorrow.

Edit: Or would it be possible to write the Countdown as a seperate program that is executed when neccessary while the rest just continous along?
Edited on 30 August 2014 - 08:08 PM
Bomb Bloke #6
Posted 31 August 2014 - 01:53 AM
I'd just integrate MKlegoman357's code into your script proper.

That is to say, take this structure:

		minute = 2
		second = 0
		while minute > 0 or second > 0 do
			mon.setCursorPos(3,11)
			mon.clearLine()
			if second >= 10 then
				mon.write("ONLINE:  " ..minute.." : "..second.." Remaining")
			else
				mon.write("ONLINE:  " ..minute.." : 0"..second.." Remaining")
			end
		
			.
			.
			.
				
			if(minute==2) then
				rs.setBundledOutput(rednetside, colors.red) 
			end
			if(second==0) then
				minute = minute-1
				second = 59
			else
				second = second-1
			end
		end

… and turn it into this structure:

		local remainingTime = 120
		while remainingTime > 0 do
			local startTime = os.clock()
			
			mon.setCursorPos(3,11)
			mon.clearLine()
			
			local minute, second = tostring(math.floor(remainingTime/60)), tostring(math.floor(remainingTime%60))
			mon.write("ONLINE:  " ..minute.." : "..(#second==1 and "0" or "")..second.." remaining")
		
			.
			.
			.
			
			if(remainingTime==120) then rs.setBundledOutput(rednetside, colors.red) end
			remainingTime = remainingTime - os.clock() + startTime
		end
natedogith1 #7
Posted 31 August 2014 - 03:35 AM
Might I suggest changing

for i=#storageUnits,1,-1 do
	storageUnit = storageUnits[i]
	capacity = capacity + net.callRemote(storageUnit["id"], "getMaxEnergyStored", "unknown")
	amount = amount + net.callRemote(storageUnit["id"], "getEnergyStored", "unknown")	
end
to

local funcs={}
for i=#storageUnits,1,-1 do
	funcs[i]=function()
		storageUnit = storageUnits[i]
		capacity = capacity + net.callRemote(storageUnit["id"], "getMaxEnergyStored", "unknown")
		amount = amount + net.callRemote(storageUnit["id"], "getEnergyStored", "unknown")
	end
end
parallel.waitForAll(unpack(funcs))
The change should make all the calls run in parallel, helping to mitigate the fact that OpenPeripheral sometimes won't return from their functions until a tick occurs.
BlackStar #8
Posted 02 September 2014 - 10:04 PM
Hi,
thanks for all your help.
I finally got around to rearrange my setup and in the process I applied both your fixes, Bomb Bloke and natedogith1.
When I did this another problem occured, Percentage of storage was displayed as "nil%" and Current Energy was 0. I then reverted the change by natedogith1 and now My display works again. I don't know why that happened, but since everything is working now I guess it doesn't matter.
Again thanks for your help :)/>
natedogith1 #9
Posted 03 September 2014 - 02:07 AM
Might I ask to see how you implemented my fix (I've used it myself recently and want to make sure I'm not going to break my own stuff as well)
Bomb Bloke #10
Posted 03 September 2014 - 02:22 AM
Presumably the OpenPeripheral functions work by throwing and catching events. If they don't stick some sort of unique identifier on those events (similar to timer IDs), then running them in parallel will cause a messy collapse.

That said, even if that is the case and the solution's unworkable, I still consider it an excellent idea.
BlackStar #11
Posted 03 September 2014 - 09:43 AM
Might I ask to see how you implemented my fix (I've used it myself recently and want to make sure I'm not going to break my own stuff as well)
There you go: http://pastebin.com/1t4hnyMg