PR33-7 4-20ma. Convert Data code and adjust readings

Hello again. So I have read the forums and also the following tutorials you made on 4-20mA, how to. But got stuck on the ADS Values as I am using a very simple code provided by you on github.

I have tried to find examples on converting the 4-20mA readings to know values of my sensor, and also how to calibrate so I get true 4-20mA instead of a lower number.

For calibration.
I should show a 0 reading as 4mA and 200 as 20mA. But what I actually see on my console is a flow of 0 = 3.827mA through 3.93mA and a flow of 200 as 19.67 to 19.678.
How do I enter calibration code to fix this variable?

For Converting the data.
My flow meter will measure 0 to 200 CFM. So I need to add code that will change the mA values to read and measure the date in between if a flow of 0 = 4mA and flow of 200 CFM = 20mA. Ane everywhere in between.

Thank you in advance for your time. I really tried to find the solution online on all the forums but was unsuccessful.

Here is a screenshot of my particle console. I will post my code for the .ino file and the ads1115.cpp separately.

Here is my Datalogger.ino code.

  • Date: 4/28/18
    */

// setup() runs once, when the device is first turned on.
#include “ads1115.h”

ADS1115 inputBoard;

float ma = 0.0;

void setup() {
inputBoard.setAddress(0);
}

void loop() {

//Input 1
int16_t input_1 = inputBoard.readInput(1);
ma = (input_1*4.00)/2130.00;

Serial.printf("Input 1 reading: %f \n", ma);


delay(1000);

Particle.publish("Input 1 reading", String(ma) + " mA"); delay(2000);

}

Here is my ads1115.cpp code

#include “ads1115.h”

bool ADS1115::setAddress(int addressJumper){
if(addressJumper == 1){
address = address | 1;
}
}

int ADS1115::readInput(int channel){
// byte writeData[2] = {(byte)readInputSingleEnded[channel -1], (byte)(readInputSingleEnded[channel - 1]>>8)};
if(!wireWrite(address, 0x01, readInputSingleEnded[channel -1], 2)){
Serial.println(“WireWrite failed”);
}
delay(50);
if(!wireRead(address, 0x00, localReadBuf, 2)){
Serial.println(“WireRead failed”);
}

uint16_t raw_adc = (localReadBuf[0] << 8) | localReadBuf[1];

return raw_adc;

}

bool ADS1115::wireWrite(int addr, int reg, uint16_t value, int len){
if (!Wire.isEnabled()) {
Wire.begin();
}
Wire.beginTransmission(addr);
Wire.write((uint8_t)reg);
Wire.write((uint8_t)(value>>8));
Wire.write((uint8_t)(value & 0xFF));
byte status = Wire.endTransmission();
if(status == 0){
return true;
}else{
return false;
}
}

bool ADS1115::wireRead(int addr, int reg, int* readBuff, int returnLen){
int buf[returnLen];
if (!Wire.isEnabled()) {
Wire.begin();
}
Wire.beginTransmission(addr);
Wire.write(reg);
byte status = Wire.endTransmission();
if(status != 0){
return false;
}
Wire.requestFrom(addr, returnLen);
unsigned long startTime = millis();
while(Wire.available() != returnLen && millis()<startTime+timeout);
if(Wire.available() != returnLen){
return false;
}
for(int i = 0; i < returnLen; i++){
readBuff[i] = Wire.read();
// Serial.printf(“read: %i \n”, readBuff[i]);
}
return true;
}

Hi,
You can print the raw value. and then convert raw values into flow rate.
checkout this tutorial on how to convert 4-20mA values into raw worls values

Thanks

Thank you. I have changed the code to read the adc values. I now have those values showing in my console.
What I can’t find is the code to use along with your formula to make the conversion. I have searched and searched. It is probably right in front of my face. Sorry to be such a pest. I really appreciate the support.

I am now showing a flow of 0= range 2033 to 2046 and flow of 200= range 10,488 to 10,495

Thank you.

You can check out the above mention tutorial, it explain how to convert raw values into real world values.
It will require some linear algebra calculations.

Thanks

if you are not a big fan of maths and want to avoid the pain
use this formula
flow = (raw_adc-2040)/42.25
(2040 = its avg value of 2033 and 2046)
Thanks

1 Like

Thank you so much. This worked great. I really appreciate all the support. You all are the best.

Cheers.

One last question… only because my mind for some reason wont let me see the obvious.

Where did the 42.25 number come from? or what does it reference?

Thank you again.

slop = y2-y1/x2-x1
= 10490-2040/200-0
= 42.25

linear equation = y = mx+c
at point A ( y = 2040 and x = 0)
2040 = 42.25*0 + c
c = 2040

at any point
y = mx+c
y-c/m = x
x = raw_adc - 2040/42.95
x ==== flow rate