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

Multiplication in CCS - v.4.093

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



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

Multiplication in CCS - v.4.093
PostPosted: Mon Aug 23, 2010 12:10 pm     Reply with quote

Hi all,

I was wondering what is the more accurate way to do a multiplication using CCS...

I am using a PIC18F4550.
I have a DC motor with a tachometer that gives me 3 logical ticks per revolution.

Thus, using an interrupt, i take a count every second, and want to display revolutions:

RPM = (count/3)*60.


(i am using an INT16 for RPM & count, so do i need to cast the other numbers into INT16's?)

Is using this equation adequate enough?

Thanks as always.
collink



Joined: 08 Jan 2010
Posts: 137
Location: Michigan

View user's profile Send private message Visit poster's website

Re: Multiplication in CCS - v.4.093
PostPosted: Mon Aug 23, 2010 12:21 pm     Reply with quote

deperkin wrote:
Hi all,

I was wondering what is the more accurate way to do a multiplication using CCS...

I am using a PIC18F4550.
I have a DC motor with a tachometer that gives me 3 logical ticks per revolution.

Thus, using an interrupt, i take a count every second, and want to display revolutions:

RPM = (count/3)*60.


(i am using an INT16 for RPM & count, so do i need to cast the other numbers into INT16's?)

Is using this equation adequate enough?

Thanks as always.


Well, for one, why don't you simplify to just multiplying by 20 instead of the multiplication and division? Division takes much longer than multiplication.

Then, if you really, really need speed you could try to figure out a way to do it with shifts. 20 is a 16x and a 4x added together so you could do this:

Code:

RPM = (count << 4) + (count << 2);


I don't believe you could do it a whole lot more efficiently than that.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

shifts
PostPosted: Mon Aug 23, 2010 1:00 pm     Reply with quote

Thanks you,

that helps alot.

after my post I did change it to multiply by 20, but will try to shift instead, since I dont believe I am getting an accurate number displayed.

Thanks again.
collink



Joined: 08 Jan 2010
Posts: 137
Location: Michigan

View user's profile Send private message Visit poster's website

Re: shifts
PostPosted: Mon Aug 23, 2010 1:14 pm     Reply with quote

deperkin wrote:
Thanks you,

that helps alot.

after my post I did change it to multiply by 20, but will try to shift instead, since I dont believe I am getting an accurate number displayed.

Thanks again.


The two shifts + addition is basically the exact same as multiplying by 20 so if you didn't get an accurate number by multiplying by 20 then you still won't.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

interrupts
PostPosted: Mon Aug 23, 2010 1:33 pm     Reply with quote

I am forced to use an external interrupt because of the other pins being used.

I have:

INT_EXT2
void EXT2_isr(){
disable_interrupts(INT_EXT2); //disable interrupt
cnt++; //recieved input from tachometer
ds1307_get_time(hr,min,sec);
if (sec == (s + 1)){ //modify filter time every second
s = seconds;
enable_interrupts(INT_EXT2);
RPM =(cnt << 4)+(cnt << 2); //muliply by 20 to get RPM
cnt = 0;
}
}

in the above, the ds1307_get_time provides me with the hours, minutes, and seconds from an external RTC... i know that this part works, since I have been using it consistently in another interrupt. (in main I initially set s = seconds)
So I check on every interrupt if one second has gone by, and onces it has, I take my count and multiply by 20.

I should be getting about 2500 rpm, but only get 120 rpm.
I can see on an oscilloscope however that my tachometer is working properly... I must not be getting the interrupts correctly however.

Best regards,
collink



Joined: 08 Jan 2010
Posts: 137
Location: Michigan

View user's profile Send private message Visit poster's website

Re: interrupts
PostPosted: Mon Aug 23, 2010 1:49 pm     Reply with quote

deperkin wrote:
I am forced to use an external interrupt because of the other pins being used.

I have:

INT_EXT2
void EXT2_isr(){
disable_interrupts(INT_EXT2); //disable interrupt
cnt++; //recieved input from tachometer
ds1307_get_time(hr,min,sec);
if (sec == (s + 1)){ //modify filter time every second
s = seconds;
enable_interrupts(INT_EXT2);
RPM =(cnt << 4)+(cnt << 2); //muliply by 20 to get RPM
cnt = 0;
}
}

in the above, the ds1307_get_time provides me with the hours, minutes, and seconds from an external RTC... i know that this part works, since I have been using it consistently in another interrupt. (in main I initially set s = seconds)
So I check on every interrupt if one second has gone by, and onces it has, I take my count and multiply by 20.

I should be getting about 2500 rpm, but only get 120 rpm.
I can see on an oscilloscope however that my tachometer is working properly... I must not be getting the interrupts correctly however.

Best regards,


Under no circumstances should you be explicitly disabling and enabling interrupts in an interrupt handler. Comment out those lines. Or, better yet get rid of them and never speak of it again.

Also, if I were you I'd move the call to ds1307_get_time(hr,min,sec); out of the handler. Update some global variables for hr, min, sec.
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Mon Aug 23, 2010 3:29 pm     Reply with quote

Seriously, you have not got time to be reading the DS1307, inside the interrupt.
Forget this.
Use one of the PIC timers, to generate a 'tick'. Have this decrement a counter if the counter value is non zero (tick_counter)
Then set the value to the number of counts needed for one second (TICKS_PER_SECOND).
Your external interrupt code should be _short_ something like:

Code:

int1 counts_updated=FALSE;
int16 counts_received=0;

INT_EXT2
void EXT2_isr(){
   cnt++; //recieved input from tachometer
   if (tick_counter==0) {
      counts_updated=true;
      counts_received=cnt;
      cnt=0; //reset
      tick_counter=TICKS_PER_SECOND; //reset the counter
   }
}

//Then in your main

if (counts_updated) {
   counts_updated=false;
   RPM=counts_received*20;
}


Best Wishes
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

many thanks
PostPosted: Tue Aug 24, 2010 6:52 am     Reply with quote

Thank you!

This will be very helpful indeed.
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