If statement in .h file or Indirect addressing? Kevin NAV code...

Ok…so I am not sure how to explain what I need but I know what I want to do.

I am helping our team program this year and really this is the first time I’ve dabble in C code. I normally program PLCs (programmable logic controllers)…anyway…

I noticed that Kevins nav code uses a commands.h file which is a structured something to send commands in a list format to the robot.c file. Very slick and easy. We’ve made our own functions and commands for our automous mode.

What I’d like to do is alter this with some inputs to create multi automous modes. We have all the inputs selections working but not sure what would be the best approach in C code to do what we need.

I want to do something like this:



if (input = 1)
    {
    struct commands command_list] = {

    /*   Command              parm 1     parm 2   parm 3   */

    {CMD_WAIT,                 1000,        0,      0},
    {CMD_DRIVE,                1500,        0,      0},
    {CMD_WAIT,                 4000,        0,      0},
    }
};

Of course that’s not exactly legal in C code…

So if I was doing this in a PLC, I might use what is called indirect addressing, or assigning a varaible to a pointer.

Like:

struct commands command_listmyvarible] =

so if myvarible is equal to 1 then run the commands in list #1. If myvarible is equal to 2 then run the commands in list #2.

Is there such a thing like this in C Code?

I hope that makes sense…

You want the struct you use to be one of a predefined set, that is selected at the beginning of runtime? You could try a big switch() statement that would contain assignment statements.


struct commands mycommand;
switch(input)
{
  case 1:
    mycommand = {...};
    break;
  case 2:
    ..... repeat
}

Not sure if I have the syntax right - it’s late, and I haven’t used structs in a while.

I wouldn’t use a pointer to an array element because you’d be allocating space for structs that would not be used - you wouldn’t switch modes after starting the process.

I think what you’re looking for is to assign a pointer to the correct array of autonomous commands based on some input at runtime.

Example:

.h file:


struct commands command_list_drive_straight] = {

    /*   Command              parm 1     parm 2   parm 3   */

    {CMD_WAIT,                 1000,        0,      0},
    {CMD_DRIVE,                1500,        0,      0},
    {CMD_WAIT,                 4000,        0,      0}
};

struct commands command_list_grab_tetra] = {

    /*   Command              parm 1     parm 2   parm 3   */

    {CMD_WAIT,                 1000,        0,      0},
    {CMD_DRIVE,                1500,        0,      0},
    {CMD_WAIT,                 4000,        0,      0}
};

In .c:


struct commands* cmd_list = NULL;

if(input == 1)
{
    cmd_list = command_list_drive_straight;
}
else if(input == 2)
{
    cmd_list = command_list_grab_tetra;
}
else
{
    /* Don't forget the else, else you'll be accessing a null pointer... :( */
}

etc…

This actually doesn’t matter - the compiler has to store the values that your code will use to initialize the array somewhere inside the program anyway, so it’s essentially the same. Actually, using globals with assigned default values (especially if you make them const) is more efficient because then they can be stored directly in Flash and don’t need to consume any RAM.

Yeah, yeah…great fixer-her-upper. What we got Dave is some thumbwheels from digikey connected to the four inputs on a joyport. Using BCD (0-9), we can run up to 99 different automodes with eight inputs on two ports. I’ll give your example a shot and see what we come up with…PS thanks alot for sharing your thoughts.

Next on the list is shaving more program FAT. Every time we turn around we are at our 32K limit…yuck…We aren’t ready to get rid of the printf statements, we need those to debug but if it keeps it up, we are going to have to dump some printf to get more code packed in…

I found it much easier to use primitives rather than printf. printf takes 4K while a simple set of primitives takes 40 bytes. The ones we use aren’t even the real way I’d normally implement such a thing, but it made a good “hello world” type intro to programming project for the freshmen.

Hey DAVE…

We just wanted to tell you this worked like a champ…BUT…holey-moley…does it eat up some program space… With the default struct command, we had 23K of program space left to mess with. Then we did your suggestions, and we duplicated the struct with three sets to represent three different automous modes, after we done that we now have 28K of complied program…whew… That was a big hit in our software… Anyway though, it worked like a champ, exactly what we need in conjuction with our thumbwheel 0-9 BCD (binary coded decemical) input wheels.

How many commands do you have in each of your autonomous programs? Each “command” inside the commands array looks like it takes up 10 bytes… You’d have to have some pretty big autonomous programs to add 5K. You are just using a pointer to the correct struct, right (versus creating a new struct and assigning the values from the struct in commands.h to it)?

It does…another approach (which might save some memory space), is based on your thumbwheel positions, call a function which puts the dsitred command list into the structure. That way you’ll just have one structure, not multiple copies.

Jon Mittelman
Mentor

I was pretty excited about the scripting idea. I modified the system to allow multiple “scripts” in the one array. I even allowed scripts to call other scripts, subroutine-like. This took a lot of time to get working, but I figured I we would write a short 4-6 command script for each of a dozen different autonomous programmes, and life would be grand.

But by the time I got up to about 7 scripts, the linker said it couldn’t fit the array. I even tried breaking the array up into multiple arrays, but the linker was still upset. I posted a question about modifying the linker script, but, so far, no responses.

Realizing that there is far less RAM for data like script arrays than there is memory for program storage, I threw out my wonderful scripting system and I plan to implement a nested-state machine system. There’s still, what? a week left?

-Norm :ahh:

You can put data like script arrays in the program storage area. Just declare it as a rom const.

You’d be better off declaring all the arrays as rom const as Alan described, because if you have a function copy the data into the struct then all that data still has to reside in Flash AND then you end up using a bunch of RAM for the RAM copy. You may as well just use it out of Flash directly. Plus you’ll waste a bunch of CPU cycles doing the copying ;). We’re not using the script language but from what I understand the array does not get changed at run-time so it’s a good candidate for making rom const. Unfortunately that doesn’t help with Chris’ other problem of filling up the 32K of Flash.

Something that might be worth considering is using the EEPROM to store your autonomous programs to get them out of Flash - you’ll have to use the EEPROM code that someone posted on here last year though and it would generally be painful, but it would free up some space.

This is some really good stuff guys. Thanks for posting information and sharing your ideas. I’ll have to try this when I get back, I am out of town on business away from the team right, bad timing to have to leave on business for the “real” job on the last week of the build season…

Anyway, we have done pretty much what Dave has suggested:


if(thumbwheel == 0)
	{
    cmd_list = command_list_00;
	}
else if(thumbwheel == 11)
	{
    cmd_list = command_list_11;
	}
else if(thumbwheel == 21)
	{
    cmd_list = command_list_21;
	}
else if(thumbwheel == 31)
	{
    cmd_list = command_list_11;
	}
else
	{
    cmd_list = NULL;


Then our command list looks something like this…I won’t post them all, but you can see how the flow goes.


//do nothing but sit here and look pretty
struct commands command_list_00] = {
{CMD_WAIT,                  1000,        0,      0},
{NULL,                         0,        0,      0}

};

//ok robot starting on the left or right side MODE 11
struct commands command_list_11] = {
{CMD_DRIVE_UNTIL,         	  1400,        180,      0}, //drive time with PWM value
{CMD_SELECT_GREEN,       	     0,        0,      0}, //change color to green, no values needed.
{CMD_WAIT_UNTIL_VISLOCK_GREEN,	 0,        0,      0}, //lock on green, not values needed.
{CMD_WAIT,                 		50,        0,      0}, //YOU MUST DELAY HERE! (wait for in milli-seconds)
{CMD_DRIVE_ALIGN_COLOR,      	149,        5,      20}, //line up with tetra, PWM value and SCALER number here
{CMD_WAIT,               		50,        0,      0}, //wait in milli-seconds.
{CMD_DRIVE_UNTIL_CLOSE,         160,       200,      0}, //drive straight PWM value, then how close in second value is size bigger means closer.
{CMD_DRIVE_UNTIL,         	   600,        165,      0}, //drive time with PWM value
{CMD_SELECT_YELLOW,       	     0,        0,      0}, //change color to yellow, no values needed.
{CMD_WAIT_UNTIL_VISLOCK_YELLOW,	 0,        0,      0}, //lock on yellow, not values needed.
{CMD_WAIT,                 		50,        0,      0}, //YOU MUST DELAY HERE! (wait for in milli-seconds)
{CMD_DRIVE_ALIGN_COLOR,      	149,        5,      20}, //line up with tetra, PWM value and SCALER number here
{CMD_NO_VISION,           	    0,        0,      0}, //disable vision system no values needed
{NULL,                    	    0,        0,      0} //turn off auto mode no values needed

};