2-wire 4-20ma transducer setup [SOLVED]

@peekay123


Sorry about the unprofessionally/unlabeled graph, but there are values starting at the 20 in fully retracted point. I just used a ruler and went for inch interments all the way to 12. Sorry this is all non-metric… I used a trend line and the function is displayed on the graph.

@bvolzmfg, that is a thing of beauty! As you can see, the fit to a straight line (R squared) is very near the ideal value of 1. As you can see, there is an offset of 578 (if you extend the line to 0 inches, the ADC value is 578).

Are there possible readings below 8 inches or is that the mechanical limit of your configuration?

1 Like

The equation you want for your code though, is the one where the inch values are on the y axis and the ADC values on the x axis, since it’s those ADC values that you measure, and you want to calculate inches. So, you can either re-plot the data that way, or just rearrange the equation to solve for x.

2 Likes

fyi I use this board

https://www.controleverything.com/content/Current-Loop-Input?sku=ADS1115_INA196_4C

and it works awesome, very simple and provides the power. Currently measuring 4 thermocouples connected to 4-20 pucks.

1 Like

There would be readings potentially close to the 20 inch max of the transducer and down to 0 inches. So most of the mechanical range (0-20 in) is used.

Appreciate that catch

Revised Graph:

This is the code for it I believe LiftPosition = 0.0079*PositionReading - 4.5065 ;

@bvolzmfg, you may want to take a few measurements at the low end, ideally between 0 and 5 inches to make sure the linear relationship holds. Once that is done, the code will be easy to implement.

I appreciate all the help. Especially @peekay123. It works great for now, just had to alter the slope a little to get it to read properly at high and low.

Here is the code final code for anyone’s future reference.

int PositionTransducerPin = A0; // connected to analog pin 0
int PositionReading = 0;
int LiftPosition = 0;



void setup()
{
    Particle.variable("Position", &PositionReading, INT);
}

void loop()
{
    PositionReading = analogRead(PositionTransducerPin);
    
    if (PositionReading >= 581 && PositionReading <= 2921) {  // Only calculate and publish is transducer reading is in range

        LiftPosition = 0.0085*PositionReading - 4.5065 ; // values for 120 Ω resistor  
    
        Particle.publish("Position", String(LiftPosition));
    
    }     
     
    delay(1500);
}

@bvolzmfg, for the sake of “proper” coding, you should add a range check prior to your calculation to avoid spurious and incorrect readings. For example if the ADC returns a value below 531, a negative distance will be returned. Also, for ADC values above 2883, the distance will exceed the transducer’s 20 inch range. So, adding this simple check will discard any invalid values:

void loop()
{
    PositionReading = analogRead(PositionTransducerPin);

    if (PositionReading >= 531 && PositionReading <= 2883) {  // Only calculate and publish is transducer reading is in range

       LiftPosition = 0.0085*PositionReading - 4.5065 ; // values for 120 Ω resistor

       Particle.publish("Position", String(LiftPosition));
    }
    delay(1500);
}

:smile:

1 Like

I appreciate that, wouldn’t have thought of it. I am having to adjust the top and bottom of the range (531 & 2883) a little because it wont read 20 Inches at at its stationary position. I guess that is just the variation of resistor?

@bvolzmfg, yup you nailed it. The transducer has a specified error range and the 120 ohm resistor is most likely a +/- 5% resistor. Simply adjust your “acceptable” value range accordingly. Good job! :wink:

1 Like

Thanks!