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

Rednet Controlled Mining Turtle (Cobble Generator)

Started by Matplotlib, 18 September 2013 - 06:36 AM
Matplotlib #1
Posted 18 September 2013 - 08:36 AM
I've a problem with activating (here, desactivating) a turtle using rednet… I have a total of 4 programs.
The 3 firsts in the main computer (id 46) :

--startup program
rednet.open("back")
term.clear()
term.setCursorPos(1 ,1)
print("Controle de la Generation de Cobble (on / off)")

--on program
rednet.send(45,"on")
term.clear()
term.setCursorPos(1, 1)
print("Controle de la Generation de Cobble (on / off)")

--off program
rednet.send(45,"off")
term.clear()
term.setCursorPos(1, 1)
print("Controle de la Generation de Cobble (on / off)")

Then, in the Turtle (id 45), I've written this :

--startup program
rednet.open("right")
local id, message, dist = rednet.receive()
while true do
  if message == "on" then
	if turtle.detect() then
	turtle.dig()
	  if message == "off" then
		break
	  end
  end
  elseif message == "off" then
	break
  end
end
os.reboot()

My problem is that the turtle starts mining perfectly well, but it's impossible to stop it (except manually of course)
Lyqyd #2
Posted 18 September 2013 - 10:44 AM
Split into new topic.

Once you start the while loop, you aren't actually checking for any new rednet messages, so the value of the "message" variable will never change.
kreezxil #3
Posted 18 September 2013 - 10:28 PM
Move these two lines around where you have now
local id, message, dist = rednet.receive()
while true do
to

while true do
local id, message, dist = rednet.receive()
I'm willing to bet that solves your current problem.
Matplotlib #4
Posted 19 September 2013 - 03:22 PM
Okay, so I tried what you both told me, so Lyqyd, it's still not working with the while loop like this :

local id, message, dist = rednet.receive()
while message == "on" then
  --code
end

Then, Kiddie, the turtle now doesn't turn on ; it means that it kind of don't receive the message…

Edit : Don't worry, if nothing works fine, I'll implement a manual system inside of the turtle itself !
kreezxil #5
Posted 19 September 2013 - 07:39 PM
Okay, so I tried what you both told me, so Lyqyd, it's still not working with the while loop like this :

local id, message, dist = rednet.receive()
while message == "on" then
  --code
end

Then, Kiddie, the turtle now doesn't turn on ; it means that it kind of don't receive the message…

Edit : Don't worry, if nothing works fine, I'll implement a manual system inside of the turtle itself !

How is this what I and Lyqyd told you to try, your example of what you said you have done looks no different than your original code that is broken. You need this loop

--startup program
rednet.open("right")
while true do
    --[[ having the following here will initialize the variables each time through the loop including the first time, which is what you want. ]]
    local id, message, dist = rednet.receive()
    if message == "on" then
        if turtle.detect() then
            turtle.dig()
            --[[ why is the following here? message is already "on" therefore the following is an unecessary if block ]]
            if message == "off" then
                break
            end
            --[[ end of wtf code ]]
       end
    elseif message == "off" then
        break
    end
end
os.reboot()
Lyqyd #6
Posted 19 September 2013 - 10:39 PM
Or really, since cobble generation is very simple, we can ignore the return value from the dig (and the detect!) and just base it on a short delay:


rednet.open("right")
local cobble = false
os.startTimer(0)

while true do
  event = {os.pullEvent()}
  if event[1] == "rednet_message" then
    if event[2] == "on" then
	  cobble = true
    elseif event[2] == "off" then
	  cobble = false
    end
  elseif event[1] == "timer" then
    if cobble then
	  turtle.native.dig()
    end
    os.startTimer(0.8)
  end
end
immibis #7
Posted 20 September 2013 - 04:09 AM
Or really, since cobble generation is very simple, we can ignore the return value from the dig (and the detect!) and just base it on a short delay:


rednet.open("right")
local cobble = false
local timer = os.startTimer(0) -- edit here

while true do
  event = {os.pullEvent()}
  if event[1] == "rednet_message" then
    if event[2] == "on" then
	  cobble = true
    elseif event[2] == "off" then
	  cobble = false
    end
  elseif event[1] == "timer" and event[2] == timer then -- and here
    if cobble then
	  turtle.native.dig()
    end
    timer = os.startTimer(0.8) -- and here
  end
end

Fixed, in case another program (or even CraftOS) is running other timers at the same time.
kreezxil #8
Posted 20 September 2013 - 07:00 AM
Spoiler
Or really, since cobble generation is very simple, we can ignore the return value from the dig (and the detect!) and just base it on a short delay:


rednet.open("right")
local cobble = false
local timer = os.startTimer(0) -- edit here

while true do
  event = {os.pullEvent()}
  if event[1] == "rednet_message" then
	if event[2] == "on" then
	  cobble = true
	elseif event[2] == "off" then
	  cobble = false
	end
  elseif event[1] == "timer" and event[2] == timer then -- and here
	if cobble then
	  turtle.native.dig()
	end
	timer = os.startTimer(0.8) -- and here
  end
end

Fixed, in case another program (or even CraftOS) is running other timers at the same time.

How is capturing the return value os.startTimer(x) via a declared variable any different than not capturing the return value at all? I really want to know as I am still learn too. :huh:/>
theoriginalbit #9
Posted 20 September 2013 - 07:30 AM
How is capturing the return value os.startTimer(x) via a declared variable any different than not capturing the return value at all? I really want to know as I am still learn too. :huh:/>
os.startTimer returns an id of the timer that has been created, the reason that this is a good thing to capture is because sometimes there can be multiple timers running, not just in your program, but in other things running at the same time too. When a timer finishes the return from os.pullEvent/Raw and coroutine.yields will contain the id of the timer that has finished as well, you can then compare this against what you stored earlier to see if it was your timer that finished or a different timer.

Problematic code

os.startTimer(1) --# assume another program has done this
os.startTimer(2) --# we do this one

while true do
  if event[1] == "timer" then
    break
  end
end

print("Two seconds have passed")
Well in this code, no 2 seconds haven't passed, only 1 has. Now lets fix the code

os.startTimer(1) --# again not ours, some other program
local timeout = os.startTimer(2) --# our timer

while true do
  local event = { os.pullEvent() }
  if event[1] == "timer" and event[2] == timeout then
    break
  end
end

print("2 seconds have passed")
In this example 2 seconds really have passed because we are only responding to our timer, not just any timer.

summary/tl;dr never assume you're the only one making timers, save the id returned from creating the timer and then when it finishes make sure its the one you started
Lyqyd #10
Posted 20 September 2013 - 01:44 PM
Yeah, catching that return value probably isn't a bad idea! Otherwise, one could end up with many more timers than desired. Exponentially more, if another program was exhibiting the same behavior.
kreezxil #11
Posted 21 September 2013 - 06:41 AM
You guys are awesome!