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

unexpected program behavior. What do I wrong? (about timers?)

Started by notgodsarmy666, 13 March 2012 - 11:29 AM
notgodsarmy666 #1
Posted 13 March 2012 - 12:29 PM
Spoiler

role=2
input="3"
-- variables above: basicly what is generated by a other part of the program

input=tonumber(input)
local function client()
rednet.open("top")
while true do
  event, p1,p2,p3,p4,p5 = os.pullEvent()
  sleep(0.9)
  rednet.send( input, "OK" )
  if event=="rednet_message" and p1==input and p2=="OK" then break end
end
local reactorFilled=0
local reactor1=0
local reactor2=0
local reactor3=0
local reactor4=0
local meltdown=0
--
--error()
loop=0
pulse=os.startTimer(0.2)
while true do
  event, p1,p2,p3,p4,p5 = os.pullEvent()
  if event=="timer"  then --and p1=="pulse"
   out=0
   if loop==0 then
	loop=1
	--swriteContent(4,"loop=1							 ")
	if reactor1==1 then out=colors.combine(out,colors.green,colors.lime) end  
	if reactor2==1 then out=colors.combine(out,colors.purple,colors.mangenta) end
	if reactor3==1 then out=colors.combine(out,colors.blue,colors.lightBlue) end
	if reactor4==1 then out=colors.combine(out,colors.red,colors.orange) end
	pulse=os.startTimer(0.2)
   else
	loop=0
	if reactor1==1 then out=colors.combine(out,colors.green) end  
	if reactor2==1 then out=colors.combine(out,colors.purple) end
	if reactor3==1 then out=colors.combine(out,colors.blue) end
	if reactor4==1 then out=colors.combine(out,colors.red) end
	pulse=os.startTimer(0.2)
   end
   redstone.setBundledOutput("back", out)
  end
  if event=="rednet_message" and p1==input then
   if p2=="OK" then sleep(0.5) rednet.send( input, "OK" ) end
   if p2 == "u" then reactorFilled=fillReactor() end
   if p2 == "1" then reactor1=1 message="1" pulse=os.startTimer(0.2) end
   if p2 == "2" then reactor2=1 message="2" pulse=os.startTimer(0.2) end
   if p2 == "3" then reactor3=1 message="3" pulse=os.startTimer(0.2) end
   if p2 == "4" then reactor4=1 message="4" pulse=os.startTimer(0.2) end
   if p2 == "X" then
	meltdown=1
	message="X"
	redstone.setBundledOutput("back", 32767)
	swriteContent(2,"								   ")
	swriteContent(3,"Good bye. See you on the other side")
	swriteContent(4,"								   ")
	swriteContent(5,"Or you better run fast, NOW!")
	break
   end
  end
  if event == "char" and p1 == "P" then redstone.setBundledOutput("back", 0) break end
  if message then rednet.send( input, message ) message=nil end

end
return
end
if role=="1" then master() end
if role=="2" then client() end
it seems while copy pasting it I have lost one indent
and because its hard to read this way, same as pastebin
So what I intended to do was:
a regular check if the other computer has send a message
[indent=1]if it has, confirm that message and store that state in varibales[/indent]
and pulse redstone in a very short time (the length of 0.2 for debug reasons it has to be 0.1 for final)

in this version it shold turn on some of the bundled redstone for 200ms and turn them off for another 200ms

but this it not how it behave.
it flickers in a very short time very unregulary. even if only one command is send this computer.

Where is the Bug I don't see?

btw. "pulse2 is the only timer started the function master() has also one it it but isn't called on this computer
Espen #2
Posted 13 March 2012 - 12:59 PM
The first thing that jumps out at me is that you used sleep() within your event loops.
This is problematic, because every event that happens during the sleep() will be ignored by your event loop, because they happen during sleep().
Try to use timers instead. I haven't analysed the code thoroughly yet, but this is at least one problem that will mess up your event recognition.

A small example to replace sleep() in an event loop with a timer:
local sleepTimer

while true do
  local event, p1, p2 = os.pullEvent()

  if event == "rednet_message"
	redstone.setBundledOutput( "back", colors.white )  -- Power white color on cable.
	sleepTimer = os.startTimer(0.5)  -- Start 0.5 second timer.
  end

  if event == "timer" and p1 == sleepTimer then
	redstone.setBundledOutput( "back", 0 )  -- Turn off cable.
  end
end
Every time a rednet_message comes in it will power on the white color on the cable and start a 0.5 second timer.
As soon as that timer runs out, it will turn off all power on the cable again.
The difference to sleep(0.5) is that it doesn't stop listening for events while the timer is running.
That means if there's an incoming rednet_message during the 0.5 seconds, it will turn on the white color again and re-start the timer, regardless if it was still running.
Edited on 13 March 2012 - 12:04 PM
notgodsarmy666 #3
Posted 13 March 2012 - 03:49 PM
the "if p2=="OK" then sleep(0.5) rednet.send( input, "OK" ) end" is an expection, it only happens if the other computer isn't ready for comunication, umm maybe I should start the timer there instead of after every incomming message
edit4: sleep is necessary, because the message and only this message has to be send delayed, because (donno really why**) the other computer ignores every message which is send before something

edit: with other words the counterparts sendig only "OK" for the handshake

edit2: the thing that is concerning me:
instead of: 0.2s on, 0.2s off, 0.2s on, 0.2s off, 0.2s on, 0.2s off, 0.2s on, 0.2s off, 0.2s on, 0.2s off, 0.2s on, 0.2s off, 0.2s on, 0.2s off
something like this happens: 0.2s on, 0,05s off, 0.02s on, 0.1s off, 0.5s on, 0.01s off …

with other words: very random in every case, I can't tell when or how long it is on or off.

(since I control machines with that, it has to be at least 0.1s)

edit3: I didn't intend to turn redstone on only a single time per message, its more like if a specific message comes in it changes (right now it only sets it) a var, and this var determinates


——————–
**= … maybe because he is doing which includes a sleep, but only because of this exception I don't wanna rewrite this part (now).
Edited on 13 March 2012 - 03:10 PM