Trouble with 4-20mA math - Wika A-10 / 250ohm Resister

Hello,

I have an arduino Mega with a Wika A-10 0-200PSI sensor connected from 12v out (step-up) to ADC1 with a 250ohm resister from ADC1 to GND.

I am getting close numbers but the math is not correct. Is there something obvious I am missing?

With the unit all wired up I am showing ADC1 = 200 with ZERO PSI.

pressureMax = 1023
pressureZero = 200
pressuretransducermaxPSI = 200
pressureValue1 = ((pressureValueA1 - pressureZero) * pressuretransducermaxPSI) / (pressureMax - pressureZero);

Serial Input Reading 1 - External PSI gauge is reading 100PSI
const int pressureMax = 1023
PSI = 95.99
ADC1 = 595.00

Serial Input Reading 2 - External PSI gauge is reading 20PSI
PSI = 18.47
ADC1 = 276.00

PressureMax is not correct, that is simply the highest value that the ADC can report.

I suggest to use two-point calibration, with (say) 20 PSI and 100 PSI as the calibration points.

The 1023 value suggests that your setup is exceeding the allowable input voltage on the ADC pin, which can fry the input circuitry. It is a good idea to put a 10K resistor in series with the ADC input, to protect it from voltages greater that AREF (usually Arduino Vcc).

Okay, thank you for the response.

Do you have any suggestions of how I can calibrate it with 2 points?

Fit a line to the two points, which is what the Arduino map function does.

Good tutorial on calibration.

Okay thank you, I will see if my brain can figure it out.

Here were the main values I could figure out, note that I am looking at an analog gauge so its not 100% accurate.

158 PSI
PSI1 = 159.90
ADC1 = 858.00

141 PSI it reads
PSI1 = 142.65
ADC1 = 787.00

130 PSI it reads
PSI1 = 131.96
ADC1 = 743.00

100 PSI it reads
PSI = 95.99
ADC1 = 595.00

60 PSI
PSI1 = 58.32
ADC1 = 440.00

50 PSI
PSI1 = 48.12
ADC1 = 398.00

40 PSI
PSI1 = 40.10
ADC1 = 365.00

30 PSI
PSI1 = 26.00
ADC1 = 307.00

20 PSI
PSI1 = 16.52
ADC1 = 268.00

Four point calibration (X is the ADC value):

1 Like

Hi JRemington,

I know you're showing me the keys but I don't understand what it means.

Sorry, I am not great at math.

Why have you not posted your code, using code tags?

Writing a program for this sort of application requires that you understand grade school math.

1 Like

Hi,

Sorry I didn't know you wanted the code, please see below.

// PRESSURE SENSOR SETUP
float pressureValue = 0; //variable to store the value coming from the pressure transducer ADC0
float pressureValueA = 0; //variable to store the value coming from the pressure transducer ADC0
const int pressureZero = 200; //analog reading of pressure transducer at 0psi
const int pressureMax = 1023; //analog reading of pressure transducer at 100psi
const int pressuretransducermaxPSI = 200; //psi value of transducer being used
  
void setup() {
  Serial.begin(9600);
}

void loop() {
  delay(20000);  // delay in between reads for stability

  pressureValueA1 = analogRead(A1); //reads value from input pin and assigns to the variable
  pressureValue1 = ((pressureValueA1 - pressureZero) * pressuretransducermaxPSI) / (pressureMax - pressureZero); //conversion equation to convert analog reading to psi
  
  Serial.println("----");

  Serial.print("PSI1 = ");
  Serial.println(pressureValue1);

  Serial.print("ADC1 = ");
  Serial.println(pressureValueA1);
}

Nothing to do with me. Posting code is a forum requirement and a basic courtesy. See the "How to get the best out of this forum" post.

1 Like

What jremington is suggesting is your input is saturating at 1023 since this is the highest analog conversion value.

Typically, 4 - 20mA inputs will read from 0 - 22mA. This leaves a small buffer to allow a reading under range and over range. Since you are converting the 4 - 20mA to 1 - 5V, the Mega input cannot read more than 5V.

Theoretically, your setup should work but it appears you have some inaccuracy at the max end. Your math is fine. Are you able to apply 200PSI? Are you able to adjust to known values?

I would verify the documentation on the pressure transducer to make sure what the max (or 20mA, or 5V) value should be. Next, I would see if the sensor has some adjustment for output to correct your inaccuracy.

To calibrate would simply be changing the max pressure (Scaled) value, or the min if you find the inaccuracy at the lower end. To be clear:

RawMin = 200
RawMax = 1023
ScaledMin = 0 PSI
ScaledMax = 200 PSI

I would also verify the pressure transducer's min output. I rarely see transducers that read to zero. Typically a 200 PSI transducer will start reading around 10 - 15 PSI.

Post the sensor's exact, complete part number.

https://www.wika.com/media/Data-sheets/Pressure/Pressure-sensors/ds_pe8160_en_co.pdf

Also note that if you change your scaled min to anything other than zero, your formula will not work any more since it is not factoring in any offset. You could use the map() function.

map() - Arduino Reference

From the very nice linear fit(*) plot in post #6, the expression

  pressureValueA1 = analogRead(A1);
  float psi = 0.23695*pressureValueA1 - 44.26;

should report accurate psi values based on the ADC readings.

(*) to four points taken from the data in post #5

This is very cool! The only issue is that at 0psi it is showing 200 so by your math it is ~4psi.

Is it possible to do the same math but I can subtract -200 from the number first?

Like

  float psi = (?*(pressureValueA1 - 200)) - ?;

20PSI - 68
50PSI - 198
100PSI - 295
130PSI - 543

I am using the WIKA A-10 50398083.

JR if you send me your Paypal or Venmo I am happy to send you some cash for your help.

You can but then your values would be off again. You should study and understand the plot he posted. His formula adjusted the 'straight line' in your formula to match what you already have.

If you want to fix what you already have then you should verify:

4mA = 1V = 0 PSI and
20mA = 5V = 200 PSI.

Then no adjustment would be necessary. Although, jrremington's solution is perfectly acceptable IMO.

1 Like

That won't help. As you say, the pressure sensor is not that accurate. The procedure I used gives the best linear fit over the range of the calibration points.

Here is a slightly better fit, using more data. Replace the two calibration constants (scale and offset) in the code with those from the equation in red on the graph.

pressure ADC
20 268
30 307
40 365
50 398
60 440
100 595
130 743
141 787
158 868
0 200
200 1023

If you look at the 0psi = 200 and 200psi = 1023 in R, you get a plot like

> df2 = read.table(text="pressure	ADC
+ 20	268
+ 30	307
+ 40	365
+ 50	398
+ 60	440
+ 100	595
+ 130	743
+ 141	787
+ 158	868
+ 0	200
+ 200	1023",header=TRUE)
> summary(lm(pressure ~ ADC,df2))

Call:
lm(formula = pressure ~ ADC, data = df2)

Residuals:
    Min      1Q  Median      3Q     Max 
-3.1041 -1.6113  0.3979  1.6128  3.6620 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -44.818796   1.582571  -28.32 4.15e-10 ***
ADC           0.237238   0.002619   90.59 1.23e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.269 on 9 degrees of freedom
Multiple R-squared:  0.9989,	Adjusted R-squared:  0.9988 
F-statistic:  8206 on 1 and 9 DF,  p-value: 1.234e-14

> ggplot(df2, aes(ADC,pressure))+geom_point() + geom_smooth(method = "lm")
`geom_smooth()` using formula = 'y ~ x'
> 

The best fit linear model of the data points towards the model jremington posted: pressure = 0.237 * ADC -44.759 and also shows that those end points don't quite fit with the line through the rest of the points.

Looking at the model, I think any pressures above 198PSI will read as 1023 on the ADC, and 0PSI will read as 188.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.