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

Scale, offset, percentage, is there a better way?

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



Joined: 13 Feb 2009
Posts: 71

View user's profile Send private message

Scale, offset, percentage, is there a better way?
PostPosted: Tue Feb 24, 2009 7:02 am     Reply with quote

Ok basically I want to calculate how far open a window is in percent. pot1avg is a 10-bit a/d read so can be anywhere from 0 - 1023. opened1 is the fully opened position, and closed1 is the fully closed position, both can be anywhere between 0 - 1023 also. Thanks to the forum, this following code works fine, but is quite slow and inefficient. Surely there is a better way to do it with out using float calculations? TIA, Ryan. Oh and BTW the percentage it output only needs to be an integer.

Code:

static signed int16 pot1avg; // eg pot1avg = 189
static int16 closed1, opened1; // eg closed1 = 104, opened1 = 376
void scale_offset_pots(void){
   if(closed1 < opened1){
      pot1avg -= closed1;
      pot1avg = (float)pot1avg / (opened1 - closed1) * 100;
   }
   else if(closed1 > opened1){
      pot1avg = 0 - (pot1avg - closed1);
      pot1avg = (float)pot1avg / (closed1 - opened2) * 100;
   }
   if(pot1avg > 100)
      pot1avg = 100;
   else if(pot1avg < 0)
      pot1avg = 0;
}
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Feb 24, 2009 7:27 am     Reply with quote

As a first remark, the case selection for different scale sign isn't necessary, I think. The first case should work for both.

If the 10 bit ADC range is utilized, you have to extend the intermediate result to int32. If the range would be always restricted to 9 bit, as in your example, the calculation can be handled with unsigned int16 (no negative scale supported in this case). Basically you have to change the order of calculation when using integer arithmetic.
Code:
pot1avg = (int32)pot1avg*100 / (opened1 - closed1);
Sydney



Joined: 13 Feb 2009
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 24, 2009 7:48 am     Reply with quote

Hi, I see what you mean about the case selection, but I think in the 1st case, if closed1 was greater than opened1 it would return a negative percentage, which would still need checking and negating?

I have previously tried the (int32) method, which also works, but is only marginally faster that the way in the OP, IIRC that function takes about 1ms@8mhz, perhaps thats as good as it gets?
Sydney



Joined: 13 Feb 2009
Posts: 71

View user's profile Send private message

PostPosted: Tue Feb 24, 2009 1:41 pm     Reply with quote

Ok after having a little play the int32 version takes ~640us, and the float takes ~768us, it isnt actually as slow or inefficient as I thought and I guess it isn't going to get much better with a 10-bit adc.

Judging by the math operation time in the help file, it would be more than 3x faster with a 9-bit adc reading, but half the resolution is quite a big tradeoff.

Thanks for the reply FvM it was very helpful, I will go for your code snippet in my application! Smile
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Feb 24, 2009 5:20 pm     Reply with quote

You won't get a negative percentage using the first case, cause divisor and dividend are both negative then.

If opened1 and closed1 are arbitrary 10 Bit values, then there's no way then using int32. Of course, a user specific number format (e.g. int24) could be used in assembly code, but I doubt, if the effort pays.
Sydney



Joined: 13 Feb 2009
Posts: 71

View user's profile Send private message

PostPosted: Wed Feb 25, 2009 1:20 pm     Reply with quote

FvM wrote:
You won't get a negative percentage using the first case, cause divisor and dividend are both negative then.


Ah yes of course it would. I now have:

Code:
pot1avg = (signed int32)(pot1avg - closed1) * 100 / (signed int16)(opened1 - closed1)


which is working well Smile thanks for your help!
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