DFRobot/Gravity Throw-in type liquid level transmitter

Hi,
First Arduino project and the evidence tells me I have bought a dud. I think I am just a few lines of code away from rescuing it but I don’t have the skills or experience yet to clearly work through the problems and identify a reasonable solution.

Can someone assist please?

The problem I have is very similar to this one (which I would have posted into but for the requirement for a moderator to bump it due to its age).
https://forum.arduino.cc/index.php?topic=641570.0

I too have bought the DFRobot drop in liquid level pressure sensor and current to voltage converter.
This is the whole project

Here is a link specifically to the current to voltage converter (120 ohm resistor)

The code loaded onto Arduino Uno V3 (straight from the project tutorial):

/***********************************************************
  DFRobot Gravity: Analog Current to Voltage Converter(For 4~20mA Application)
  SKU:SEN0262

  GNU Lesser General Public License.
  See <http://www.gnu.org/licenses/> for details.
  All above must be included in any redistribution
****************************************************/

#define ANALOG_PIN A1
#define RANGE 5000 // Depth measuring range 5000mm (for water)
#define CURRENT_INIT 4.00 // Current @ 0mm (uint:mA)
#define DENSITY_WATER 1  // Pure water density normalized to 1
#define DENSITY_GASOLINE 0.74  // Gasoline density
#define PRINT_INTERVAL 1000

int16_t dataVoltage;
float dataCurrent, depth; //unit:mA
unsigned long timepoint_measure;

void setup()
{
 Serial.begin(9600);
 pinMode(ANALOG_PIN, INPUT);
 timepoint_measure = millis();
}

void loop()
{
 if (millis() - timepoint_measure > PRINT_INTERVAL) {
    timepoint_measure = millis();

    dataVoltage = analogRead(ANALOG_PIN);
    dataCurrent = dataVoltage / 120.0; //Sense Resistor:120ohm

    depth = (dataCurrent - CURRENT_INIT) * (RANGE/ DENSITY_WATER / 16.0); //Calculate depth from current
readings

    if (depth < 0) depth = 0.0;

   //Serial print results
   Serial.print("depth:");
   Serial.print(depth);
   Serial.println("mm");
  } 
}

My physical setup is shown in the attached photo. As far as I can tell, just what the project tutorial recommends.
The thick black ‘cable’ is the sensor. It has +ve, -ve and a tube for sensing atmospheric pressure.

The arduino is powered with a 12v 2.1A power supply from an Optus modem/router. I did this to try and get the Arduino voltage as clean and close to 5V as possible after reading a few posts that recommended using the power pin for this purpose.

The primary error is that:

  1. The code provided returns 0.0mm water depth always.
    See results 1 in attached results file.

Secondary issues as far as I can tell:
The actual value reported by the code project is a negative depth but this is set to 0mm by

if (depth<0) depth=0

When I comment out the error mask I get:
See Results 2 in the attached results file.

I left the last 0.00mm reading in the copied data just so you could see how the output changed from the newly modified code.
So its generally reading around -960mm (in a bucket of water with about 185mm depth in it). Clearly wrong.
But also clearly wandering a lot. I believe from Wawa’s original comments that the scatter is likely due to the poor choice of reference voltage in DFRobot’s code.
I have tried to tackle the accuracy side first as I think I have a hope of nutting that out. Preliminary efforts understanding how to change the reference voltage to sort out precision have proven daunting – hence why the original post from 2019 did not set me right.
So I serial print a few more parameters to see whats going on:
See Results 3 in attached results file

OK, so now on to the multimeter to see if I can measure circuit parameters and calculate the result that the code delivers.

Current at the green terminal block of the A to V converter is 4.47mA. Sounds reasonable for 185mm of water. Furthermore, it is stable.

Voltage at the pin connectors halfway between the A to V converter and the Arduino is
4.29V between +ve and the blue wire to A1 on arduino (ie the signal voltage). It is stable.
4.94V between the +ve and the gnd wire (ie the Arduino voltage). It’s quite stable too. One little flicker to 4.95V when first measuring, but fine after that.

Using dataVoltage of 111, I understand the arduino is probably seeing 111/1024 * 4.95V = 0.53657V which when divided by the 120 Ohm resistor gives 0.004471435.

That’s the 4.47mA I measured with the DMM. Sounds like I understand a bit of what is going on here. I picked up the importance of the 1024 (or 1023) from other posts.

But the code that DFRobot provide doesn’t use the 1024. It just divides dataVoltage (111 in the example) by the resistor’s 120Ohm which doesn’t seem to honor the science.

Am I correct that DFRobot have an error in that calculation of dataCurrent?

If so, how do I fix it?

Because if I carry my calculations a little further, I subtract 4mA CURRENT_INIT from my 4.47mA to get 0.000471435, which I multiply by the

(RANGE/DENSITY_WATER/16)

part of the code (which is 5000/16 and equals 312.5) and end up with 147.324mm of water. Not far off the actual 185mm or so.

Also must mention the it seems DFRobot have incorrectly defined CURRENT_INIT by assigning it 4.0 instead of 0.004 to remain in SI units to work with the voltage (not millivolts) reading from the sensor.

So, I figure:

Change CURRENT_INIT to 0.004

Change the calculation of dataCurrent to = ((dataVoltage/1024)*4.95)/120)

But when I do that, I get weird results where dataCurrent goes to 0 and Depth goes to -1.25mm. I’m lost here!
See Reults 4 in attached results file.

And none of this has even contemplated the issue of precision yet.

What advice do you have for me?

Here is the final code for completeness:

/***********************************************************
  DFRobot Gravity: Analog Current to Voltage Converter(For 4~20mA Application)
  SKU:SEN0262

  GNU Lesser General Public License.
  See <http://www.gnu.org/licenses/> for details.
  All above must be included in any redistribution
 ****************************************************/

#define ANALOG_PIN A1
#define RANGE 5000 // Depth measuring range 5000mm (for water)
#define CURRENT_INIT 0.004 // Current @ 0mm (uint: mA)
#define DENSITY_WATER 1  // Pure water density normalized to 1
#define DENSITY_GASOLINE 0.74  // Gasoline density
#define PRINT_INTERVAL 1000

int16_t dataVoltage;
float dataCurrent, depth; //unit:mA
unsigned long timepoint_measure;

void setup()
{
  Serial.begin(9600);
  pinMode(ANALOG_PIN, INPUT);
  timepoint_measure = millis();
}

void loop()
{
  if (millis() - timepoint_measure > PRINT_INTERVAL) {
    timepoint_measure = millis();

    dataVoltage = analogRead(ANALOG_PIN);
    dataCurrent = ((dataVoltage / 1024) * 4.95) / 120.0; //Sense Resistor:120ohm
    depth = (dataCurrent - CURRENT_INIT) * (RANGE / DENSITY_WATER / 16.0); //Calculate depth from current readings

    //    if (depth < 0) depth = 0.0;

    //Serial print results
    Serial.print("dataVoltage:");
    Serial.print(dataVoltage);
    Serial.print("    dataCurrent:");
    Serial.print(dataCurrent);
    Serial.print("    depth:");
    Serial.print(depth);
    Serial.println("mm");
  }
}

You are being hurt by integer division. dataVoltage is an int. dataVoltage/1024 will be zero unless dataVoltage is 1024. Try dataVoltage/1024.0 instead.