View previous topic :: View next topic |
Author |
Message |
falleaf
Joined: 23 May 2004 Posts: 48
|
calculation in CCS C |
Posted: Thu Jun 24, 2004 3:47 pm |
|
|
I would like to compute this formular in 16F876:
Code: | delta = (pos_motion*acceleration/velo_motion)*(pos_motion*acceleration/velo_motion) - 4*pos_motion*acceleration; |
pos_motion, velo_motion are SIGNED LONG numbers, and acceleration is defined as 5.
delta is forced as float number, and I gave constants to pos_motion and velo_motion to printf to pC for testing. However, I get wrong results.
pos_motion = 10000;
velo_motion = 50;
the result should be 800,000; but I cannot get it.
May someone explain me about this? How the C code compute in this case? will it be overflow as computing? |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Thu Jun 24, 2004 4:00 pm |
|
|
You're probably getting hit by the priorities that these calculations are using. Try:
delta = (((pos_motion*acceleration)/velo_motion)*((pos_motion*acceleration)/velo_motion)) - (4*pos_motion)*acceleration;
Note where the parenthesis are located. |
|
|
falleaf
Joined: 23 May 2004 Posts: 48
|
|
Posted: Thu Jun 24, 2004 4:19 pm |
|
|
Thanks rnielsen, I'll try.
by the way,
what will happen if I force the format number as:
beta = (signed long) delta;???
will it save the high bytes of result as normal, or what will it do? |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
|
Posted: Thu Jun 24, 2004 5:14 pm |
|
|
Technically what you are attempting to do should work but it's a good practice to spread the computation over several lines. Use signed math only where you have to. You might as well declare and use some intermediate variables. If you don't you the compiler will it has to. |
|
|
falleaf
Joined: 23 May 2004 Posts: 48
|
|
Posted: Thu Jun 24, 2004 5:35 pm |
|
|
I have to compute in signed format number because it's the motion control, and it may take negative values.
as using asm, to express a negative number, I take out a bit of direction, and compute with positive ones. But if do this with C, i'm afraid that it will generate longer codes, and no need to do so.
Code: | velocity_temp = (((pos_motion*acceleration)/velo_motion) - sqrt(delta))/2; |
in this case, delta should be float, and velocity_temp should be float. I would like to get LONG format, and give it
velocity = (signed long) velocity_temp; |
|
|
falleaf
Joined: 23 May 2004 Posts: 48
|
|
Posted: Fri Jun 25, 2004 1:26 am |
|
|
with pos_motion = 10000, velo_motion = 50; I got this
Code: | delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000 |
I use hyperterminal to get these results. I'm confused :(( |
|
|
Ttelmah Guest
|
|
Posted: Fri Jun 25, 2004 2:31 am |
|
|
falleaf wrote: | with pos_motion = 10000, velo_motion = 50; I got this
Code: | delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000delta = 2.875000
delta = 2.875000delta = 2.875000delta = 2.875000 |
I use hyperterminal to get these results. I'm confused :(( |
Remember that a 'signed long', only has a range of +32767 to -32768.
The very first part of the maths:
(pos_motion*acceleration/velo_motion)
starts by taking 10000*5 = 50000 -> allready overflowed.....
As others have said, _split_ the maths, and consider working only with unsigned values. If the motion is -ve, test for this before starting, and set a flag to say that this is true. Then you can perform this part of the arithmetic, with something like:
Code: |
if (pos_motion<0) {
pos_motion=-pos_motion;
neg=true;
}
else neg=false;
temp=(int16)pos_motion*acceleration/velo_motion;
if (neg) temp=-temp;
|
Now in this case, I am assuming that only 'pos_motion' can be -ve, and the other values are allready declared as 'int16', with 'temp' declared as 'signed long'. Then the arithmetic is performed using unsigned maths, and the sign bit put back after the calculation has finished.
If you split the arithmetic up like this, you can work through the sections, and print the resuls to find which parts are causing problems.
Best Wishes |
|
|
falleaf
Joined: 23 May 2004 Posts: 48
|
|
Posted: Fri Jun 25, 2004 3:51 am |
|
|
Oh, I tested with the program, and this is my code:
Code: |
float velocity_temp=0;
float delta=0;
signed long delta1=0;
float delta2=0;
if (velo_motion < 0)
{
velo_motion = - velo_motion; // gan gia tri duong vao de tinh toan
pwm_direction = 0; // cho quay theo chieu nguoc
}
else
{
pwm_direction = 1; // quay theo chieu thuan
}
printf("pos_motion = %ld", pos_motion);
printf("acceleration = %u", acceleration);
delta1 = (pos_motion* acceleration);
delta2 = (float)delta1;
delta2 = delta2/5;
printf("delta2 = %f", delta2);
delta = delta1*delta1 - delta2;
printf("delta = %f",delta); |
I change pos_motion = 1000;
and acceleration = 2
velo_motion = 30;
delta1 is right, and the result is 2000;
delta2 at the upper line is right, and it results 1999.9999991 (but not good)
but as I compute with division operator, it gets wrong values, and returns all stuff.. blah.. blah... cannot read.
I think this is the problem inside the compiler???
I'm using version 3.094 :( |
|
|
falleaf
Joined: 23 May 2004 Posts: 48
|
|
Posted: Fri Jun 25, 2004 6:28 am |
|
|
I found the problem. We cannot do it with local variables, as I put it out as global variables, the program worked very good.
Thanks for all. |
|
|
|