ADC false readings

Hello, I'm currently working on a project where I feed a voltage into A0 using an OP295 op amp. The op amp will give me a steady voltage of lets say 1.30v, the counts should be at 266, but the ADC will read +-20-30 counts off, so about 220 or 290, and it will read different at any given time. I am using the default reference voltage and it seems to be steady during the duration of my analogRead. When I try to feed my A0 pin with an external power supply @ 1.30 volts, my counts are exactly where they should be. I can't seem to figure out the problem here. I have placed the traditional .1uf caps from vcc to gnd, and from A0 to gnd. But I never seem to be able to achieve the value that it should be at. Any help would be greatly appreciated. Thanks.

Hello, I’m currently working on a project where I feed a voltage into A0 using an OP295 op amp. The op amp will give me a steady voltage of lets say 1.30v, the counts should be at 266, but the ADC will read ±20-30 counts off, so about 220 or 290, and it will read different at any given time. I am using the default reference voltage and it seems to be steady during the duration of my analogRead. When I try to feed my A0 pin with an external power supply @ 1.30 volts, my counts are exactly where they should be. I can’t seem to figure out the problem here. I have placed the traditional .1uf caps from vcc to gnd, and from A0 to gnd. But I never seem to be able to achieve the value that it should be at. Any help would be greatly appreciated. Thanks.

Could be noise on the opamps output.
What gain does the opamp have , and what is it amplifying.

How do you know it is a steady 1.3v. A multimeter can't tell you - it just gives you an average. You need an oscilloscope to be sure there is no variation in the voltage.

Things providing voltages to be measured by the ADC should have an output impedance of 10k or less (see the Atmega 328 datasheet). Does your op-amp circuit meet that condition?

...R

HI, can you post a circuit diagram please, a CAD or picture of a hand drawn circuit in jpg, png or pdf would be okay.

We need this information to help give you an accurate reply.

Thanks..

Tom...... :slight_smile:

Electromind:
The op amp will give me a steady voltage of lets say 1.30v, the counts should be at 266, but the ADC will read +-20-30 counts off,

OK....

Electromind:
When I try to feed my A0 pin with an external power supply @ 1.30 volts, my counts are exactly where they should be.

There's a clue.

Electromind:
I can't seem to figure out the problem here. I have placed the traditional .1uf caps from vcc to gnd, and from A0 to gnd. But I never seem to be able to achieve the value that it should be at. Any help would be greatly appreciated. Thanks.

Sounds to me like you need to stop fiddling with the Arduino and start fiddling with the op-amp instead.

Topics merged.

DO NOT CROSS-POST, IT WASTES TIME.

We need to know:
1-Power source (what it it ?) for arduino at time of error.
2- your Vcc voltage (voltage on 5V pin of Arduino) at the time of the error.
3- A schematic of your circuit.
4- Do you have a COMMON ground between op amp circuit and arduino ?

Here is the op amp side of the circuit, please forgive me as I have not revised and completed the full circuit schematic yet. I am amplifying the signal across a current sense resistor at a gain of 11. The voltage across the sense resistor, AND the output of the OP amp seem steady according to my multimeter.

You need to review and correct your schematic, it has connection points that should not be there.

Electromind:
The voltage across the sense resistor, AND the output of the OP amp seem steady according to my multimeter.

Mutlimeters are no good at measuring signals that wobble. I bet if you connect it to an oscilloscope you'll see something different.

polymorph:
You need to review and correct your schematic, it has connection points that should not be there.

Which connections exactly?

fungus:

Electromind:
The voltage across the sense resistor, AND the output of the OP amp seem steady according to my multimeter.

Mutlimeters are no good at measuring signals that wobble. I bet if you connect it to an oscilloscope you'll see something different.

I'll be able to scope the output as soon as I arrive at work

R2 and R3 are grounded, through multiple wires. The non-inverting input of the Op Amp is grounded. You wouldn't be getting 1.3V with it wired that way. I'm not sure what it would be, but it wouldn't be meaningful.

The ADC on the Due has a bandwidth of MHz, so there is a lot more noise bandwidth.

What bandwidth do you actually want to sample the signal on? Make sure you LPF
the signal going into the ADC pin (or sample frequently digitally LPF it afterwards).

You will find the ADC is noisy on the Due as it shares power with the digital
parts of the chip (alas).

polymorph:
R2 and R3 are grounded, through multiple wires. The non-inverting input of the Op Amp is grounded. You wouldn’t be getting 1.3V with it wired that way. I’m not sure what it would be, but it wouldn’t be meaningful.

Ahh, I didn’t notice that I had R3 connected to the wrong side of R2 in the schematic. It is wired properly on the circuit itself, my apologies for the mistake.

MarkT:
The ADC on the Due has a bandwidth of MHz, so there is a lot more noise bandwidth.

What bandwidth do you actually want to sample the signal on? Make sure you LPF
the signal going into the ADC pin (or sample frequently digitally LPF it afterwards).

You will find the ADC is noisy on the Due as it shares power with the digital
parts of the chip (alas).

I’m actually using the UNO board. I’m driving a MCP4822 DAC to control a LM317 which sources a voltage in a sweep. This is a setup for a test fixture. I am using an external power supply to power the board and the LM317. The voltage IN pin on the LM317 is coming straight from the power input line to reduce noise and load on the on board reg.

Here is the code.

#include <LiquidCrystal.h> // 16x4 display is connected to show voltage and time. DO NOT use pin digital pin 12 as it is MISO. 
#include <SPI.h>
#include <MCPDAC.h>


unsigned long previousMillis = 0;
unsigned long interval = 1000;


int y = A0; // Input voltage from opamp
int yy = 0; // check for counts proper counts at A0
int down = 0;
int up = 0; 
int xx = 0; // make sure counts come down
char Str1[8] = "FAIL";
char Str2[8] = "PASS";
char Str3[16] = "   SAFE MODE";
char Str4[16] = "Balancer ON";
char Str5[16] = "Balancer OFF";
char Str6[16] = "Test Results";
char Str7[16] = "Balancer Test";
int button = 9;
int val = 0;
int ledPass = A3;
int ledFail = A4;


LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
float volts;
unsigned long currentMillis;
void setup()
{
  // CS on pin 10, LDAC to ground, SDI on pin 11, SCK on pin 13. 
  MCPDAC.begin(10);
  lcd.begin(16, 4);

  // Set the gain to "HIGH" mode - 0 to 4096mV.
  MCPDAC.setGain(CHANNEL_A,GAIN_HIGH);
  
  // Do not shut down channel A, but shut down channel B.
  MCPDAC.shutdown(CHANNEL_A,false);
  MCPDAC.shutdown(CHANNEL_B,true);
 

pinMode(y, INPUT);
unsigned long currentMillis = millis();
pinMode(button, INPUT);
pinMode(ledPass, OUTPUT);
pinMode(ledFail, OUTPUT);
Serial.begin(9600);


}


void(*resetFunc)(void)=0;


void loop()
{
    val = digitalRead(button);
 noInterrupts();
   
  while(val <= 0){
    resetFunc();
    
}
  
 interrupts();

  unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
   previousMillis = currentMillis;
 
 static unsigned int volts;
  MCPDAC.setVoltage(CHANNEL_A,volts&volts);
digitalWrite(ledPass,LOW);
digitalWrite(ledFail,LOW);
lcd.setCursor(0,0);
lcd.print(Str7);
lcd.setCursor(4,2);
lcd.print("V1.0");
  Serial.println(yy);
   {

     if (currentMillis >= 2000){
    volts+= 100;
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print(Str4);
   volts =2480;
   lcd.setCursor(0,1);
   lcd.print((volts /1000.000) +1.3);
   lcd.setCursor(3,1);
   lcd.print("v");  
 { if(currentMillis >= 4400){
   yy = analogRead(y);
   if(yy >= 280 && yy <= 400){
     up = true;
   }}}}}
{

  if (currentMillis >= 4500){
    volts+= 100;
    volts =2175;
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print(Str5);
   lcd.setCursor(0,1);
   lcd.print((volts /1000.000) +1.3);
   lcd.setCursor(3,1);
   lcd.print("v");
  xx = analogRead(y);
  if(xx <= 0){
    down = true;
  }}}

{
  if (currentMillis >= 7000){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(Str6);
  lcd.setCursor(0, 1);
  
{
if(up == true && down == true){
   lcd.print(Str2);
  digitalWrite(ledPass, HIGH);
      delay(500);
    digitalWrite(ledPass, LOW);
 
  
}}
{
if(up == true && down != true){
    lcd.print(Str1);
  digitalWrite(ledFail, HIGH);
      delay(500);
    digitalWrite(ledFail, LOW);

 
}} 
{
  if(up!= true && down == true){
     lcd.print(Str1);
     digitalWrite(ledFail, HIGH);
    delay(500);
    digitalWrite(ledFail, LOW);
   
}}
{

  if(currentMillis >= 10000){
     volts = 0;
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print(Str3);
  


}}}}}}

What about the current sense resistor? Both ends can't be grounded.

Once again my mistake, I rushed while making the schematic to post on here. The GND OUT on the revised schematic(used paint to edit lol) is the output GND that a test board will plug into. I am measuring current on the low side. Again, sorry for the mistakes on the schematic.

REVISED SCHEMATIC

It is good practice to add a 2.2k resistor in series between the current sense resistor and the non-inverting input of the Op Amp. In that way, you compensate for input bias current. You can also then add a capacitor from the noninverting input to ground to act as a lowpass filter.

Have you tested this Op Amp to see how it responds near the ground rail? So-called "rail to rail" Op Amps often will only be good down to a few 10s of mV from ground, then not behave well.

Personally, I'd add a small negative supply voltage and some zero calibration.

That’s a non-inverting op amp configuration. Attached is a schematic of how it should be wired.
The resistor labeled "Sense " is grounded on both sides in your schematic. There can be no current flow that way.

What about these questions ?

1-Power source (what it it ?) for arduino at time of error.
2- your Vcc voltage (voltage on 5V pin of Arduino) at the time of the error.

NON-INVERTING OP AMP AMPLIFIER.jpg

polymorph:
It is good practice to add a 2.2k resistor in series between the current sense resistor and the non-inverting input of the Op Amp. In that way, you compensate for input bias current. You can also then add a capacitor from the noninverting input to ground to act as a lowpass filter.

Have you tested this Op Amp to see how it responds near the ground rail? So-called “rail to rail” Op Amps often will only be good down to a few 10s of mV from ground, then not behave well.

Personally, I’d add a small negative supply voltage and some zero calibration.

I’ll give that a try. I haven’t tested the Opamp near ground rail, thats something I should probably do as soon as possible.

Code look alright?

raschemmel:
That’s a non-inverting op amp configuration. Attached is a schematic of how it should be wired.
The resistor labeled "Sense " is grounded on both sides in your schematic. There can be no current flow that way.

What about these questions ?

1-Power source (what it it ?) for arduino at time of error.
2- your Vcc voltage (voltage on 5V pin of Arduino) at the time of the error.

I am powering with either a 12v regulated power supply 3A max, or my bench variable power supply.
VCC during time of error is 5v steady according to my multimeter.

My device i am testing draws ~400ma @ 3.7v during ON period.

The schematic has been revised in the previous comments, sorry for the errors in the original.

REVISED SCHEMATIC ATTACHED: