Converting 4-20mA outputs from sensor into physical displacement

Dumb question: How can I convert 4-20mA of input current from a sensor and translate that into physical units for me to do calculations?

Here's my take on it:
If I have a linear displacement sensors with a range of 0-50mm, and I hook it up to the SEN0262 module and connect that to an Arduino. Based on the graph in this example, everything's linearly related.

So that means I can say 4mA-->0mm and 20mA-->50mm. Or alternatively I can say 0.48V-->0mm and 2.4V-->50mm.

Say I stick with just the voltage rather than converting to current. I set the Y axis as displacement and X axis as the voltage and using the two data points I get:

y=3.13x-12.5 ---> and this is the formula I use in my code to get my physical displacement readings right?

The linear formula is

y = mx + b

You can use the fmap() function to convert one scale and offset to another. It doesn't matter what your source units are, as long as they are accurate and faithful to the input data.

Or, you can just do the math. It's not that hard.

You don't even need to use voltage units for this, you could use raw ADC values, since the voltage and/or current are a result of the distance, not directly relevant to it.

Yeah I went the route of doing the linear math based off my voltage values and known displacement values, I just wanted to make sure it made sense...Which it sounds like it does?

I wanted to convert around to voltage to help me verify everything made sense but I see what you mean.

I guess you're on the right track then. Verification should usually first be performed end to end, so in this case, looking at actual readings at the devices actual physical endpoints.

It is not efficient to convert to units that you don't use. The scaling costs CPU time to do the math.

What is the ADC reading at 4mA (0mm)? At 20mA (50mm)? Don't forget to subtract the 4mA (ADC ?) offset before the scale to mm.

By actual readings at the devices, you're talking about either voltage or ADC values from moving the endpoints around?

i.e moving one end 4mm, getting a reading from that, and moving it 9mm and getting another reading?

What is the ADC reading at 4mA (0mm)? At 20mA (50mm)?

I haven't done the actual calibration yet (tomorrow) to get those values...but how do those factor in this conversion? Just to verify?

Don't forget to subtract the 4mA (ADC ?) offset before the scale to mm.

Can you elaborate on what you mean by this?

EDIT:
Looking around, are you referring to this method? If so, what's the difference between my Y=mX+B formulas and what's below?

Move the device to 0mm.
Record the ADC value, call it A
Move the device to 50mm.
Record the ADC value, call it B

Now you are ready to measure, take a random reading C.

You now have all you need to calculate a mm offset given any ADC value.

Position(mm) = (C - B) / (A - B) * 50

A pen and envelope and a few minutes should help establish the connection to the formula y = mx + b.

1 Like

0.48V/0.004A = 2.4V/0.020A = 120 Ohm.

Does the module do more than a 120 ohm resistor?

Doing the end-to-end calibration helps account for any differences between the voltage calibration of the module and the voltage calibration of the Arduino's ADC reference.

You can code this using integer math if you use the right data types and order of calculation:

Position(mm) = (C - B) / (A - B) * 50

int position = 50L * (reading - B) / (A - B);

It's faster than float calculations.

Wait so, what’s the difference between this method and my method?

Shouldn’t they give the same result?

You didn't show the derivation of your formula, so I can't say. Or your code.

Yeah that’s my bad.

So I’m going the long route and calculating the voltages (even though ADC route is faster like you said).

My method of calibrating these sensors references a datum line in relation to two wheels. Since I want to know how much above or below my sensor is in relation to this line. Shown below.

Since I want to try to measure my displacement in relation to the two wheels, my idea is to have the bottom of the sensor be at a known distance below this line, and record the voltage (see Green ball).

Then, bring it up a known different height, record the new height and voltage values (see blue ball).

In this example,
Height1= -45mm Voltage1= 1V
Height2=-20mm Voltage2= 2V

From there, create my slope and line graph to convert. Does it make sense?

The example shows 20mA (2.4V) represents a pressure of 5000mm of water, not 50mm.

About the 120 Ohm resistor: the I/V converter isolates the power source for the sensor and the power of the board (though not completely) and in doing so it reduces the noise on the signal. Furthermore it prevents too high voltages (in case of mishap) from reaching the board. So: yes a 120 Ohm resistor is a cheaper (and working) solution, but this is better.

I'm worried about something else: in using the analogRead() you use VDD as a reference (assuming you use a board like the UNO). When reading the position of a potmeter it's no problem, but here you are measuring a voltage. The problem is this: when powering the UNO from VIN then VDD is 5 Volts, but when powering from the USB VDD is 4.6 Volts (and this goes for several other boards too), and this affects your reading.

If you use the end-to-end calibration everything is compensated, but be sure to use the same setup for calibation as you will use for the actual application.

Using another source for reference requires more knowledge of the processor on your board.

1 Like

I agree- which is why I plan on using the AREF pin on the arduino- that should mitigate the potential for any inaccuracies due to the power source right?

Using the AREF requires first of all a reliable voltage source. And then you need to meddle with the register setting for the ADC. I have not enough experience with Arduino IDE to guide in that.

All in all I think the best way is what I suggested earlier: do the end-to-end calibration and make sure that you use the same power source.

Bad idea. That pin can easilly be damaged and should not be used as an output.

Which Arduino are we talking about.
For an Uno or classic Nano, 4-20 mA is best measured with a 51 ohm sense resistor.
Leo..

Wawa, you are right about not using AREF as output, and I did not suggest using it as output.

The Nano Classic has the 328 processor, as does the UNO. If you suggest to use a 51 Ohm resistor instead of the I/V converter, you probably want to use the 1.1 Volt Internal Reference, and that still means meddling with the register settings for the ADC.

void setup() {
  analogReference(INTERNAL); // switch to 1.1volt Aref
}

Leo..