CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

How to make this code more fast?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
p_chusak



Joined: 24 Nov 2004
Posts: 3
Location: thailand

View user's profile Send private message AIM Address MSN Messenger

How to make this code more fast?
PostPosted: Wed Nov 24, 2004 1:13 am     Reply with quote

Hi i'am a new pic user;
I try to make servo control By Pic 18f4431
I have some problem

for this code

output_bit(PIN_B1,1);

compen_s=(kp_servo*new_error_pos/100)+ Kd_servo*diff_error_pos/100);

output_bit(PIN_B1,0);


all variable are 32bit signed

I use oscillloscope display output of PIN_B1
it show B1 high about 0.235ms or 235us i use 10Mz in H4 mode so
this process use 2350 Cycle (approximate) it use 35-40% cpu bandwidth
for one line code ( servo loop call every .5ms )

In datasheet of pic18f4431 i see hard ware multiply for fast mul
How i use it for this problem? or How to make this code line faster?


Thank.
Ttelmah
Guest







PostPosted: Wed Nov 24, 2004 3:56 am     Reply with quote

Division is the real 'killer' here. Do you need to use /100?. If you can change the scaling of your numbers, so you can use a _binary_ division (/128, or even better /256), then you can easily reduce the times by perhaps a factor of 3*. Division is the slowest arithmetic operation in general.
In general, servo algorithms in the PIC, use *256, as the 'factor', then you can declare a union somthing like:
Code:

/* This union is used internally to allow access to the various parts of each
32bit 'address' as bytes, 16bit integers etc. */
union lblock {
    unsigned int16 ui[2];
    signed int16 i[2];
    int8 b[4];
    signed int32 word;
};

//Trims an incoming 32bit value to a 24bit value.
signed int32 trim24(union lblock val) {
   if (val.b[3] & 0x80) {
   //Here -ve
        if ((val.b[3] != 0xFF) || !(val.b[1] & 0x80)) val.word=0xff800001l;
   }
   else {
   if ((val.b[3]) || (val.b[1] & 0x80)) val.word=0x7FFFFFl;
   }
   return(val.word);
}

//performs a division by 256 (using shift), and trims result to 24 bits.
signed int32 div256(union lblock val) {
   val.b[0]=val.b[1];
   val.b[1]=val.b[2];
   val.b[2]=val.b[3];
   return(trim24(val.word));
}

The main arithmetic, is then done on the values at 256* their 'target' sizes, and div256, used to give the final scale.
On the code as written (without bothering to do this), you could probably get about a 25% speed increase, by recoding as:

compen_s=(kp_servo*new_error_pos)+ (Kd_servo*diff_error_pos)/100;

This gives just one division, rather than the two seperate ones being used...
The hardware multiplier should already be being used by the compiler. Even then though, it is only an '8*8' multiplier, and requires several calls to complete a 32*32 multiplication, and handle the signs correctly.

Best Wishes
p_chusak



Joined: 24 Nov 2004
Posts: 3
Location: thailand

View user's profile Send private message AIM Address MSN Messenger

PostPosted: Wed Nov 24, 2004 7:53 pm     Reply with quote

Wow""ThanK:)......A lot>>.

now speed up >60% by shift>>8 and get 24bit signed"""
Guest








PostPosted: Thu Nov 25, 2004 12:37 am     Reply with quote

p_chusak wrote:
Wow""ThanK:)......A lot>>.

now speed up >60% by shift>>8 and get 24bit signed"""


18F452, 20 MHz, CCS 3.212, arithematics speed in usec

s_int32 * s_int32 45
float + float 36
float * float 28
float / float 227

floating point (24 bits) is faster than int32 !

I did not check how long does s_int32 / s_int32 takes,
anyway, divide always takes a long long time,
instead of using (int32)x / (int32)100,using (float)x * 0.01 might be faster ?
Guest








PostPosted: Thu Nov 25, 2004 12:53 am     Reply with quote

noticed that 1/100 ~ 1/128 + 1/512 + 1/4096

so, instead of using y = x/(int32)100, try this

int32 x, y, a;

y = (a=x>>7);
y+= (a>>=2);
y+= (a>>=3);

should be less than 7 usec at 40 MHz, I guess Cool
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group