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

sending rednet commands

Started by shiskebab, 01 May 2014 - 10:01 AM
shiskebab #1
Posted 01 May 2014 - 12:01 PM
hi all i am writing a program that sends commands to my mining turtles. how the setup works is the turtle in charge will always idle and look for a redstone signal with a specific id and message. once the message has been received it should relay that message to another turtle and start digging

terminal that sends the signal:

local function one()
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("sending dig commands")
   print ("waiting for response...")
   sleep(1)
   rednet.open("right")
   rednet.send(17, "startdig") -- sends the "startdig" message to the turtle
   id, message = rednet.receive(10) -- waits 10 seconds for a response
   if id == "17" and message == "digging" then
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("robots are digging!")
   rednet.close("right")
   sleep(2)
   Mainmenu()
   else
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("could not get response from digger after 10 seconds")
   print ("you should probably check on them")
   sleep(2)
   rednet.close("right")
   Mainmenu() -- loops the program back to the Mainmenu()
   end
end

and here is the turtle function supposed to pickup the signals:


local function diggers()
   rednet.open("right")  -- turtle starts by idling until a rednet signal is received
   id, message = rednet.receive()
   if id == "20" and message == "startdig" then -- recognizes only id 20 and message startdig
   rednet.send(20, "digging")
   rednet.send(18, "digging") -- send the dig command to the other mining turtle turtle
   rednet.close()
   for i=1,10 do -- for loop when it is actually digging
   tunnel()
   end
   diggers()
   elseif id == "20" and message "comeback" then -- another alternative command that should make the turtle go back to where it started
   rednet.send(20, "comingback")
   rednet.send(18, "comingback")
   rednet.close()
   turtle.back(tostring(diggings))
   sleep(0.5)
   diggers()
   end
end

i managed to make the terminal program actually send the redstone signal. however, the turtle never does anything with it which makes me think the "if" statements that are supposed to check id's and messages never validates anything.

any suggestions?
OczkoSX #2
Posted 01 May 2014 - 02:57 PM
Maybe seperate programs on turtle? One program will receive rednet signals, second will digging and third will coming back. And in receive program you can do something like this:

id, msg = rednet.receive(10)
shell.run(msg)
and from computer you can send message "dig"
shiskebab #3
Posted 01 May 2014 - 02:59 PM
never mind the above i fixed it by removing the check for "id"

the only think i cant do now is functions apparantly. i have three functions which usually activates one of the other but the program crashes because they cant all be over each other at the same time

(might be a bad explanation)

heres the code:


term.clear()
term.setCursorPos(1,1)
local tunnelerl = 17

local function Mainmenu() -- first function 
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("following commands are valid")
   print ("1 - start branching 10 paces")
   print ("2 - diggers come back to starting point")
   input = read()
   if input == "1" then 
    one() -- trying to call one() but can't because one() isn't stated above this function but under
   elseif input == "2" then 
   two() -- same as one()
   end
end

local function one() -- second function activated by Mainmenu()
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("sending dig commands")
   print ("waiting for response...")
   sleep(1)
   rednet.open("right")
   rednet.send(17, "startdig")
   id, message = rednet.receive(10)
   if message == "digging" then 
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("robots are digging!")
   rednet.close("right")
   sleep(2)
   Mainmenu() 
   else
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("could not get response from digger after 10 seconds")
   print ("you should probably check on them")
   sleep(2)
   rednet.close("right")
   Mainmenu()
   end
end

local function two()
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("sending comeback commands")
   print ("waiting for response...")
   rednet.open("right")
   rednet.send(17, "comeback")
   id, message = rednet.receive(10)
   if message == "comingback" then
    term.clear()
    term.setCursorPos(1,1)
    print ("Welcome to DigNet")
    print ("robots are coming back!")
rednet.close("right")
    sleep(2)
    Mainmenu()
   else 

    term.clear()
    term.setCursorPos(1,1)
    print ("Welcome to DigNet")
    print ("could not get response from digger after 10 seconds")
    print ("you should probably check on them")
    sleep(2)
rednet.close("right")
    Mainmenu()
end
end

local function Mainmenu()
   term.clear()
   term.setCursorPos(1,1)
   print ("Welcome to DigNet")
   print ("following commands are valid")
   print ("1 - start branching 10 paces")
   print ("2 - diggers come back to starting point")
   input = read()
   if input == "1" then 
    one()
   elseif input == "2" then 
   two()
   end
end

Mainmenu()

if i move Mainmenu() to the bottom there is no difference because now function one() and two() can't call Mainmenu()

Maybe seperate programs on turtle? One program will receive rednet signals, second will digging and third will coming back. And in receive program you can do something like this:

id, msg = rednet.receive(10)
shell.run(msg)
and from computer you can send message "dig"

that's actually better than my solution, you think same would work for the functions?
CometWolf #4
Posted 01 May 2014 - 03:15 PM
Your problem is because you're defining your functions locally after you've already defined another function pointing to it.

local function test()
  print(test2()) --this essentially points to _G.test2, or the global test2 of you will
end
local function test2() --this however, is not the same as _G.test2, as this one is local to this script.
  return "hello"
end
To deal with this, we can use a forward declaration

local test2 --this is a forward declaration, now this variable is defined as local to this script, so any later uses of it, will point to the local variable
local function test()
  print(test2()) --now this points to the local variable because of our forward declaration
end
function test2() --note that im not using local here, since this variable is already defined as local. If we had, it would point to yet another local variable instead.
  return "hello"
end
Bomb Bloke #5
Posted 01 May 2014 - 04:52 PM
That still leaves the issue of recursive function calls.

Doing this sort of thing:

function mainmenu()
  either call one() or two() when done
end

function one()
  call mainmenu() when done
end

function two()
  call mainmenu() when done
end

mainmenu()

… will eventually crash out. The reason why is that each time you call a function, the instance of the function which is making the call stays loaded in memory until the next called function ends (at which point the first continues from where it left off - the exception is with tail calls, but they'd be a cop-out here).

If none of your function calls ever end, but rather just keep making more calls indefinitely, eventually you run out of memory and your script errors out with a stack overflow.

One way around this would be to do it like this:

local function one()
  don't do anything special when done
end

local function two()
  don't do anything special when done
end

local function mainmenu()
  either call one() or two() when done
end

while true do  -- Start a loop that repeats indefinitely.
  mainmenu()
end

This structure also happens to remove any need for forward declarations.
Lyqyd #6
Posted 01 May 2014 - 05:49 PM
You can also put the loop in the mainmenu function, of course, so that a return from it is meaningful as well. I actually end up using a slightly more complex system in my multipage menu systems, wherein each page has a draw function and an event handling function. There is a currentDraw and a currentHandler variable that get set in tandem to change pages, with a single event dispatching loop that calls the currentDraw function and passes any relevant events to the currentHandler function. It's not particularly any better or easier, but I like that it keeps things compartmentalized nicely.