EduCAD and Arrays!!!!!

Ok, several things in this post:
-1. How many people would be interested in EduCAD?
-2. Those Dang Arrays!!!

1: I’m developing a Program I call “EduCAD”. No, It’s not an edubot design studio, but rather a program that allows you to draw out motion for autonomous movement, and generate the code for instant use. This program is going to be pretty cool to have your eduBot Write things with a marker.
Would you be interested in this program?
2: ARRAYSSSSSSSSS!!! Ack!
Ok, I’ve tried, and tried, and tried! But I just cant get a stinking array to work with MPLAB. What am I doing Wrong??? I’m using standard C syntax:

int X[2][3] = {
{3,2,1},
{3,2,1}
};

and so on. Bot the compiler doesn’t like my code. Is my array to large? It was an 82x3 array, then I split it into 2 41x3 arrays, but it still came up w/ the same problems on each one. What am I doing wrong?
I’m trying to find some sort of C18 programming guide, to see what form it likes arrays in. This also plays a role in EduCAD as well. In general, EduCAD will generate an array of Movement Data, and apply it to a general user_routines.c file for auto control. Nothing Fancy.
But I’m having trouble getting that silly array to work.
I also couldn’t get the switch command to work either.
What’s up???!

-EDIT-
Ok, I just got the Arrays working, sort of. You can’t have any variable names in the array, even if it is defined before the array. I can compensate for this in EduCAD, however, In my current program, I have all the data in and everything, but now I’m getting an ERROR - selection ‘i.user_routines.o’ cannot fit selection. What’s that mean? Am I using too much memory?
I have a const float [82][3] array. I’ll try shortening it. I thought we’d have plenty of memory to do this with. I don’t want to have to reprogram it out so it’s in program memory…again!
-EDIT-

floats… the only thing bigger is the infamous double float. A single float is 4 bytes. and you have an array of what… 82x3? so that means, unless i am way off, that this single array is using a total of 984 bytes. Kinda big, no? in my experience, it is easier to use an int or, depending on if negatives will be used, an unsigned int. Or if your values are msall enough use a char or unsigned char (1 byte each :smiley: ). Floats just have way more precision that you really need.

P.S. if i am gravely wrong, someone please tell me.

  1. Our programmer would be very interested in this. I believe WildStang developed something very similar to what you are talking about. But, I don’t think it is available for use abroad.

Would using Ints allow for Decimals?
I need something that can use decimals, and as far as my understanding was, int = integer? I thought a float was the lowest decimal-form variable (as far as space is concerned)
I think your memory prediction was correct, and, If I’m not mistaken, there is 1800 bytes of variable memory available. I wonder how much the IFI variables take by defualt? Maybe I am cutting it close.
I JUST learned C, this is my first time actually proggin’ it, so cut me some slack. I’m coming from a 10-year BASIC background.
Oh, and somehow magically, my Windows 98, non-se decided to start compiling now…
So now I don’t have to use 2 computers at once just to compile and upload a project!

I don’t think that array should be taking up ALL of your RAM…you have 1800 bytes. I’m not entirely sure how much RAM the other processes take up, but I think that 1800 bytes is solely program RAM so you shouldn’t be running into RAM issues…

Float is the only variable that allows for decimals, but I’m not sure why you’d need decimals if you’re doing auton code. There’s no way you can get it THAT precise because alot of factors like battery life and objects on the floor will affect the movement of the robot. You might be able to calculate it down to 13.3432423432432432434 feet to get to the ramp, but really the robot may not get there in that amount or it might go too far with that. Alot of assumptions have to be made when making this program and I’m not sure if a float would allow you anymore control than an int or unsigned int.

Sachiel,

A few things:

  1. Beware of “automatic initialization” in embedded code. It almost never works. Unlike a PC, where the entire program (both code and data segments) are loaded by the operating system into RAM, an embedded controller loads into ROM… RAM is (at best) all zeros or (at worst) random noise when you boot.

If you need a table, load it into ROM and always EXPLICITLY initialize any variables.

  1. Using Float or Double is pure “death by libraries” in an application like this. You have no floating point co-processor in this baby. More specifically, the PIC is a RISC processor (reduced instruction set). It does integer multiplication lightning fast (1 machine cycle) but that’s it.

Any floating point reference invokes a software library routine which can be hundreds of instructions long.

Note that even a division operation in not supported by the machine code!

  1. Plan what you want to do before you do it. What is the required update rate? What is your time “budget” for instructions within the loop?

Some professional help could not hurt… There are a million ways to get lost… Embedded programming is an art which take years to master.

KISS!

Good luck.

I know first had the the initialization of variables on the EDU controller is not reliable. EXPLICITLY INITIALIZE YOUR VARIABLES – this can really bite you.

As to Math libraries, has anyone found a good interger based math.h for sqrt, cos, sin, tan, and atan (among others)?

If so, do tell.

Joe J.

*Originally posted by sanddrag *
**I believe WildStang developed something very similar to what you are talking about. But, I don’t think it is available for use abroad. **

That’s correct. WildDraw was a VB.NET program that was used to create waypoints. The waypoints were then placed (copy/paste) into our robot code. The drivers would use a selector switch (allowing for 8 waypoint sets) to choose the desired path of the robot. The waypoint grid was based on the geometry of our robot and the field.

Sachiel - What sort of program would this end up being? Time based? How are you going to take into consideration the dynamics of a robot? Momentum, wheel slippage, and field obstacles are some challenges to consider. You can tell a robot to drive forward for 2 seconds and back for 2, but the forward momentum at the end of the first 2 seconds would cause your end position to be further forward than the start.

Thank’s for the response guys.
Let me tell you the application here.
The 82x3 matrix was a table of data for movement, specifically to write our team name, RAPTAR.
It was planned out extremely in-depth.
The main loop only contains this code:

void Process_Data_From_Master_uP(void)
{
Getdata(&rxdata);

pwm01 = pwm02 = 127;
pwm03 = pwm04 = 127;

if (F_Count < MAX_FUNC)
{
counter ++;

if (counter > Func[F_Count][2]*58)
{
counter =0;
F_Count ++;
}

if (F_Count == MAX_FUNC)
{
F_Count = 0;
}
pwm03 = Func[F_Count][0];
pwm04 = Func[F_Count][1];

}
Putdata(&txdata);
}

Simple, No?
F_Count is the Function counter. It keeps track of what current function we’re on.
counter is a loop counter. Since the User_Routines.C loops every 17ms, It loops roughly 58 times/sec. This is where the Decimal Precision comes in. Func[82][3] is an array that holds movement data. As you can see from the code, Func[x][0] and Func[x][1] are the left/right pwm values. Func[x][2] is the Time Value. This is the number (in seconds) of time for the function to be carried out.
The decimals come in here: 90 degree rotation.
To get the time each wheel must travel for complete 90 degree rotation you simply do this:

((2pi(WD /2))/4)/(WC*(170/60))

Where WD is the distance in inches between the wheels, and WC is the circumference of a wheel. This is not done in code, I got the values ahead of time and hard coded them into the Func array.
The particular 90 deg. Rotation variable for our bot is this:
0.4085043078971248173852353625317 seconds

Now, I know there still isn’t going to be that much precision, but trust me, there is a BIG difference between passing our decimal time than passing a 1 time for rotation.
One way to get around all this might be to measure cycle-by-cycle. Where Func[x][2] = Time in Cycles. But this would require some additional math. Not much, I suppose. That was my idea from the last post, and I’m just getting started on it.
That would turn our nasty decimal rotation time into about
240 cycles.
That would allow for an integer array.

I am led to believe that the size of the array might have been the
cause. I tested the code with smaller arrays, and it worked fine.
However, parts were re-written, so I’m still not 100% sure.

Anyway, I’ve got this method working up to an extent now. I’ll continue to post here as EduCAD develops.


if (F_Count < MAX_FUNC)
{
    counter ++;

    if (counter > Func[F_Count][2]*58)
    {
        counter =0;
        F_Count ++;
    }

    if (F_Count == MAX_FUNC) 
    {
        F_Count = 0;
    }
    pwm03 = Func[F_Count][0];
    pwm04 = Func[F_Count][1];

}

Notice that in the above code, the outer conditional tests to see if F_Count < MAX_FUNC. Assume F_Count is one less, and that the counter has elapsed. Okay, so the F_Count++ line gets executed, and F_Count == MAX_FUNC, so the second inner conditional is true, and sets F_Count to 0. Then pwm0[34] are set with the new F_Count value, which is 0. This means that the last function values never get used. You might try puting the second inner conditional AFTER the pwm assign statements.

And to get finer granularity using decimal values, just change the ‘58’ in Func[F_Count][2]*58, to something smaller. It won’t be very precise, and you’ll have to find out the Func[F_Count][2] numbers empiracally, but it should be able to emulate the behaivor with using floats currently pretty well I’d imagine.

Actually this isn’t true.
C starts arrays with 0.

For example, an array of x[3] has values x[0], x[1], and x[2]. If you tried to ask for an x[3], the program would generate an error. This is why the MAX_FUNC is layed out in that way.
Actually, I have gotten some really good results removing the *58, and simply multiplying the timer values so that they are the number of cycles. This also allows me to use an integer array, so I can save alot of wasted memory space.
So far, everything works well.

As to Math libraries, has anyone found a good integer based math.h for sqrt, cos, sin, tan, and atan (among others)?

Dr. J,

Although I am sure one exists, I usually roll my own using a Taylor Series expansion as a basis. It allows me to exactly control the precision and error I can tolerate for my application. I also know exactly how many machine operations I am executing.

A moderately good paper can be found here:
http://www.agere.com/enterprise_metro_access/docs/AP02044.pdf

The paper cited above is targeted for a different processor but the math is sound.

Of course, the exact implementation for the PIC is left as an “exercise for the student”. :wink:

Actually this isn’t true.
C starts arrays with 0.

For example, an array of x[3] has values x[0], x[1], and x[2]. If you tried to ask for an x[3], the program would generate an error. This is why the MAX_FUNC is layed out in that way.

Sorry. I figured MAX_FUNC would be the last (maximum) indexable array value. Apparently not …

From Betts:

Dr. J,

Although I am sure one exists, I usually roll my own using a Taylor Series expansion as a basis. It allows me to exactly control the precision and error I can tolerate for my application. I also know exactly how many machine operations I am executing.

Assuming Autonomous Mode stays and/or gets harder in 2003, The ability to do trig fast and efficiently is going to be an important topic.

I don’t see any reason why we should all roll our own.

I think we should start a new thread on just this topic. I have done a bit of digging and found a possible candidate. I will keep you posted

As an example of the kind of things we should think about is that we can save code space by only writing a cosine function and using trig identities (e.g. sin(theta) = cos(pi/2-theta) to calculate the other functions.

Also, the series will converge faster if you expand about a point closer to the point of interest. It may be faster for a given amount of desired error to use a series of expansions based on the value of theta rather than a single expansion about zero.

For example:

use an expansion about 0 for values -pi/8 <= theta < pi/8
and
use an expansion around pi/4 for values pi/8 <= theta < 3pi/8
and
use trig identities to get all other values of theta to map to this range

Again, while this is a good exercise for the student, I see no reason for us all to roll our own code for these very useful functions.

There is going to be a lot for us all to learn…

Joe J.

Dr. J.,

I agree… It’s going to get interesting this year…

Another possibility is to externally generate and then load a lookup table in ROM… This would certainly be much faster…