How to fix unstable analog output from A0 pin

Hello,

actually i am trying to read 4-20 mA by using Arduino Uno and same is little successful but reading on display is continuously varring ± 0.15 mA (i.e. measure value is continuously fluctuating in digit after the decimal point), means it is not stable but at same time 4-20 mA source shows a fix (stable) reading on their display and i already checked source is correct and calibrated.

Can you suggest me how can i fix this issue.

CODE:-

#include <LiquidCrystal.h>
float Vacross0,Iamp0 = 0;
const int Shunt_Res0 = 250;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
lcd.begin(16, 2);
}

void loop() {
Vacross0 = analogRead(A0);

Vacross0 = (Vacross0 * 5.0) / 1023.0;
Iamp0 = (Vacross0 * 1000) / Shunt_Res0;

lcd.setCursor(0, 0);
lcd.print("A0=");
lcd.print(Iamp0);
lcd.print("mA");
delay(500);

}

const int Shunt_Res0 = 250;
cf.
const float Shunt_Res0 = 250.0;

0.15mA isn't 'unstable', it's not a lot to be "off" by.

1 Like

While reading 4-20 mA, +- 0.15mA is big error.

@sumit110, your topic has been moved to a more suitable location on the forum ( where your old topic is also located :wink: ) Installation and Troubleshooting is not for problems with your project, see About the Installation & Troubleshooting category.

Can you please take some time again (!) to read How to get the best out of this forum and apply what you have read / learned about code tags (the </> button) to the code in your post. Using code tags has been mentioned before in your other thread.

#include <LiquidCrystal.h>
float Iamp0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() 
{
lcd.begin(16, 2);
}

void loop() 
{
  Iamp0 = (analogRead(A0)) * 0.02;
  lcd.setCursor(0, 0);
  lcd.print("A0=");
  lcd.print(Iamp0);
  lcd.print("mA");
  delay(500);
}

Post Edit --
Putting that sketch to the test using "5V" and seven 1N4148 diodes (approx 0.6V ea.) in series with 220Ω (and Serial Monitor instead of LCD)
I get "3.86mA" with an occasional "3.88mA"

Dear @runaway_pancake

Thanks for your reply, and it is really helpful to me, now error (span of fluctuation is reduce) but still reading is not stable. Can you help me to fix this issue?

I had been editing my post while you made your last Reply.
(See above.)
No matter what - the readings will not be so rock-solid as to be 'invariable'.

Actually i am new in electronics, and due to the same i am not getting meaning of below term can you elaborate please?

Putting that sketch to the test using "5V" and seven 1N4148 diodes (approx 0.6V ea.) in series with 220Ω

That's my solution to not having a 4-20mA current source laying around.
Suffice to say, there is about 0.8V across my 220ohm resistor, meaning there's about 3.6mA.
External noise will skew results (contribute to 'error'). You may have to twist (loosely) your current source leads.

Here I have modified the loop () to print out the results of the analogRead, which may be of interest --

void loop() 
{
  Iamp0 = analogRead(A0);
  Serial.print(Iamp0);
  Serial.print(" -- ");
  Iamp0 = Iamp0 * 0.02;
  //lcd.setCursor(0, 0);
  Serial.print("A0 = ");
  Serial.print(Iamp0);
  Serial.println("mA");
  delay(500);
}

At this resolution, every count means about "0.02mA".
16mA of range, spanning 800 counts (16 / 800 = 0.02 each).

@runaway_pancake

I dont really understand what you are saying. your linguistics are better than mine. i am new in electronics. please can you elaborate in simple language.

The value the A/D returns depends on two things.
The voltage on the analogue input, and the reference voltage of the A/D.
You have chosen (with default Aref and the 250 ohm resistor) to use the potentially unstable supply of the Arduino as reference. No wonder that the values are fluctuating.

The better way would be using a 51 ohm resistor and the stable internal 1.1volt Aref.
There are many threads on this site explaining howto. Do a search.
Leo..

You are using a 250 ohm resistor so for 4mA you see 1000mV and for 20mA 5000mV.
1: You dont say what the source of the 4-20mA is and it may well not like driving that load.
2: The supply current for the display is flowing through the same ground line as the 4-20mA loop and may affect your readings. You SHOULD use a star ground.
3: I see no decoupling capacitor on your frizzy breadboard between Vcc and ground.

So, my suggestions:
1: as Leo says use a stable reference to measure the 4-20mA; assuming you ARE using a UNO the INTERNAL reference is stated as 1100mV.
2: change the load resistor to 51 ohms. That will give 20mA = 1000mV and 4mA = 200mV (approx)
3: Connect the 4-20mA ground on the busbar at the top of the board as shown on the frizzy, and connect that to a seperate ground pin on the arduino. (eg the ground next to AREF)
4: Put an electrolytic capacitor - say 470uF - across the supply connections to the display.
5: work in millivolts, milliamps to keep the best resolution.
6: take and average multiple readings from the ADC as shown in the code below
you will need to adjust these values to get accurate readings.
float Shunt_Res0 = 51.0; //the TRUE value of the load resistor
float vRef = 1100.0; // the TRUE value of the reference voltage

CODE: (not tested)

#include <LiquidCrystal.h>
int iValue; //the value you read in from the ADC.
int sum1;
float Vacross0, Iamp0 = 0;
float Shunt_Res0 = 51.0; //the TRUE value of the load resistor
float vRef = 1100.0; // the TRUE value of the reference voltage in mV
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
lcd.begin(16, 2);
analogReference(INTERNAL);
}

void loop() {
sum1 = 0; //ready to start adding values
  //add up 16 successive readings; 
  for (byte count = 0; count <16; count++ )
  {
    iValue = analogRead(A0);    // actual read
    sum1 = sum1 + iValue;
    delay(20);
  }
Vacross0 = (sum1 * vRef) / 16 *  1024.0;  //millivolts
Iamp0 = (Vacross0 ) / Shunt_Res0; //milliamps

lcd.setCursor(0, 0);
lcd.print("A0=");
lcd.print(Iamp0);
lcd.print("mA");
delay(500);

Uhhh, as long as the common point is the Arduino board itself.
There should no other current flow through the 4-20mA circuit other than the sensor current.
A dedicated/separate sensor ground could be better.

The code in post#13 should of course include a call to the internal 1V1 reference in setup().
Leo..

Thanks Leo! code edited.

@Wawa Thanks for your suggestion and reply, i will check :slightly_smiling_face:.

@johnerrington

Thank you so much for your reply. its very helpful to me. i will check up with above solution and let you know. I really appreciated your help to me.

@johnerrington

Everything i got it but i am not getting regarding average reading, Can you explain me how to i will get 16 no. Of average reading and what I have to change or add on above code for average reading. please explain me.

You get an average by taking a number of readings (say 16)
adding the results together
then dividing by the number of readings (eg by 16)

you dont have to add or change anything. The code above aggregates (adds up) 16 readings; then this line does the divide by 16 AND the conversion to mV.

Vacross0 = (sum1 * vRef)  / ( 16  *  1024.0) ;  //millivolts

TRY IT

@johnerrington

I already checked this code but error on display output with unstability @ 4ma input, its showing 4270933 mA to 4276622 ma on display. Can you check up please.