Second Void

4 replies [Last post]
Roombie
Title: NooBot+
Joined: 04/22/2010
Posts:
BotPoints: 20
User offline. Last seen 12 years 18 weeks ago.

Basically what we're trying to do is run two programs at once. We start off our first program with a void main but once we add the second program with another void insertwhatevername it just doesn't run. Is there a certain name for the second void that we're supposed to use?

We know it is the void that's causing our problem since we isolated the first program and it works fine, but it just doesn't run the second program.

KIPR Matthew
KIPR Matthew's picture
Title: KIPR Staff
Joined: 06/04/2009
Posts:
BotPoints: 154
User offline. Last seen 5 years 3 weeks ago.

The CBC can only run one program at once.

*! Use the following at your own risk. KIPR does not endorse the following, it is only my opinion !*

You can run multiple processes on the CBC. What that does (while still running one program, and even one function at a time) is switch very quickly between two functions, which is what you are referring to. The problem is that there are some bugs and sometimes unexpected results from running multiple processes. That being said, I have also had great success with using processes.

There are a couple of good rules of thumb to keep in mind when using processes that will save you a bigger headache later.

1. Is there any way I can do this with out multiple processes? While processes are great and good, I use them as a last resort.

2. Make sure you are very careful about starting processes.

3. I try to only use two concurrent processes, three at the very most. When you spawn a new processes you increase the latency (delay) of your functions. This goes with 2.

4. Make sure you kill every process you spawn. This goes with 3. If you make 30 process that are doing nothing, you increase latency.

When I talk about latency, I am talking about how long it takes to get back to the original function. If we imagine on a macro scale that the fastest we can process is at one operation per second, then create a new process. We are switching back and forth between each process every other clock cycle. So one second on process one and the next second on process two and the third on process three, and so on. Now if you create a third process it takes one more second, or cycle, to get back to the original function.

Lets go back to the micro scale. If you are doing a loop that updates a sensor value while waiting to do something else, it should be pretty responsive. Now if you spawn a second process, there might be some noticeable lag, and if you spawn a third process there is definite lag in updating the value since, you can only update the value every third clock cycle. In reality it is even slower than that because it will take some clock cycles to evaluate or print the value, and those can only be progressed every third cycle.

This is why I try to keep to rule number 1, since every new process spawned increases latency. In reality, the cycles happen so fast that simple things are not noticeable, but I have run into issues where two functions work fine separately (such as detecting objects or the edge of a table), but when combined using processes they lag too much to be useful.

That being said, feel free to experiment and draw your own conclusions. Here is how to use processes:

start_process(functionName);

functionName is the & followed by the name of the function for example &stay_on_table. The function that you are calling has to be a void type function that does not take any arguments, so void stay_on_table() works, but neither int stay_on_table(), or void stay_on_table(int i) will work.

usually the start_process() function is usually used as:

pid=start_process(&stay_on_table);

pid is just a variable. The start_process() function returns the process id number of the new process. This useful for the kill_process() function:

kill_process(pid);

where pid is the process id number.

Some final notes:
Don't forget that you still need an int main() function, and that the main function is one of your running processes. If you kill a process that was doing something, like driving motors, that will continue until you tell it otherwise, so having an ao() after killing a process running motors is a good idea. The best way to learn is by making mistakes. If you get stuck post where and we will try to offer help.

Join the Botball folding at home team!
http://folding.stanford.edu/
Team 87314 "Botball"
Stats: http://folding.extremeoverclocking.com/team_summary.php?s=&t=87314

PiPeep
PiPeep's picture
Title: RocketBot
Joined: 07/19/2009
Posts:
BotPoints: 170
User offline. Last seen 8 years 28 weeks ago.

Matthew, that was very well stated.

I would just like to add that one of the issues with threading is the sharing of information between your threads (processes). If, in one thread, you are updating a value (or set of values), and then attempt to access that data in another thread, if the thread writing the data was interrupted, you will have partially updated information, which can lead to all sorts of unforeseen bugs.

Although there are ways of ensuring this data writing is done safely (locks), the best way to handle this is simply to not share information between these threads after initialization. Scope is your friend.
Local variables = good
Global variables = bad

Also, you can run multiple programs at one time by forking your current program's execution, but unless you have a real reason for launching another program (like a C program launching a Java program), it should be avoided. Multiple programs running concurrently have an even larger overhead than multiple threads, and information sharing becomes even trickier.

Jeremy Rand
Jeremy Rand's picture
Title: Botball Youth Advisory Council
Joined: 04/03/2009
Posts:
BotPoints: 1168
User offline. Last seen 7 years 18 weeks ago.

To elaborate on what PiPeep said, if you want to run 2 programs (processes, not threads) simultaneously, have the first program run the following command:

system("/mnt/user/code/program2/robot &");

Where program2 is the name of your second program. This will only work if you are running a CBC firmware which supports binary caching (the Norman/Nease Mods v1.2 support this, and I think the latest NHS Patchset does as well; the official KIPR firmware does not, to my knowledge).

That said, threads are probably sufficient (what Matt Oelke was talking about was threads, not processes... interesting how KIPR terminology seems to differ from the terminology everyone else uses). The only time I've needed to do this is when I was launching the Chumby Control Panel and wanted to keep my main program waiting for a Black Button press, at which point it would kill the Chumby Control Panel. Not the kind of stuff that's particularly useful in Botball (albeit nice for hackers).

-Jeremy Rand
Senior Programmer, Team SNARC (2012-2013), Norman Advanced (2010-2011), Norman HS (2008-2009), Norman North (2005-2007), Whittier MS (2003-2004)
2012-2013 VP of Tech, 2011 President, Botball YAC (2009-2013)
Mentor, Alcott and Whittier MS

bsilver
bsilver's picture
Title: NooBot+
Joined: 05/30/2011
Posts:
BotPoints: 9
User offline. Last seen 11 years 16 weeks ago.

If you declare your main as main(int argc, char **argv) argc is the number of command-line arguments. If you check argc early on in the program and split between 2 execution paths, you can use this to run 2 programs at once with KISS-C firmware with something like system("/mnt/user/bin/robot argument &"). In the first one, argc will be 1 while in the second one argc will be 2 (the first argument is always the name of the program). However, all of the issues mentioned above still apply.