4-20ma water level sensor

Hi, I have a 4-20ma water level sensor (head pressure sensor) hooked up to an Arduino Mega and am seeing some unexpected results. The sensor is sitting at the bottom of my homes water cistern located ~ 60ft away from the home. There is a copper wire pair that runs out there for the sensor from a utility room in the house where the Arduino and power supplies are mounted. Below is a trend indicating the unexpected behavior. The voltage change between the valley and the peak on the trend is about 1 volt on the analog pin. But no water was added to the cistern in that time and usage was pretty mild, I would expect the level to slowly trend down over the month not rise and fall over a couple day period

Here is my wiring schematic, I'm using a 12V Mean Well power supply to power the 4-20ma loop, that same power supply is also powering the Arduino on the barrel jack. (lets pretend the drawing is of an Arduino Mega and not the Uno)

The Sensor is ranged 0-5M depth

I tried a 24v power supply aswell and didn't have very good luck, the sensor was very close to saturated even though the level in the cistern was only about 3M deep. It was reading ~4.8 volts at the Analog pin. Which I thought to be out to lunch, I don't think the sensor right now being powered by the 12 supply is wildly out to lunch i just expected to see a really steady level slowly decline over the month, not increase 20% ish over a couple days and then fall back and repeat.

Below is my code, I was wondering if any one had any comments or suggestions on any part of the setup on what you would do differently and also why I maybe seeing this rise and fall in the voltage reading on the analog pin when the level should have been near dead steady through that time period or if anything slowly be dropping as we use water in the house. Its weird I had an issue running the sensor part of the loop on 24V aswell, the sensor I purchased was sold as a 24V sensor.

Troubleshooting done:

  • I've removed the sensor from the loop and hooked up a 4-20ma signal generator in its place and tested that section of the loop including through the resistor and there was no issue with what the Arduino kicked back. at 20ma it was 5V and at 4ma 1V and made sense through the range.
  • I've played around with grounds, connecting the ground from the AC side of the power supply to the grounds on the Arduino and sensor loop, didn't seem to affect anything.
  • I've tried powering the Arduino from the USB and the 12V supply, seemed to make minimal difference over the same time period as the attached trend
  • Ive thought maybe temperature was effecting the reading but the cistern is buried below ground and I don't think its changing much in there, the peaks on the trend are at 10pm and 3pm, it doesnt match up with heat of the day or anything along those lines

Any criticism or advice would be welcome, Thanks!

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_TEMPLATE_NAME ""
#define BLYNK_AUTH_TOKEN ""

#include <BlynkMultiClient.h>

byte ETH_MAC[] =        {  };

#include <SPI.h>
#include <Ethernet.h>  
#include <math.h>
#include <DHT.h>

#define W5100_CS   10
#define SDCARD_CS  4
#define ANALOG_PIN A0
#define RANGE 5000 // Depth measuring range 5000mm (for water)
#define VREF 5000 // ADC's reference voltage on your Arduino,typical value:5000mV
#define CURRENT_INIT 4.00 // Current @ 0mm (uint: mA)
#define DENSITY_WATER 1  // Pure water density normalized to 1

int16_t dataVoltage;
float Val2, Val3;

static EthernetClient blynkEthernetClient;

void connectEthernet()
{
  if (Ethernet.begin(ETH_MAC, 5000L, 500L)) {
    Serial.print("Ethernet IP: ");
    Serial.println(Ethernet.localIP());
  } else if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.");
  } else if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  } else {
    Serial.println("Ethernet: DHCP configuration failed.");
  }
}

void setup()
{
  // Debug console
  Serial.begin(9600);

  // Deselect the SD card
  pinMode(SDCARD_CS, OUTPUT);
  digitalWrite(SDCARD_CS, HIGH);

  // Initialize Ethernet shield
  Ethernet.init(W5100_CS);
  delay(1000); // Give the Ethernet shield a second to initialize

  connectEthernet();

  // Setup Blynk
  Blynk.addClient("ETH", blynkEthernetClient, 80);
  Blynk.config(BLYNK_AUTH_TOKEN);

  pinMode(ANALOG_PIN, INPUT);
 
}

void loop()
{
dataVoltage = analogRead(ANALOG_PIN)/ 1024.0 * VREF;
Val2 = map(dataVoltage,0,5000,0,10000);
Val3 = Val2/100;
  Blynk.virtualWrite(V0, dataVoltage);
  Blynk.virtualWrite(V1, Val3);

  Blynk.run();
  Ethernet.maintain();
 delay(2000);
 
}

How was the air pressure in that time? Is the sensor air pressure compensated?

I prefer RS485 sensor.

Hello mbabiy

Make step back and run a tutorial for the sensor only to study the sensor behaviour.

Hmm, ya fair question. I would say that the sensor is not air pressure compensated, Looks like it went from 100.6 kPa to 103.0kPa so 2.5kPa change, 1M of water is 9.81 kPa so the sensor is about 50kPa range so i guess that would change it maybe 5% anyways. Never thought of that, Thanks

Hi,
Can you please post a link to specs/data of the sensor?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

Does your pressure sensor measure absolute pressure or gauge pressure?

Can you give us a link to the pressure sensor data sheet, or at least tell us its make and model number?

Depends on a few things …

You need to use the internal reference on your board and change the burden resistor , by default the A/D uses Vcc as it’s reference ( which your code does ) , which can drift around .
If it is an absolute transducer then the output will change with atmospheric pressure , you should use a gauge ( differential) type sensor .

What is the span of your transducer , is it suitable for this pressure range ( looks fine -5m ~ 0.5bar) . What is the transducer , is it suitable for use in water ? ( not a cheapo one …)

Look at transducer errors - an inch or so movement in that span may well be within the error band ( drift etc) of the transducer ( 0.1% of 5m span is 5cm )

This type of setup is prone to long term small leaks causing errors .
There are other techniques , eg bubblers

1 Like

oops. 1%.

1 Like

Haha, This is what i found on specifications of the sensor, It was a cheap amazon one, 50$ CAD or something like that. Not sure what the application Fire Refrigerator is... But ya its probably not the highest quality sensor to hit the market that is for sure.

Item Type: Liquid Level Transmitter
Probe Material: Stainless Steel
Model: WLB-131Y
Function: Water Level Measurement
Applicable Scenarios: Fire refrigerator, deep well water level, river reservoir, engineering pool
Power Supply Voltage: DC24V
Output Signal: 4~20mA
Accuracy: 0.5% FS
Measuring Range: Approx. 5metres / 16.4ft
Protection Level: IP68
Temperature: 0~60℃

Hammy, I think my code just sets the VREF at 5000, should i be measuring the VREF off the Arduino instead and using it? the reading does not seem to be noisy and the drift takes a couple days or so to move 15-20%, would the voltage drift on the Vref be that slow?

I hear ya about the bubbler setup and a few other ways to accurately measure levels in an industrial setting, I have a background in Process Operations and Control, This was just a cheap experiment at home so i obviously didnt get industrial grade sensors and such. You guys all made good points on the atmospheric pressure and the transducer error.

The supply voltage is not an accurate reference , it will drift with time and temperature . The internal ref (1.1volt) is more stable .

The accuracy figure is basic . Probably just linearity ? Add temperature drift , hysteresis and so on . Measure the 4-20mA with a good multimeter and see if it drifts over time for a fixed depth .

You're really should be using the 1.1v internal reference, as explained by @Wawa in this post...

...using the schematic linked in that post.

Careful here, if the connection to your load resistor becomes faulty, the sensor could apply maximum voltage (12V?) trying to drive current through a faulty or open circuit to your input pin, I would put a 15k resistor between load resistor and input pin to limit current through the pin's protection diode and a 100nF ceramic capacitor from input pin to GND.
Take @hammy's advice and use the internal 1.1V ADC reference and use a 51Ω resistor instead of 250Ω, that would give 1.02V @ 20mA.
If you want to get closer to 50Ω, put a 2.4k resistor in parallel with the 51, resulting resistance will be about 49.94Ω and 0.999V with 20mA flowing.

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