Do you write functions for your code?

My team’s code is pretty simple this year so we just slapped our series of if statements for autonomous and a couple of independent if statements for user_routines inside the normal functions without changing much, but i was curious how many other coders actually did things nice and proper and wrote functions and such. If so, where do you put them and what have you found the most convenient?

haha i wish i had time for preform_autonomus_route(“section 1”);

wow, you actually end your sentence with a semicolon. What does your English teacher think?

Yeah, everything we did was nicely done into functions. (well, everything I did) Functions are much better, even if they only contain three lines of code. :slight_smile:

I did what made logical sense to me. Any similar robot functions were grouped together into an actual code function.

I believe I had one for drive motors, one for an arm motor, one for all of our solenoids, and one for our compressor. And then some more random small ones that I don’t even remember what they did.

Functions keep things cleaner, and if you have the time to set it up, use it.

I shouldn’t be talking since our robot barely worked, but we used a select statement to switch between autonomous modes in user routines fast. This “in theory” will make our autonomous failsafe if the desired mode encounters a problem.

autoMode = DEAD_RECKON;

	switch (autoMode) 
	{
	case DONOTHING:
		break;

	case DEAD_RECKON:			/* Dead_Recockning */
		// MyTimerInterrupt is calling Handle_DeadReckoning
		//rr_auto_mode_dead_reckoning();

// RR_LEFT_DRIVE_MOTOR = leftScaledSpeedCmd;
// RR_RIGHT_DRIVE_MOTOR = rightScaledSpeedCmd;
// RR_LEFT_DRIVE_MOTOR = 157;
// RR_RIGHT_DRIVE_MOTOR = 175;

		if(RR_OPTICAL_SENSOR_1 == 1)
			autoMode = LINE_TRACKING;
		break;

	case KNOCK_BALL:	
		// put something here
		break;

	case LINE_TRACKING:
	rr_auto_mode_line_tracking();
		break;

	case DONOTHING:
		break;

	}

We’re using a PID control loop also in our autonomous, taking in feedback from 2 encoders mounted on the left and right drive train. We ended up disabling a good portion of it since the encoders kept getting dislodged. Anyone else use a PID loop with success?

I understand the theory behind it, but id be interested in seeing some actual implementations of it, especially ones including the I and D not just the P in Proportional, Integral, Differential

I reallly appreciate the new ability of C to give us not only real functions, but multiple files. I took full advantage of it. (Granted, during the “heat” of a coding session while working on the robot, the code often digressed into horrible slurs of barely legible mush … I did clean it up a bit so others could understand it though ;))

An example you say? Well, we have an arm that picks up the 2x multiplier, but it tends to backdrive badly, making it difficult to control with the joystick. So, we put in some “antibackdrive” code to stop this, which I put in functions … including a function to move the arm to a given setpoint (it has a pot on it), which proved useful for the auto ball-knock-down routine.

Oh, and as for the many files I had: obviously, a custom_defs file for all of the many constants a robot always seems to need (much quicker access than scrolling through pages of pbasic code!); and, something that proved particularly useful at vcu, a file named cond_comp.h. That is, conditional compilation. Everything in it is just commented out (shock!) – there’re just a bunch of tests to do in the pit; e.g., test acceptance angle of IR sensors/make sure they haven’t broken (funny little things like to do that), we have a “harpoon” whose chain tends to break if we come in too hard, so power is limited in the code when it is too close (another pot on it) … but when pot is removed and we redo limits, there’s a test that debugs the pot values, removes the limit code and sets a low speed setting for the motor … etc. You can imagine that this saves a lot of time having it all thought out ahead of time, just commenting/uncommenting and testing away. I know there’s a thread saying just the opposite … but I love C!

actaully, the SW we are creating for these machines is realtime embedded code

remember that the C compiler will convert your code into assembly code, and from that into machine code

breaking your code up into many little functions makes it look nice, but it actually takes longer for it to run, and takes up more code space, because the function calls are actully jumps in assembly code

its shorter and faster to have sequential code all in one routine that simply falls through to the next statement.

not that we really have to be concerned with optimizing our code for size or speed.

well wait, I have seen some people posting that they have used up all the available code space this year - so maybe some of us got a little carried away with the functions :^)

Yep guys, Ken’s right on the money with this one.

Functions are great for repeated routines that are called at different times with different arguments, but using functions just for the sake of using functions is wasting your CPU power!

Every time you call a function, the processor has to push all its arguments and the return address onto the stack, goto the function address, execute the function, return to the main routine and clear the stack elements added.

If the function is there just to make your code look pretty, you’re wasting CPU cycles on the robot.

On processors without big pipelines (x86, etc have big pipes, especially Intels), function calls are relatively cheap, especially for FIRST robots. The big thing you have to watch out for is stack space, as the PIC can only natively handle 16 nested function calls. There are ways around this limit (like writing your own stack handler), but they tend to be messy and ridiculously hard to debug in addition to being a pain in the neck to write if you’ve never done it before. Anyways, just be careful that you don’t have calls 16-levels deep and everything should be just fine.

We had the same problem someone else mentioned: a long, double-jointed arm that would fall under the weight of gravity. We ended up writing a PI loop to solve the problem. We use pots on the joints (that sounds wrong), which we use to maintain either a target velocity or a target position. It actually works really well for us.

We’re a little busy right now, but we may write something up about it eventually.

In terms of organization, we also split most of our code into different files. We have a lot of code for the arms that would only get more confusing if it were thrown in with the general usage code (same with the drive code), especially because the arm is only updated on interrupts (5 and 10 times a second).

It’s very nice in terms of development, because everything is seperated, we know where it all is, and we can work on different parts of the code at the same time. If we are having problems, it is very easy to take part or all of the file out of the system while we test other things.

As long as you don’t go overboard, I think the chip should be fine handling multiple function calls–the power is enough that you are going to get through an entire loop in less than the “required” time when new data comes in/interrupt is fired. I think at the very maximum we could have five nested functions (main loop, function called, interrupt handler, arm code, arm position code), and there have been no problems as yet.

There’s also a lot to be said for standardized naming conventions and using #define.

Standardized naming conventions (InitializeGyro(), InitializeEncoders(), InitializeAutonomous() etc) can prevent a lot of searching to fix typos. It also increases the clarity and readability of your code.

#defines become almost essential when dealing with complicated expressions and equations. It’s a lot easier to have a series of clearly labeled constants in a header file than to wade through a line wondering what 3 / 16, 82, 5, and 37 represented. Also, having constants in a header file makes changing certain often used values incredibly easier. There is no degradation in program speed because the compiler replaces the constants with the specified value at run time.

We have a couple main files which we added our stuff to, according to category. The main categories that we had were autonomous, operator, and utilites. This worked well as it kept the file numbers managable, but still seperated things out.

We have a few more… =)

This list I can recall atm: 254_arm, 254_auton, 254_drive, 254_encoders, 254_utilities, 254_interrupts, 254_timers, 254_recordable (recordable autonomous, work in progress)…hmmm, I think that’s it, might be one more somewhere.

We’re also working on breaking our pump and gear shifting code to functions for ease of use in autonomous mode.

Im not sure, but don’t good compilers make using functions not so ineffecient? If not, can’t you just use inline to get the same effect as not using functions?

I would have suffered greatly if not for the ability to divide everything into functions this year. Even if some of them are only called once, they still make it much easier to keep code organized, readable, and easy to debug. Our (failed) autonomous code has about 8 separate functions, each of which contains 20-30 lines of code. Trying to keep all that organized within Process_Data_From_Local_IO() would have been a nightmare, but dividing all of it into separate functions made coding a breeze. Sure, it might take another CPU cycle or two to jump to the appropriate memory location, but that’s not much of a problem when the thing’s running at 40 MHz.

I did a lot of the stuff your taliking about. I’ll post some of my hardware-driver code. (don’t have it on me) It includes #defines for every motor, victor, spike, pot, and whatnot. And to top it of, to move the shoulder to a certain position, you call Shoulder_Check(Target). It also includes macros to scale (and translate) the analogs. :smiley:

I used many functions, many just like:

#define square(a) a*a

And also a nice function to turn based on degrees you want to turn. Kickin’.