Scaling ADC values


Closed Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Feb 2006
    Posts
    10

    Default Scaling ADC values

    Hello all,

    I am trying to build a midi controller that incorporates an accellerometer. I have one of the 2 axis accelerometers from Dimension Engineering. The behavior that I would like is for the midi output to follow the tilt of the accelerometer on each axis from -90 degrees to +90 degrees. In other words, if the accelerometer were in its neutral position, the midi controllers associated with each axis would spit out a value of 64. If tilted to a full 90 degrees in a given direction the midi output for that axis would spit out either 0 or 127. Make sense?

    Ok, the problem is that when tilted 90 degrees from neutral, the accelerometer does not reach its limit (0v or 5v). The values I get from the ADC at 90 degrees from neutral are about 45 to 85. Here is a snippet of the code where I get and process the adc value.


    ADCIN 1,modval ' Read channel 1 to modval
    modval = modval/2

    The divide by 2 is just the simplest way I could think of to get the result from 8 bit to 7 bit (for MIDI) that I could think of. I am sure there is an easier way.

    So, my question is, what is the best way to go about scaling an adc result of between 45 and 85 to the desired results of 0 to 127.

    thanks in advance for the help!
    Brad

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    First off, don't forget, PBP only deals in integers, so if your input range is less than your target output range, you'll lose a bit in the translation.
    So, here's a quicky thing I can think of to get you what you want...(in pseudo-code)

    adcinput var word : minimumvalue var word : maximumvalue var word
    range var word : scalefactor var word : newadcinput var word

    Loop:
    Get adcinput 'get the numbers from the A/D pin

    if adcinput < minimumvalue then 'check for a new minimum value
    minimumvalue = adcinput 'if it's less than the old one, replace it
    endif

    if adcinput > maximumvalue then 'check for a new maximum value
    maximumvalue = adcinput 'if it's greater than the old one, replace it
    endif

    range = maximumvalue - minimumvalue 'get the total range of the input so far

    scalefactor = 65536 / range 'get the scale factor for multiplying the number

    newadcinput = adcinput * scalefactor 'up to a full 16 bit number to help avoid losing any more precision than we have to

    newadcinput = newadcinput >> 9 'shift that big number back down to a 7 bit number

    goto loop



    Of course this could probably all be shortened up into one decent line of code, but you should get the picture.
    Since we're working with integers, if you just took the range of the input and multiplied it to get a number range close to 0-127, you'd lose way too much precision. By taking and multiplying it up to a 16 bit number and dividing it down by a constant, you might save a bit of that precision. If we had floating point, we'd be ok, but we don't...

  3. #3
    Join Date
    Feb 2006
    Posts
    10


    Did you find this post helpful? Yes | No

    Default

    Thanks for the help Skimask, it helped a lot. I used your method with a couple of modifications and it seems to work very well.

    First, I added to your method was to define minimums and maximums. I was having problems bumps/shakes of the accelerometer making the min and max values go well outside of the range which I wanted to capture (which is neutral to 90 degrees on either axis). The MIN and MAX statements solved that.

    I also added a line to subtract the minimum value from the capture adc value. This ensured that the final output was actually 0-127. Without it, my output would never go all the way down to 0.

    In the long run (as I am sure many of you will notice) I will probably just define range since I know what the adc values are at +90 and -90 degrees. I haven't done that yet, because I want to be sure that environmental variables don't affect the accelerometer output.

    Here is the routine that I ended up using....


    modcheck:
    ADCIN 1,modval ' Read channel 1 to modval
    modval=modval min 166
    modval=modval max 91
    if modval<minval then minval=modval
    if modval>maxval then maxval=modval
    range=maxval-minval
    modval=modval-minval
    scalefactor=65535/range
    modvalnew=modval*scalefactor
    modvalnew=modvalnew>>9

  4. #4
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    One thing I forgot to mention (but it seems you already took care of it in a way) is to initially set your minimum value very high (so the only place it can go is down) and your maximum value very low (so the only place it can go is up)...

  5. #5
    Join Date
    May 2007
    Posts
    65


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by skimask View Post
    One thing I forgot to mention (but it seems you already took care of it in a way) is to initially set your minimum value very high (so the only place it can go is down) and your maximum value very low (so the only place it can go is up)...
    yes, both near the center
    "Beethoven had his critics too, see if you can name 3 of them"

Similar Threads

  1. Stable Adc Reading Routine
    By gebillpap in forum General
    Replies: 27
    Last Post: - 13th May 2015, 02:18
  2. 16F877A problem: "coupled" digital values
    By Lupo83 in forum General
    Replies: 16
    Last Post: - 4th December 2007, 12:46
  3. Adc giving widely flactuating values
    By tamersoss in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 17th December 2006, 08:59
  4. ADC value with 2 decimals on an LCD
    By Squibcakes in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 2nd December 2005, 15:54
  5. 12F675 ADC 'Issues'
    By harrisondp in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 31st March 2005, 01:55

Members who have read this thread : 2

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