Scaling down and offsetting input values MX2125
Keith Hilton
Posts: 150
in BASIC Stamp
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
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
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
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
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.
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]
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.
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.
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
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.
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.
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.
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.
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
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?
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
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
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.
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
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: