Shop OBEX P1 Docs P2 Docs Learn Events
Scaling down and offsetting input values MX2125 — Parallax Forums

Scaling down and offsetting input values MX2125

In the Parallax book Smart Sensors & Applications Version 1.0 Pages 76, to 85, there is a extremely confusing explanation of scaling. Plus on page 77 where it says (0 to 1200), shouldn't that be (0 to 1250)? Also, where did the 254 come from in the line (0 to 254)? I kept thinking 256 minus one.
When I got to page 84, where it said "Your Turn-Developing the Program", I got stuck. I could not figure out where to put this line.
value = (value MIN 1875 MAX 3125) -1875 ** 13369 -100 Furthermore: I don't understand this line. I know that -1875 is subtracting the lower limit of the sensor MX2125. I know that * * means divide 13369 by 65536 which gives the ratio .20399. I also know that -100 is the lower limit of what is being scaled down to. But---I just don't see how the code works? Below is my code and it produces an error and will not run. Would someone please help me with the questions I ask, and help me make the code run? Thanks.

' {$STAMP BS2}
' {$PBASIC 2.5}
x VAR Word
y VAR Word
value VAR Word
value = (value MIN 1875 MAX 3125) -1875 ** 13369 -100
DEBUG CLS

DO

PULSIN 6, 1, X
PULSIN 7, 1, y

DEBUG HOME,DEC4 ? X, DEC4 ? y


PAUSE 100
LOOP

Comments

  • I've tried everything to get it to work, and nothing works. I'm lost.
  • kwinnkwinn Posts: 8,697
    edited 2016-08-20 05:52
    To scale an input value between 1875 and 3125 to a scale of -127 - +127

    Lets say the input value is 2500

    1) Apply offset to align the input scale to zero. (Subtract the lower value from the input value)

    value = value – 1875 so the input value is now 625 on a scale of 0 to 1250

    2) Apply the scale. (Multiply the value by the scale factor (13369 in this case) and return the upper 16 bits of the value) (Equivalent to 625 x 13369 / 65535)

    value = value ** 13369 so value is now 127 on a scale of 0 to 254

    3) Apply any additional offset that is needed for our output scale.

    Value = value – 127 so the value is now 0 on a scale of -127 to +127

    In Pbasic that can be done in a single statement.

    value = value -1875 ** 13369 -127


    For page 84 you do not need “value” so you can delete those two lines. You should be doing the calculations on the X and Y variables after the “pulsin” statements.

    X = (X MIN 1875 MAX 3125) -1875 ** 10486 -100
  • kwinnkwinn Posts: 8,697
    BTW, the correction factor is calculated as desired range x 65535/measured range, where the range is the maximum value - the minimum value.
  • kwinn, thank you for trying to help. Below is the new code I came up with. It seemed to work. I could get zero, or close to it while the other value was 100. If you went too far a value might jump to 500 or more. Still can't figure out how they arrived at the X=-100/100, Y=0/100, and X=0/100, Y=-100/100 in examples d. and c. on page 84 of the book? My display was always positive numbers, they have negative numbers X=-100/100?
    Also, I can't understand where you got the scale factor of 10486, I thought the scale factor would have been 13369.
    I tried the 13369 and it would not read 100 and zero like your 10486.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    x VAR Word
    y VAR Word

    DEBUG CLS

    DO
    PULSIN 6, 1, x
    PULSIN 7, 1, y
    x = (x MIN 1875 MAX 3125) - 1875 ** 10486 -100
    y = (Y MIN 1875 MAX 3125) - 1875 ** 10486 -100
    DEBUG HOME, DEC3 ? X, DEC3 ? y
    PAUSE 100
    LOOP
  • kwinnkwinn Posts: 8,697
    Below is the new code I came up with. It seemed to work. I could get zero, or close to it while the other value was 100. If you went too far a value might jump to 500 or more. Still can't figure out how they arrived at the X=-100/100, Y=0/100, and X=0/100, Y=-100/100 in examples d. and c. on page 84 of the book? My display was always positive numbers, they have negative numbers X=-100/100?
    The X and Y inputs for this exercise were the readings from a 2 axis accelerometer.
    If the X axis is vertical then X should read + 100 in one orientation and -100 when rotated 180 degrees. Y should read 0 (or close to it) in both cases.
    If the Y axis is vertical then Y should read + 100 in one orientation and -100 when rotated 180 degrees. The X should read 0 (or close to it) in both cases.
    Also, I can't understand where you got the scale factor of 10486, I thought the scale factor would have been 13369. I tried the 13369 and it would not read 100 and zero like your 10486.
    The scale factor and offsets are calculated using the input minimum and maximum numbers you get from the sensor and the minimum and maximum numbers you want as outputs.

    In this case the inputs are between 1875 and 3125, and the desired outputs are between -127 and +127.
    The input range is 3125 – 1875 which is equal to 1250.
    The output range is +127 - (-127) which equals 254
    The scale factor would be (254 / 1250) or 0.2032. Not 10486, but I will explain that later.
    The scale factor gives us a number between 0 and 254 for an input between 0 and 1250.
    Now we subtract 127 to end up with a number between -127 and +127.

    Now for the explanation. Most small micro’s do not have floating point hardware, and doing floating point calculations in software is time consuming and it takes up memory as well, so calculations are done with integers when possible. Stamp Basic has an integer instruction called Multiply High (**) that multiplies two 16 bit integers together to produce a 32 bit integer and returns the max 16 bits. That instruction is the equivalent of multiplying the two 16 bit integers together and dividing the result by 65535. The calculations for scale factor and output offset would be:

    input_range = input_max – input_min

    output_range = output_max – output_min

    scale_factor = (output_range x 65535) / input_range

    input_offset = input_min

    output_offset = output_min

    The calculation for each axis would be:

    axis_value = axis_input - input_offset ** scale_factor + output_offset

    Try a few values of this with a calculator or even better, on a spreadsheet.
    [/quote]

  • Kwinn, thank you so much for trying to help me. I can get the X=100 and Y=0 when rotated 180 degrees, but the debug screen does not post the negative 100. According to what you are saying, one of the 180 degree rotation should have a -100 on the debug screen. I have not seen a negative number on the debug screed from my code above.
    Next: I got the scale constant from this: 65536 x ( 255/1251-1 )=13369.
    1250/65536=.20399 1250 X .20399=254.9 or -127 to +127
    You got .2032 as the scale factor because you used 254 instead of 255, I added the 0.
    Now I am going to try and follow your explanation of the 10486
    input_range = input_max – input_min input_range = 3125-1875

    output_range = output_max – output_min output_max- output_min +127 -127

    scale_factor = (output_range x 65535) / input_range 255 x 65535/ 1250=13369

    input_offset = input_min -1875

    output_offset = output_min -127

    The calculation for each axis would be: ????????????????????????

    axis_value = axis_input - input_offset ** scale_factor + output_offset ?????????????

    Try a few values of this with a calculator or even better, on a spreadsheet.
    I still don't see where the 10486 scale constant comes from??????????
    Is this some kind of new math? I only know old math, maybe that is my problem.
  • Should I have used this in the code to get the negative 100 in the debug?
    x = (x MIN -1875 MAX 3125) - 1875 ** 10486 -100
    y = (Y MIN -1875 MAX 3125) - 1875 ** 10486 -100
    Notice the - in front of the 1875's now.
  • kwinnkwinn Posts: 8,697
    Should I have used this in the code to get the negative 100 in the debug?
    x = (x MIN -1875 MAX 3125) - 1875 ** 10486 -100
    y = (Y MIN -1875 MAX 3125) - 1875 ** 10486 -100
    Notice the - in front of the 1875's now.

    No, it should be:
    x = (x MIN 1875 MAX 3125) - 1875 ** 10486 -100
    The input from the input from the accelerometer goes from +1875 to 3125.
    The (x MIN 1875 MAX 3125) part limits x to a minimum of +1875 and a maximum of +3125.
    Subtracting +1875 from the input puts x into a 0 to 1250 range number. The offset is a fixed value, so you do not want to multiply it by the scale factor.
    When you then subtract 100 from x after multiplying by the scale factor it should give you a negative value if the input from the accelerometer was less than 2500.
  • OK--I figured out where you got the 10486 scale factor.
    You used 65536 x 200/1250=10485.7 rounded 10486
    Now to try and figure out the negative number issue.
    Say the accelerometer was x=2000.
    Then 2000-1875=125
    Then **10486=.160
    Then 125x.160=20
    Then 20-100=-80 Is this the correct approach?
    From my code of August 22, I don't get any negative numbers on the Debug screen. Should I be getting negative numbers? If so my code is wrong. I don't give up easily---Thank You Kwinn
  • kwinnkwinn Posts: 8,697
    Close.

    125 ** 10486 is equivalent to:
    (125 x 10486) / 65535 = 20. This is what the Multiply High (**) function does. It multiplies two 16 bit numbers to produce a 32 bit result and returns the high 16 bits of the result.

    Subtracting 100 from that result changes it from a 0 to 200 value to a -100 to + 100 value. If the value from the accelerometer is less than 2500 the output from the calculation x = (x MIN 1875 MAX 3125) - 1875 ** 10486 -100 should be negative. If it is not negative try dividing the calculation into separate steps and printing the result after each step.
  • kwinnkwinn Posts: 8,697
    So for printing the intermediate results the do loop would be:

    DO
    PULSIN 6, 1, x
    PULSIN 7, 1, y
    DEBUG HOME, DEC3 ? X, DEC3 ? y

    x = (x MIN 1875 MAX 3125)
    y = (Y MIN 1875 MAX 3125)
    DEBUG HOME, DEC3 ? X, DEC3 ? y

    x = x - 1875
    y = y - 1875
    DEBUG HOME, DEC3 ? X, DEC3 ? y

    x = x ** 10486
    y = x ** 10486
    DEBUG HOME, DEC3 ? X, DEC3 ? y

    x = x -100
    y = y -100
    DEBUG HOME, DEC3 ? X, DEC3 ? y
    PAUSE 100
    LOOP

    This should show you where the error is.
  • You say to print the results after each step. I don't know how to print the results after each step. When I run the program, the display just runs through the numbers in the "entire" program real fast. I tried putting a 5000 pause after each DEBUG and that did not work either. I don't have a clue as to how to make my code show negative numbers, when the accelerometer is below 2500. I am just working from the Parallax book, I don't have a teacher, and I am green at coding.
    I really like the accelerometer if I can only work through the book and understand how to use it. I have been wondering something--in the back corner of my brain. Everything in electronics boils down to only two things, Voltage and Current. To use this accelerometer it will eventually have to lead to altering Voltage or Current to be used. Thus far the readings the accelerometer is putting out on the DEBUG screen is just numbers, and right now those numbers are meaningless to me. Hopefully as I get further in the Parallax book, I hope these number relate to how Voltage or Current can be changed in a project. BUT first I must know how to scale. Thanks for your help Kwinn, I appreciate you trying to help me.
  • kwinnkwinn Posts: 8,697
    edited 2016-08-25 13:36
    Unfortunately I do not have a basic stamp to try code on, but try this do loop instead of the one in your DO LOOP. It should display the x and y values for each step for any entries you make.

    DO
    DEBUG “Enter a number from 1875 to 3125”
    DEBUGIN SNUM, x
    y = x
    DEBUG HOME, DEC3 ? x, DEC3 ? y

    x = (x MIN 1875 MAx 3125)
    y = (y MIN 1875 MAx 3125)
    DEBUG DEC3 ? x, DEC3 ? y

    x = x - 1875
    y = y - 1875
    DEBUG DEC3 ? x, DEC3 ? y

    x = x ** 10486
    y = x ** 10486
    DEBUG DEC3 ? x, DEC3 ? y

    x = x -100
    y = y -100
    DEBUG DEC3 ? x, DEC3 ? y
    LOOP

    Changed typo in fourth line (was y +x) to y = x.
  • Kwinn, sorry but this last code would not work. There was an error that popped up in the 3rd line down,
    DEBUGIN SNUM, x The comma was darkened in the error message, so I removed the comma, and the code ran. But the Debug screen showed "no" readings at all.
  • kwinnkwinn Posts: 8,697
    edited 2016-08-26 11:44
    Kwinn, sorry but this last code would not work. There was an error that popped up in the 3rd line down,
    DEBUGIN SNUM, x The comma was darkened in the error message, so I removed the comma, and the code ran. But the Debug screen showed "no" readings at all.

    The comma was a typo. Did you replace your DO loop with the one I posted and keep the rest of your code like this? Did you enter numbers in the debug terminal as shown on page 52 of the stamp manual?

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    x VAR Word
    y VAR Word

    DO
    DEBUG CLS
    DEBUG “Enter a number from 1875 to 3125”
    DEBUGIN SNUM x
    y = x
    DEBUG HOME, DEC3 ? x, DEC3 ? y

    x = (x MIN 1875 MAx 3125)
    y = (y MIN 1875 MAx 3125)
    DEBUG DEC3 ? x, DEC3 ? y

    x = x - 1875
    y = y - 1875
    DEBUG DEC3 ? x, DEC3 ? y

    x = x ** 10486
    y = x ** 10486
    DEBUG DEC3 ? x, DEC3 ? y

    x = x -100
    y = y -100
    DEBUG DEC3 ? x, DEC3 ? y
    LOOP
  • Kwinn, yes, my code was exactly like the one above. It does not run. I did not enter any numbers in the debug terminal as shown on page 52 of the stamp manual. Page 52 of the stamp manual is about "Defining Arrays". I have no idea of how to use the information on page 52, to make the code run both positive and negative numbers.
    I have continued on in Chapter 3, because it looks like I will never be able to write a code that gets negative numbers like the example on page 84 and 85. Oh well, at least I got the positive numbers.
    I have started to notice a trend in going through all of my old Parallax books. It is easy for a student like myself to get so involved in the "Debug Terminal Display" that one forgets how the information can be applied. What do I mean by that? Chapter 3 in this book is all about the part MX2125, a tilt sensor. As the book teaches, it becomes like a refresher course in high school trig. As you re-learn how to operate your scientific calculator, and write the code to view on the Debug terminal, the real world application of what is happening is easily lost in the shuffle. In other words, you can't see the forest for the trees. When I took that first micro controller class back in 2004, I don't think I would have ever really understood what was happening unless I had read both of Matt Gilliland's Application Cookbooks. Seeing how to use the micro controllers---beyond---the Debug screen really helped me. I am wondering when I complete Chapter 3 on the MX2125, if I will be able to apply it to a real world application beyond the Debug screen. Are there any other great application books like the ones Matt Gilliland wrote?
  • OK, Kwinn, I wrote a new and different code--on my own-- and it works. I appreciate you trying to help.
    Here is the code that works.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    x VAR Word
    y VAR Word

    DEBUG CLS

    DO
    PULSIN 6, 1, x
    PULSIN 7, 1, y

    x = (x MIN 1875 MAX 3125) - 1875 ** 10486 -100
    y = (Y MIN 1875 MAX 3125) - 1875 ** 10486 -100

    DEBUG HOME, CLREOL, SDEC ? x,
    CLREOL, SDEC ? y

    PAUSE 100
    LOOP
  • kwinnkwinn Posts: 8,697
    Don’t give up just yet. My Basic is pretty rusty, and I do not have a Basic Stamp to work with, but I know that it can be done. One problem is that in order to print negative numbers you must use SDEC rather than DEC. I have made the change in the code below. Try it and note the following.

    1 - Does “Enter a number from 1875 to 3125” show up in the debug window?
    2 – Can you enter 1875?
    3 – If you can enter 1875 what if any results are printed out.


    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    x VAR Word
    y VAR Word

    DO
    DEBUG CLS
    DEBUG “Enter a number from 1875 to 3125”
    DEBUGIN SNUM x
    y = x
    DEBUG HOME, DEC5 ? x, DEC5 ? y

    x = (x MIN 1875 MAx 3125)
    y = (y MIN 1875 MAx 3125)
    DEBUG DEC5 ? x, DEC5 ? y

    x = x - 1875
    y = y - 1875
    DEBUG DEC5 ? x, DEC5 ? y

    x = x ** 10486
    y = x ** 10486
    DEBUG DEC5 ? x, DEC5 ? y

    x = x -100
    y = y -100
    DEBUG SDEC5 ? x, SDEC5 ? y
    LOOP
  • Kwinn, I will run your last program tonight and let you know the results. Maybe you did not understand my previous post. Kwinn---I got it working with the code listed above. It runs the positive numbers and negative numbers just like it is supposed to do. Problem solved!
  • kwinnkwinn Posts: 8,697
    Kwinn, I will run your last program tonight and let you know the results. Maybe you did not understand my previous post. Kwinn---I got it working with the code listed above. It runs the positive numbers and negative numbers just like it is supposed to do. Problem solved!

    I didn't see your previous post last night. I must have started the reply before you posted it. I did have a few interruptions between starting and posting. Any way, your change is basically the same as mine, so no need to run it unless you want to see the intermediate results.

    All that head scratching because we were using DEBUG DEC instead of DEBUG SDEC to print the result.
  • Yes, problem solved. Again, thanks for your help Kwinn. I am deep into Chapter 3, with programs associated with the tilt sensor MX2125. Thus far everything involves signals being sent to the Basic Stamp, and numbers on a Debug screen. At this point I have "NO" idea what the numbers represent, other than numbers on a Debug screen. What do these numbers represent---Voltage? Current? Resistance? To be used, these numbers would have to leave the Basic Stamp. That is a "major" fault I find with the Parallax instruction books, they seem to never give an example of something like this leaving the Basic Stamp, and being used in the real world. Kwinn, can you, or someone else, give me an example of how these numbers from the MX2125 that are in the Basic Stamp can be used when they exit the Basic Stamp?
  • kwinnkwinn Posts: 8,697
    The MX2125 is a dual axis accelerometer, so the x and y outputs could be used for such things as a slope indicator, vehicle acceleration measurement, mechanism orientation, vibration measurement and other things.
  • msrobotsmsrobots Posts: 3,709
    edited 2016-08-30 00:46
    @Keith,

    since you are programming you should know that numbers can represent anything, depending what you want from them.

    Step a little back and think about it.

    it's not really about voltage, current or resistance.

    A simple tilt sensor for example usually works like simple switches, usually open and closed when tilted. A simple (old old) joystick has 4 switches so you can have center (no switch) and 8 detectable positions (up/down/left/right and the diagonals when two switches are closed)

    Any given of those 8 directions can be represented as a number between 0 and 15. (4 bit = 4 switches), but not all will be valid/possible. You can't go up and down in the same time, but up and left works (two switches).

    could go like this:

    0000 = 00 in center
    0001 = 01 moved left
    0010 = 02 moved down
    0100 = 04 moved right
    1000 = 08 moved up

    0011 = 03 moved left+down
    0110 = 06 moved down+right
    1001 = 09 moved up+left
    1100 = 12 moved up+right

    Those numbers now represent a direction for something.

    A newer joystick may use potentiometers for x and y axis and deliver you a analog resistance instead of a switch.

    So you do not just have up (like in on/off) but how far up from the center (say 0 to 10 kOhm resistance).

    Same goes for other sensors, say temperature or ultrasonic or infrared. They deliver you a value with a given range and you have to scale it to your needs in software.

    What you then do with them values is up to you.

    But the values represent something outside (Temperature/a direction/counts of some stuff on a conveyer/whatever you measure) and your software takes this as input.

    Then your program has to decide what to do with that input and create some output actions.

    You can already send output to the debug screen. Same works for serial LCD displays.

    Or you simple switch some pins on or off. Thermostat for example, measure temp and compare with max/min to decide if pin x is on or off to switch a heater on or off.

    Or run some servos/light strips/actuators/whatever your project needs to do with the input it got.

    outside it may be voltage/current/resistance/serial data/waveforms/... but inside they are just numbers.

    Enjoy!

    Mike

  • Thanks for your input msrobots. Having dealt with analog for so long, it is very difficult for me to think in terms of digital. Even more difficult thinking in terms of digital controlled by a micro controller. I only took one class back in 2004 on micro controllers, and the teacher knew nothing about micro controllers. Now, I am trying to learn on my own from Parallax books. A large part of the Parallax books deal with the Debug display. I would really like to read some books on things that happen once the information leaves the micro controller, and controls some external circuit. Displays on the debug scree are great, but to actually use the information, there has to be a circuit after the information leaves the micro controller.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    To be used, these numbers would have to leave the Basic Stamp. That is a "major" fault I find with the Parallax instruction books, they seem to never give an example of something like this leaving the Basic Stamp, and being used in the real world.

    Keith,

    The numbers don't mean anything without context. As kwinn and msrobots mentioned, there is a context to the information that is important here. For example, on the accelerometer, what is it being used for? Our examples explain how to connect to and communicate with the sensor. We also explain how it works and by creating the demo you can see the range of values you get back.

    But there is no flaw in not providing application specific examples since everyone's example is going to be different. There's no way to write a demo for every possible use of this sensor. Instead we give you all the information how how to communicate with it and get the information it provides and then it is up to you to decide what to do with that information.

    Do you want tilt angle, acceleration? How do you want it displayed? Are you looking for a specific range? These are questions only you can answer that are specific to your needs. Once you know that information you can use the information we have provided and a little programming experience to create your own unique application that does just what you want.

    You mentioned having dealt with analog for so long that I thought I might put things into analog perspective. If you look at Ohm's Law, you need two of the parameters to get the third. So if you're looking for current and you have voltage and resistance you can calculate that. It's not automatic. You still have to do the math. The same thing applies to our microcontrollers and sensors. We give you the core programming information and connection information and it is up to you to come up with the output. Okay, maybe not the best example, but it is what popped into my head at the moment.

    :nerd:
  • Thanks for your reply Chris. OK, because this post is getting too long, I am going to make a new post concerning exactly what I want to do with the accelerometer. The new post will be in the Basic Stamp Forum.
Sign In or Register to comment.