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

Telling something to a turtle with rednet

Started by BinaryDigit, 20 December 2013 - 06:16 AM
BinaryDigit #1
Posted 20 December 2013 - 07:16 AM
Hello there! I'm not sure if someone has already asked about it, but i have a problem. I'm trying to make a turtle do something with a rednet message, while the turtle is already doing something else. Here's a sample code, to illustrate my point:

rednet.open("right")
function rec() --this is a "receive" function
  id,message,distance=rednet.receive()
end
function right() --this is just a sample function
  while message=="right" do
    turtle.turnRight()
  end
end
function left() -- another sample funct
  while message=="left" do
    turtle.turnLeft()
  end
end
--this is the actual program, i'm using a while true do loop so when i rename the prog as "startup" it will load automatically at reboot and keep running
while true do
  parallel.waitForAny(rec(),right(),left())
end

now, when i try to broadcast a message (for example,"right"), the turtle starts to turn right, as expected; but when i try to broadcast "left", the turtle keeps turning right. Obviously, i'm doing something wrong with "parallel": how can i make a program as the one mentioned? Maybe i have a fix for this, something like (pseudo code):
1)a central computer start spamming "right" or "left" or whatever i type at constant pace
2)turtle start to turn right, at each step send a message to a central computer asking for "job" (right or left, in the above example), hopefully receiving one of the "spammed" messages
3)then the turtle sends back to the computer a message like "received", so the central will stop spamming and waits for another input

Anyways, what's wrong? Thank you for any reply and excuse me for my english, i'm italian :)/>
TheOddByte #2
Posted 20 December 2013 - 10:18 AM
Well why don't you just put it all in a while <condition> do loop?

rednet.open("right")
while true do
    local id, message, distance = rednet.receive()
    if message == "left" then
        turtle.turnLeft()
    elseif message == "right" then
        turtle.turnRight()
    end
end
BinaryDigit #3
Posted 20 December 2013 - 10:31 AM
Thanks a lot for your reply, Hellkid98! But….unfortunately, i have already tried it, and it doesn't work. The turtle turns right (or left) once and then it stops, waiting for another message. My goal is to tell the turtle "right" and then it starts turning right and keep doing it in loop (this is why i used a while loop in right() and left() functions) until i send another command (for instance, "left") in order to do something else..
Edited on 20 December 2013 - 09:58 AM
TheOddByte #4
Posted 20 December 2013 - 11:50 AM
Then would this be useful?

rednet.open("right")
local command = nil
while true do
	local ID, message
	if command ~= nil then
		message = command
		command = nil
	else
		ID, message = rednet.receive()
	end
	if message == "right" then
        local id, msg
		repeat -- Use a repeat loop and check if you have received a message everytime in the loop
            id, msg = rednet.receive(0.3) -- Waiting for a message for 0.3 seconds
			turtle.turnRight()
		until msg ~= nil -- Breaks the loop if the message wasn't nil
		command = msg

	elseif message == "left" then
        local id, msg
		repeat
            id, msg = rednet.receive(0.3)
			turtle.turnRight()
		until msg ~= nil
		command = msg
	end
end
Edited on 20 December 2013 - 10:51 AM
Bomb Bloke #5
Posted 20 December 2013 - 03:48 PM
The reason why neither of those examples work is that most turtle-commands are "event eaters": Any non-turtle-related events received while the turtle's moving around get discarded, and rednet messages come in as events. Meaning the turtle won't "see" a great percentage of the messages sent to it.

The parallel API is a way around this: It allows you to execute a pair of functions side by side, and each gets its own copy of the event queue that the other can't interfere with. You can set one to listen for rednet messages and the other to move the turtle. Check this thread for some more details.
CaseyRobinson #6
Posted 20 December 2013 - 04:40 PM
I would suggest breaking the program into two parts, one to handle the turtle movement and the other to deal with rednet. Something along these lines:


function movement()
  while true do
  if( haveATurnDir() ) then
	doTheTurn()
  else
	sleep(1)
  end
end

function handleRednet()
  while true do
	id, message, disatnce = rednet.receive()
	doTheThingWithTheMessage()
  end
end


rednet.open("right")
parallel.waitForAny( movement, handleRednet )

I just noticed that your call to waitForAny includes the parens () on the function names, so they will be called and their return values passed to waitForAny, which is almost certainly not what you want in that example.
BinaryDigit #7
Posted 21 December 2013 - 07:28 AM
Ok, i've tried the second code provided by Hellkid, and it's kinda strange. Sometimes it works, sometimes don't. I guess that this is because i have to send the message in a certain exact moment. I've tried what CaseyRobinson suggested (don't put the parenthesis after the functions in the "parallel" line), so i rewrited the original code without parenthesis. Nothing changed. I wondered if the problem was related to the fact that i was using while loops for the functions, so i wrote this other code:

-- receive messages
function receive()
  id,message,distance=rednet.receive()
end
--turn  left
function left()
  if message=="left" then
    turtle.turnLeft()
end
end
--turn right
function right()
  if message=="right" then
    turtle.turnRight()
  end
end
--the actual program
rednet.open("right")
while true do
  parallel.waitForAny(receive,left,right)
end

If i execute the code, after few seconds i get this error message (obviously"prova" is the name of the program):

prova:22:unable to create new native thread

I tried to add sleep(0.5) before parallel.waitForAny, the program starts but when i try to broadcast "right" or "left", nothing happens. By now, the most feasible solution is the second code that hellkid wrote…but it would be useful only if i "spam" the message.. definitely i have to learn more about loops and especially dat parallel function