Pages: [1] 2   Go Down
 Author Topic: Help mapping analog value from sensor  (Read 2917 times) 0 Members and 1 Guest are viewing this topic.
0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « on: February 13, 2010, 10:57:51 pm » Bigger Smaller Reset

I'm having trouble understanding how to get an analog value mapped to an actual value.

I'm testing with a MPX4250AP that I had from a previous project and this code below seems to work but it does not seem to work for
other sensors.

.00488 is 5/1024
.02246 is the range of the sensor divided by 1024 (230 kPa / 1024)
20 is the lowest kPa value

The data sheet says it has a range of 20 to 250 kPa.
http://www.freescale.com/files/sensors/doc/data_sheet/MPX4250A.pdf

I thought that I could use this code:

KPA = map(analogRead(13), 0, 1023, 20, 250);

But it seems to be off about 5% from actual values.

I can use:

And the voltage is exactly what the mpx4250ap is putting out.

Can someone shed some light on the most accurate way to
map the incoming value to the actual value?

 « Last Edit: February 13, 2010, 10:59:14 pm by avrguy » Logged

Left Coast, CA (USA)
Offline
Brattain Member
Karma: 361
Posts: 17262
Measurement changes behavior
 « Reply #1 on: February 14, 2010, 12:30:11 am » Bigger Smaller Reset

Looking at the graph in figure 4 of the linked datasheet I would suggest using mapping as:  KPA = map(analogRead(13), 0, 1023, 0, 260);

The fact that the sensor does not continue to give linear responses below 20 or above 250 kPa does not change the fact that the response curve is shown to be a 0-5vdc = 0-260 kPa linear relationship. Try it and see if you don't get more accurate results for valid pressure inputs between 20-250 Kpa.

Lefty

 « Last Edit: February 14, 2010, 12:31:25 am by retrolefty » Logged

Sweden
Offline
Jr. Member
Karma: 0
Posts: 74
Arduino rocks
 « Reply #2 on: February 14, 2010, 02:38:51 am » Bigger Smaller Reset

Its always nice to use engineering units as values.
About the first example, you are almost right in the formula.
Here is the calc, a little bit cleaned, from my lib FloatRamp:
Code:
Out =  OutMin + ( OutMax - OutMin ) * ( float(In) - InMin ) / (InMax - InMin)  ;
Note the conversion of the input to float, just to stay accurate. All other variables are floats.
 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #3 on: February 14, 2010, 01:00:34 pm » Bigger Smaller Reset

Quote
Looking at the graph in figure 4 of the linked datasheet I would suggest using mapping as:  KPA = map(analogRead(13), 0, 1023, 0, 260);

That looks to give a reading about 9% low. I was going by page 2 of the datasheet that said the min was 20 and max was 250. I understand what your saying about the graph though.

Quote
Out =  OutMin + ( OutMax - OutMin ) * ( float(In) - InMin ) / (InMax - InMin)  ;

I tried to work this out but I guess I'm not clear on what is In and what is Out? Is In 0-1023 and out 20 to 250?
 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #4 on: February 14, 2010, 01:08:13 pm » Bigger Smaller Reset

I tried this:

//Out =  OutMin + ( OutMax - OutMin ) * ( float(In) - InMin ) / (InMax - InMin)  ;

KPA =  20 + ( 250 - 20 ) * ( RAW - 0 ) / (1023 - 0)  ;

I left the zeros in just to make it easier to relate back to the formula given. The result seems to be about 5% high.
 Logged

Sweden
Offline
Jr. Member
Karma: 0
Posts: 74
Arduino rocks
 « Reply #5 on: February 14, 2010, 02:38:26 pm » Bigger Smaller Reset

What if you try this:
20kPa = 0.204V = 41.8 as InMin.
250kpa = 4.896V = 1002.7 as InMax.
About zeros, I dont have the knowledge of Arduino to tell if it matters. I just love them.
 Logged

0
Offline
Full Member
Karma: 0
Posts: 103
Arduino rocks
 « Reply #6 on: February 14, 2010, 07:40:17 pm » Bigger Smaller Reset

Note that the datasheet gives you the formula:
Quote
Nominal Transfer Value:  VOUT = VS (P × 0.004 - 0.04)

If Vs = 5v, and you use the default reference voltage (5v) on the analog inputs, the Vout/Vs = (P x 0.004 - 0.04).

The value you get from analogRead is equal to (Vout/Vs)*1023.  (Let's call this IN).

Now just do some algebra:
IN/1023 = P * 0.004 - 0.04;
P = (IN/1023 + 0.04)/0.004;

Cleaning this up a bit:
1/0.004 = 250;
250 * 0.04 = 10;

P = 250 * (IN/1023 + 0.04)
P = 250 * IN / 1023 + 10

Be sure in your code to force this to be floating-point math:
Code:
float P;
int IN;
P = 250 * IN / 1023[glow].0[/glow] + 10; // the .0 forces floating-point math instead of integer math.

BTW:
Quote
.00488 is 5/1024
This is a common mistake because indeed a 1-bit ADC has 1024 possible values.   But keep in mind:
0V = 0
5V = 1023, NOT 1024.
Granted the error is small enough that most people wouldn't notice but it is additional error in the calculations.
 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #7 on: February 14, 2010, 08:29:48 pm » Bigger Smaller Reset

Quote
What if you try this:
20kPa = 0.204V = 41.8 as InMin.
250kpa = 4.896V = 1002.7 as InMax.

It's about 19% off if I did it correctly.

Quote
P = 250 * IN / 1023.0 + 10; // the .0 forces floating-point math instead of integer math.

I think that's it Dilbert! Seems to be very close, less than 1% off
in my inital tests.  Simple to implement and understand too. I totally missed the formula in the datasheet.

I'll do more testing and report back.
 Logged

0
Offline
Full Member
Karma: 0
Posts: 103
Arduino rocks
 « Reply #8 on: February 14, 2010, 09:02:31 pm » Bigger Smaller Reset

I used the same technique with a MPX4115A.  It has a similar formula, but the constants don't come out to such nice numbers.
 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #9 on: February 14, 2010, 09:12:32 pm » Bigger Smaller Reset

I was just trying to work out the same thing for the MPX4115AP and the MPXV5004DP:

The formula for the:
MPXA5004DP  VS * (P * .2 - .2)
MPX4115AP is VS * (P * .009 - .095)

I'm having a problem with this, can you explain that part a little more:

Quote
Cleaning this up a bit:
1/0.004 = 250;
250 * 0.04 = 10;

I may have been looking at this for too long but I'm not seeing
the relationship 1/0.004 = 250;  :-?

Seems like for the MPXV5004DP it would be .784 but the pressure seems
to be off by that amount.

 « Last Edit: February 14, 2010, 09:14:33 pm by avrguy » Logged

0
Offline
Full Member
Karma: 0
Posts: 103
Arduino rocks
 « Reply #10 on: February 14, 2010, 09:47:21 pm » Bigger Smaller Reset

I was simplifying the constants a little bit.

P = (IN/1023 + 0.04)/0.004;

The divide by 0.004 is algebraically the same as multiplying by 1/0.004 which is 250.  Then the 250 can be distributed across the equation so that 250 * 0.04 becomes 10.   It's not necessary to do this.  The equation above will work just fine too, but in the CPU, it's easier and faster to multiply than to divide.

The MXP4115's constants don't come out so nice, but the technique works the same.

Code:
P = (IN/1023.0 + 0.095) / 0.009;  // Optionally simplify constants as desired.

MPXA5004DP... left as an exercise for the reader.
 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #11 on: February 14, 2010, 10:25:34 pm » Bigger Smaller Reset

Quote
P = (IN/1023 + 0.04)/0.004;

I don't think the formula works for the MPX5004AP,

Consider a reading of 1023 from the input pin:

P = (1023/1023 + .2) / .2;
P = 1.2 / .2;
P = 6; // Should be 3.92;

The formula below works but is different than your formula and I
don't understand the difference because it looks like
we should be subtracting .784 as yours does.

P = 3.92 * IN / 1023.0;
P = 3.92;

 Logged

0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
 « Reply #12 on: February 14, 2010, 10:30:43 pm » Bigger Smaller Reset

OK, I see now. The formula in the datasheet for the MPX5004 is slightly
different.

It should be P = (1023/1023 - .2) / .2;

And it works fine now. Thanks for the lesson!
 Logged

Sweden
Offline
Jr. Member
Karma: 0
Posts: 74
Arduino rocks
 « Reply #13 on: February 15, 2010, 02:16:47 am » Bigger Smaller Reset

I went a little bit concerned over your statement:
Quote
It's about 19% off if I did it correctly.
because I use that formula in my working life to. Am I wrong?
But after checking the specs and consulted mr Excel, Im back on track.
Actually, my formula is just like the other, its called "straight-line equation". Its just another way of config it.
But: If you needs precision, the Vs is critical. Especially at lower pressures.
My values was at TypVs, 5.1V. MinVs gives 16,4 kPa instead of 20 at TypVs. 18%.
My suggestion is to read Vs on another pin and compensate for the diff.
 « Last Edit: February 15, 2010, 02:18:51 am by srylul » Logged

0
Offline
Full Member
Karma: 0
Posts: 103
Arduino rocks
 « Reply #14 on: February 15, 2010, 03:05:24 am » Bigger Smaller Reset

That's probably what threw it off by such a high percentage.  If the device is being powered by the Arduino's voltage regulator, then it is running on 5V.

BTW: It should be noted that the formulas that I gave are assuming that the Vs to the sensor, and the Vref to the ADC are equal, as is the case when using the Arduino's voltage regulator and the default reference voltage.  As long as that is the case, it shouldn't be necessary to make any compensation for Vs.
 Logged

 Pages: [1] 2   Go Up