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

How long to wait after setting redstone on dispensers?

Started by D3matt, 06 January 2013 - 06:54 PM
D3matt #1
Posted 06 January 2013 - 07:54 PM
I'm trying to create a firework launching program, and a problem I'm having is getting the length of the redstone pulses correct. I want to launch multiple fireworks from the same launcher repeatedly, but if I go too fast it seems to not detect the redstone input. What is a good value to use? I want it be fast enough that the program doesn't spend a ton of time sleeping (since I'll be using an API to control my launchers), but slow enough that it won't skip ticks. I settled for 0.2 seconds on my test program, but that seems like a big delay for an API to force on a program.

Also, is there a better method to delay setting the bundled outputs to 0 than using os.sleep? I am considering maybe using a timer created each time the launch function is fired, but I am not sure how to create a distinct timer each time the event is fired, or how I would keep track of which wires each timer needs to reset. And that wouldn't prevent the running program from calling the launch function repeatedly on the same wires before they reset. Come to think of it, how would I even pull the timer events when needed? The more I think about it, the more I think about it, the more it sounds like just using os.sleep is the best method, and writing the program and API to minimize the impact of that mandatory delay. A 0.2 second sleep would still allow 5 discrete launch commands per second. But it would be nice to be able to fire multiple launch commands simultaneously.

For reference, this is what I've got so far:


launchdelay = 0.2
launchercluster = {side = "bottom", output = 65535}
function launchercluster:launch (targets)
  local excluded = 65535 - self.output
  local bundleout = targets - excluded
  redstone.setBundledOutput(side, bundleout)
  os.sleep(launchdelay)
  redstone.setBundledOutput(side, 0)
end
function launchercluster:new (o)
  o = o or {}
  setmetatable(o, self)
  self.__index = self
  return o
end
Basically, a program will define a new launcher cluster with the side that it's on and the colors (in decimal form) of that bundle that are included in that cluster. The program then calls the launch function for that cluster, allowing it to launch any combination of colors included in that cluster. IE: If I call launch(65535) but only the colors corresponding to 32767 are a part of that cluster, only those colors will launch. (At least, that's how I hope that bit of code works, I haven't actually tested it yet since the server I was working on is down…)
theoriginalbit #2
Posted 06 January 2013 - 09:17 PM
If memory serves I believe the total time that the dispensers 'tick' for is 0.8 seconds… and I think it needs 0.1 to it to activate, meaning a difference of 0.7… i could be mistaken thought, Mojang may have changed it in some of the latest updates.
D3matt #3
Posted 06 January 2013 - 10:18 PM
The redstone doesn't need to be active for the entire length of the dispenser's "tick" though, just long enough to trigger it. I KNOW it's a lot less than 0.8, though. I had it at 0.1 successfully in a loop (with no delay before setting the bundles back to 0) before, but I had issues with the intro to my show so I added some delays there, and for some reason that completely broke my loop until I added 0.2 second delays after every single step.
D3matt #4
Posted 06 January 2013 - 10:50 PM
On the other hand, my entire idea may be out the window since I can't seem to access the methods of the launchercluster class from outside the API itself.

EDIT: Actually, launchercluster itself seems to be nil from outside of the API.
theoriginalbit #5
Posted 06 January 2013 - 11:08 PM
ok so here may be a stupid question. but are you making the object before trying to run it? or are you loading the API? lastly, is there a particular reason you are implementing it as an object?
D3matt #6
Posted 06 January 2013 - 11:31 PM
Nevermind. I forgot the most important line: The one that actually returns the object. (I just updated the code in the OP to reflex a few fixes I made. My code is always sloppy the first time through)

However, I could use some help with the color code part. I want to only be activating the colors that are part of the defined cluster. However, I'm pretty sure I royally screwed that part up, because the results are nowhere near what I was expecting. Should I be doing something with the bit API here? Maybe if I invert the binary value of both my target range and the excluded range and AND them, lastly inverting them again…? Do you even understand what I'm trying to say or am I explaining it poorly? Basically, if there is a 0 in that bit in the output value, it cannot be set by the launch function. I thought I could do it with simply decimal subtraction, but I am now starting to think that I will need more than that. But it's really late and I can't be looking at it tonight.
D3matt #7
Posted 07 January 2013 - 07:14 AM
Nevermind, I got that figured out too. I was way overthinking it and forgot what AND actually is. Now, I just need the original question posed in the OP figured out.
theoriginalbit #8
Posted 07 January 2013 - 11:17 AM
Sorry was asleep… Which question was that?
D3matt #9
Posted 07 January 2013 - 12:35 PM
How long to wait between changes to redstone for dispensers to detect it, and what the best method to enforcing that delay is.

I did some testing and found the smallest I can do is 0.16 with a sleep(0) between each cycle. But I'm still not sure what the best way to put that delay in is while still allowing seperate clusters to be controlled during that delay. I'm using os.sleep right now, but the only way to launch multiple clusters at the same time with that would be to add some overly complicated function to launch from multiple clusters at once.
theoriginalbit #10
Posted 07 January 2013 - 12:45 PM
well there is two methods. first would be to use the parallel api which would allow multiple functions to run. however for this use case I believe that os.pullEvent() would work nicely. using pullEvent and os.startTimer then you could detect which timer has fired and act based off that. also there is no need to use sleep then especially the sleep(0) as the program would now yield…
D3matt #11
Posted 07 January 2013 - 01:07 PM
well there is two methods. first would be to use the parallel api which would allow multiple functions to run. however for this use case I believe that os.pullEvent() would work nicely. using pullEvent and os.startTimer then you could detect which timer has fired and act based off that. also there is no need to use sleep then especially the sleep(0) as the program would now yield…
I can't use timers and pullEvent, because the API would have no way to listen for the event. That would have to be in the main program, and the main program would have to be in the form of a pullEvent loop, which wouldn't really work. So I guess parallel it is. Would I want waitForAny or waitForAll in this case?
NeverCast #12
Posted 07 January 2013 - 01:12 PM
waitForAny will quit when either of the coroutines finish, waitForAll waits for all of them to finish.

In this case I'd assume you would want waitForAll.
D3matt #13
Posted 07 January 2013 - 01:16 PM
Thanks. I think I've got a pretty good handle on this now.
Cloudy #14
Posted 07 January 2013 - 08:31 PM
Just FYI - turtles can turtle.place() fireworks.
theoriginalbit #15
Posted 07 January 2013 - 10:15 PM
Just FYI - turtles can turtle.place() fireworks.
Ahh that's good to know. One thing I never tested. Lol.
D3matt #16
Posted 08 January 2013 - 08:28 AM
Just FYI - turtles can turtle.place() fireworks.
Hmmm, very interesting. I think I'll stick with dispensers though, this project would require too many turtles communicating to be practical.