Problem reading analog input voltage on DUE

Hello, I've been trying to implement this circuit:

What it does is: takes an input voltage of 0.55-2.75V, subtracts 0.55 and multiplies it by 1.5 so that on PIN 1 of LM358N I can get 0-3.3V. It works well on the simulation software.

I tried to build the circuit and it works. I have 0-3.3V as an output voltage. The thing is: I want to connect this voltage to an Arduino Due so that I can get a 0-4095 proportional digital range to the original 0.55-2.75 voltage range. The problem is that the digital reading on the Arduino Due is not right. For exemple: if I apply 1.65V to it (via opamp circuit output), I read 2500 or something close to this number, but i was expecting to read something close to 2047 since 1.65V is half of the input voltage on this Due. This problem happens for the whole scale, but it is not a fixed offset, it varies.

One thing that I noticed it that I if I disconnect the ground pin from the Arduino Due it still reads the same range with the same problem. That makes me believe it is some type of ground connection error. I tried connecting a capacitor, a resistor, both between the opamp output and its ground, but there were no better results.

I

When you put the A:D pin to ground what does the readout indicate?

It reads 0-2

http://www.djerickson.com/arduino/due_adc.html
The ADC peripheral needs some calibration to improve accuracy:

Some general rules to improve ADC conversions:

  • Power the DUE with a powerbank since power thru the USB cable from a PC is unstable,
  • Pay attention to wiring,
  • Put a signal conditioning circuit on the analog input pin,
  • Oversample and average ADC conversions,
  • Write your code with PDC DMA (example sketches are provide in the DUE sub forum ADC with direct register programming).

0-2, a low or a bit of noise. So the A:D can read a zero. If you put the AD pin to 3.3V it reads near 4096? If the switching the of pin from 0V to 3.3V the ADC reads the changes? Then the issue is not with the A:D.

Firstly, The LM358 is NOT a "rail-rail " op amp and while it will (just) run from a 5V single supply it wont work properly if the inputs are near 0V and it certainly wont give you an output of 0V.

Can you please post the code you are using to read and show the analog reading?

Have a look at my site, especially re voltage references and how to take analog readings.

For a perfect ADC, you would get 1.00 * 1023 / 5.00

It should be ...1.00 * 1024 / 5.00

I have an analysis here The Arduino ADC and how it measures an input voltage

The mistake originates I believe from Atmel and certainly is in their data sheets;

There is a tutorial to output a DAC full swing (0V - 3.3V) instead of 0.55V - 2.75V:

Thanks everyone for the help!! I reliazed the Due I was using as the voltage receptor was malfunctioning. I isolated it and tested with a potentiometer (on 3.3V pin) measuring the voltage across the potentiometer and compared it to the digital readout. Turns out the max voltage across the pot was 2.7V instead of 3.3V. And measuring the voltage at 3.3V pin I got 2.7V. Then I wired the OPAMP circuit again and I saw that when the OPAMP output voltage was >= 2.7V the digital readout was always 4095. So basically, this board is operating at 2.7V instead of 3.3V and this is affecting everything because the scaling OPAMP circuit was developed considering a normal 3.3V operating voltage.

Also, the internal DACs of this DUE were outputing a wrong voltage range. I tested it on USB and also on a external power supply. Same results. It seems like this board is not reliable.

I'll get another DUE and perform the tests again. But I appreciate every answer, I'll take a closer look at the links you guys posted.

Thanks for the help.

You may well find the problem with your due is because of a protection diode dropping the voltage.

When I used a Due for a project i set up the AD in the following way

void setup()
{
 analogReadResolution( 12 );
////
  ADC->ADC_MR |= 0x80;  //set free running mode on ADC
  REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000; // adc start up value
  // ADC->ADC_CHER = 0x80; //enable ADC on pin A0
}

Those settings worked quite well.