How do I rescale an input value-> lower output & avoiding floating point?


Closed Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Mar 2009
    Posts
    653

    Default How do I rescale an input value-> lower output & avoiding floating point?

    Ok, so I have an 8 bit AD input 0-255, that I wish to rescale to a PWM output of say 0-150 (don't ask!), now in the real world I'd just divide 150 by 255, (0.0392156862745098) & then apply that to all my incoming input values....but that'd obviously involve floating point.

    What's the best way to approach such rescaling in Picbasic, cos I've thoroughly checked my head, and there's nothing listed in there?

  2. #2
    Join Date
    Sep 2009
    Posts
    755


    Did you find this post helpful? Yes | No

    Default Re: How do I rescale an input value-> lower output & avoiding floating point?

    PWMVar var byte
    ADRes var byte
    PWMVar=(ADRes*150)/255

  3. #3
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: How do I rescale an input value-> lower output & avoiding floating point?

    Excellent...I realise this was more a maths question (which you can all now tell I suck at) rather than a PICBAsic one....but that's exactly what I needed, & I shall use it gratuitously :-)

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default Re: How do I rescale an input value-> lower output & avoiding floating point?

    Hi,
    Don't forget the */ operator.

    Basically */ is like multiplying by 1/256 parts. So x = y */ 256 is the same as x = y * 1 and x = y */ 128 is the same as x = y * 0.5.

    So why is it "better" than manually multiplying and dividing?

    Because the */ operator doesn't actually divide anything (division is slow in software). It multiplies the two values giving a 32bit intermediate result. It then takes the middle 16 bits of that intermediate value and returns those bits as the result. Lets say ADresult = 255
    Code:
    PWM = ADResult */ 150
    It multiplies ADresult by 150 resulting in the intermediate value of 38250 which in binary form looks like:
    Code:
    00000000 00000000 10010101 01101010
    It then "extracts" the middle 16 bits of this value and returns those as the result. What's 00000000 10010101 in decimal? Yep, it's 150... or 149 actually.

    Lets say you want to do x = 12345 * 1.45. 1.45*256=371 so
    Code:
    x = 12345 */ 371
    Behind the scenes you'd first get 12345*371=457814 which, expressed in binary, is:
    Code:
    00000000 01000101 11100010 10011011
    Those 16 middle bits ( 010000101 11100010 ) in decimal form is 17890 which is pretty close to 12345*1.45.

    It's not perfect but there's usually a way to make it "fit" pretty good - and it avoids using division which, again, is a pretty slow operation on these devices.

    Then we have the ** operator which is the same thing but it performs an inherent division of 65536 instead (ie. it returns the top 16 bits of that 32 bit intermediate result).

    /Henrik.

  5. #5
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: How do I rescale an input value-> lower output & avoiding floating point?

    Wow.....Henrik, that was a stonking reply....it's now in my test program & works a treat (as did pedja089's formula, but I like the fact that */ is that little bit quicker).

    Many thanks for taking the time to explain....great stuff

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts