0
Offline
Newbie
Karma: 0
Posts: 38
Arduino rocks
|
 |
« on: February 13, 2010, 10:57:51 pm » |
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. KPA = (analogRead(13)*(.00488) / (.02246)+20); .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.pdfI 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: VIN = .00488 * analogRead(13); 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: 279
Posts: 15316
Measurement changes behavior
|
 |
« Reply #1 on: February 14, 2010, 12:30:11 am » |
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 » |
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: 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 » |
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. 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 » |
I tried this:
//Out = OutMin + ( OutMax - OutMin ) * ( float(In) - InMin ) / (InMax - InMin) ;
float RAW = analogRead(); 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 » |
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 » |
Note that the datasheet gives you the formula: 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: float P; int IN; IN = analogRead(pin); P = 250 * IN / 1023[glow].0[/glow] + 10; // the .0 forces floating-point math instead of integer math.
BTW: .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 » |
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. IN = analogRead(pin); 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 » |
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 » |
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: 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 » |
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. 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 » |
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 » |
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 » |
I went a little bit concerned over your statement: 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 » |
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
|
|
|
|
|
|