Relation between voltage and adc of ads1115

Hello all ,

i have flow sensor which giving 4-20ma so i am using 220 ohm resistor so for 4ma output is 0.88v and corresponding flow measurement range is 0.2 lpm , for 20ma output is 4.4v and flow measurement range is 50 lpm.

in my setup vdd of ads1115 chip is connected to 5v pin of uno.
my output is 0.88 to 4.4v .

i am not able to understand how to scale my output voltage to adc value .

Voltage=( slope * adc reading ) + constant and then this formula use to calculate flowrate as below ,

flowRate= (14.148 * voltage) - 12.25 which i calculate from 0.88v= 0.2 lpm and 4.4v=50 lpm
thanks

In four steps.

float flow = minimumFlow + (flowRange / voltageRange) * (measuredVoltage - minimumVoltage);

float flow = 0.2 +  ((50.0 - 0.2) / (4.4 - 0.88)) * (ADS.getVoltage() - 0.88);

float flow = 0.2 +  14.148 * (ADS.getVoltage() - 0.88);

float flow = -12.25 + 14.148 * ADS.getVoltage();

So your formula is correct,
you might need some precautions to detect broken wire

flow = 0;
voltage = ADS.getVoltage();
if (voltage < 0.1) Serial.println("Warning: no voltage broken wire?");
else if (voltage < 0.88) Serial.println("Warning: under voltage ");
else if (voltage > 4.4) Serial.println("Warning: over voltage");
else flow = -12.25 + 14.148 * ADS.getVoltage();

Of course you can test with less strict values like 0.8 instead of 0.88 and 4.5 instead of 4.4.

Be sure to use a precision resistor - 1% or better as otherwise the 16 bits of the ADS1115 is overkill.

you might check my library - GitHub - RobTillaart/ADS1X15: Arduino library for ADS1015 = I2C 12 bit ADC and ADS1115 = I2C 16 bit ADC

Hello thanks for the answer . i have downloaded your library . and i think i dont need to manually scale it down voltage to adc and all right ?.

but when i am compiling code that time i am getting this .

SO replace ads.getVoltage() in your code to ads.toVoltage()

Hi thanks for response,

#include <Wire.h>
#include <ADS1X15.h>  // Include the Rob Tillaart ADS1X15 library

ADS1115 ads;  // Create an ADS1115 object

void setup() {
    Serial.begin(9600);  // Start serial communication
    ads.begin();  // Initialize the ADS1115 sensor
}

void loop() {
    float flow = 0;  // Default flow rate
    int16_t adcValue = ads.readADC(0);  // Read raw ADC value from channel 0
    float voltage = ads.toVoltage(adcValue);  // Convert raw ADC value to voltage

    // Check for no voltage, under voltage, or over voltage
    if (voltage < 0.1) 
        Serial.println("Warning: no voltage, broken wire?");
    else if (voltage < 0.88) 
        Serial.println("Warning: under voltage");
    else if (voltage > 4.4) 
        Serial.println("Warning: over voltage");
    else 
        flow = -12.25 + 14.148 * voltage;  // Calculate flow if voltage is normal

    // Print the ADC value, voltage (with 3 decimal places), and flow rate
    Serial.print("ADC Value: ");
    Serial.print(adcValue);
    Serial.print(" | Voltage: ");
    Serial.print(voltage, 3);  // Print voltage with 3 decimal places
    Serial.print(" V | Flow Rate: ");
    Serial.print(flow);
    Serial.println(" L/min");  // Assuming the flow rate is in liters per minute

    delay(1000);  // Wait 1 second before next reading
}

i am getting this kind of value

when there is no spraying
ADC Value: 4678 | Voltage: 0.877 V | Flow Rate: 0.000 L/min

this during my spraying cycle
ADC Value: 4789 | Voltage: 0.898 V | Flow Rate: 0.45 L/min
ADC Value: 4777 | Voltage: 0.896 V | Flow Rate: 0.42 L/min

again no spraying
ADC Value: 4678 | Voltage: 0.877 V | Flow Rate: 0.000 L/min

again during spraying,
ADC Value: 4777 | Voltage: 0.896 V | Flow Rate: 0.42 L/min
ADC Value: 4792 | Voltage: 0.899 V | Flow Rate: 0.46 L/min

during spraying and not spraying i can observed nearly same voltage as on serial monitor.

this okay or something have to change in code .

and during spraying i get this result and spraying time is nearly 3 sec . then how to know how much water is sprayed out in cycle. have to improve code or ?

thanks

Yes, to know the flow you must integrate all samples during the time the valve is open.

a snippet of pseudocode

uint32_t t1, t2;
float lastFlow;
float flow;

void setup()
{
  ...

  lastFlow = 0;
  t1 = millis();
}

void loop
{
  flow = measureFlow();
  //  takes the average flow for the last duration
  t2 = millis();
  totalFlow = totalFlow + 0.5 * (flow + lastFlow) * (t2 -t1)   / 60000 ;
  //          total +     [    average flow     ] * [duration] / [millis to minutes]
  lastFlow = flow;
  t1 = t2;

  Serial.println(totalFlow);

}

it is possible to use a better integration code and it is probable that you need serious adjustments to get it working 100% to your needs.

1 Like

thanks for guidance,

still small question can i do linear relation between voltage and adc like ,

ADC value 4677 corresponds to 0.88V
ADC value 32767 corresponds to 4.4V

y = ( 0.000125*X )+0.295375 where y= voltage and x= adc value

i mean can we do this way or not ?

thanks

if you fill in 4677 ==> 0.88
if you fill in 32767 ==> 4.39125

So if you indeed read those two ADC values the formula is correct.
However I doubt that you will read 32767 at 4.4 Volt, you need to verify that again.

The default range is 6.144 V for 32767 so I expect 4.4 / 6.144 * 32767 ==> 23466 as raw

As the ADC reads zero at zero volt the formula is even simpler.
Every step is 6.144 volt / 32767 = 0.0001875;

voltage = raw * 0.0001875;

4693 => 0.8799375... volt
23466 => 4,399875...volt

Hey thanks a lot , you were right.
"you need to verify that again."

thanks