Arduino Mega ADC non lineer problem

Hi. I use the arduino mega. I am measuring AC Voltage. My electronic component AD536A true rms to dc convertor. Adc input voltage 0-4.098V and very stabil.
Arduino Aref pin connect MCP1541 IC and 4.098 supply very stabil.

I meausring 17.5V arduino measure=17.5V
I meausring 32.1V arduino measure=32.8V
I meausring 48.1V arduino measure=49.9V (non lineer :S)
I meausring 70.7V arduino measure=74.2V

Can you help me??

My code:

/*
 * SmoothADCExample.ino
 *
 * This example defines A0 & A1 (analog inputs) to be handled by SmoothADC library
 *
 *
 * Samples every 50ms for A0
 * Samples every 500us for A1
 *
 * Every second, the average value from A0 & A1 are sent to serial port
 */
#include <SimpleModbusSlave.h>
#include <SmoothADC.h>

SmoothADC		ADC_0;				// SmoothADC instance for Pin 0
SmoothADC		ADC_1;				// SmoothADC instance for Pin 1
unsigned int	ADC0Value = 0;		// ADC0 final value
unsigned int	ADC1Value = 0;		// ADC1 final value

unsigned int	MemTimeSerial;

float Vout = 0.00;
float Vin = 0.00;

enum 
{     
  // just add or remove registers and your good to go...
  // The first register starts at address 0
  ADC0,     
  ADC1,        
  ADC2,
  ADC3,
  ADC4,
  ADC5,  
  LED_STATE,
  BUTTON_STATE,
  TOTAL_ERRORS,
  // leave this one
  HOLDING_REGS_SIZE 
  // total number of registers for function 3 and 16 share the same register array
};

unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array
////////////////////////////////////////////////////////////



void setup()
{
  
 modbus_configure(9600, 1, 2, HOLDING_REGS_SIZE, 0);
	//Serial.begin(9600);
analogReference(EXTERNAL);
	ADC_1.init(A1, TB_MS, 100);	// Init ADC0 attached to A0 with a 50ms acquisition period
	if (ADC_1.isDisabled())	{ ADC_1.enable(); }
	
}

void loop()
{
	unsigned int	tempTime = millis();
		
	ADC_1.serviceADCPin();
	delay(10);
	  ADC_1.serviceADCPin();
  delay(10);
     
	if ((tempTime - MemTimeSerial) > 100)
	{
		MemTimeSerial = tempTime;
		
		#ifdef DEBUG
		ADC_1.dbgInfo();
		#endif
		
	ADC0Value = ADC_1.getADCVal();
		
	Vout = (ADC0Value* 4.098) / 1023.00;
  Vin = Vout *1065.510838;
		//Serial.println(Vin,1);

  holdingRegs[TOTAL_ERRORS] = modbus_update(holdingRegs);
  holdingRegs[ADC1]=Vin;
  holdingRegs[ADC0]=ADC0Value;
	}
}

secretagent:
I meausring 17.5V arduino measure=17.5V
I meausring 32.1V arduino measure=32.8V
I meausring 48.1V arduino measure=49.9V (non lineer :S)
I meausring 70.7V arduino measure=74.2V

Rather than giving data like that post the actual voltage on the ADC pin and the corresponding value returned by analogRead()

...R

Right. Measure the input to the AD536A using a true RMS DMM. Measure the DC output of the AD536A with a DMM. Record the corresponding analogRead() from the Arduino. Post your results in tabular and graphical form.

How were you hand measurements taken?

This could also be a difference in how the meters work or the calibration of the two instruments.

I see where Robin2 is going. How do you know the Arduino ADC is causing the non-linearity? It could be AD536A interface. I would request four data points per line.

Hand measurement at the input
Voltage at the ADC pin
Count reading from the ADC pin
Converted value in the Arduino

For the 4th line:
70.7
?
?
74.2

Ad536A output pin lineer; example;
input voltage : 20V Ad536 output: 0.200V ADC=39
input voltage : 40V Ad536 output: 0.400V ADC=81
input voltage : 60V Ad536 output: 0.600V ADC=123
input voltage : 80V Ad536 output: 0.801V ADC=165-166

YOu can see ADC nonlinearty....

Robin2:
Rather than giving data like that post the actual voltage on the ADC pin and the corresponding value returned by analogRead()

...R

Ad536A output pin lineer; example;
input voltage : 20V Ad536 output: 0.200V ADC=39
input voltage : 40V Ad536 output: 0.400V ADC=81
input voltage : 60V Ad536 output: 0.600V ADC=123
input voltage : 80V Ad536 output: 0.801V ADC=165-166

The ADC conversion code is

Vout = (ADC0Value* 4.098) / 1023.00;
  Vin = Vout *1065.510838;

Correct?

Vout =165*4.098/1023 = 0.6609677
Vin = 0.6609677 *1065.510838 = 704.268292.

I don’t see a 10x factor in the code, but perhaps there is one somewhere. Given there is then the program would output 70.4V for the 80V input is substantially different than the OP. Not to mention inverted. The OP shows the DMM reading lower than ADC, this is the reverse.

What is the accuracy of the meter you are using? Is the accuracy of the meter reading the AC side match
that of the DC side given that you have switched settings and there is 2 orders of magnitude difference in the measurements being taken. I cannot tell if the error is in the ADC, in the meter being used, or in the interface circuit.

Those reading are awfully detailed, given the ADC steps are 4.9mV each. Other than the reading at 200mV input, they are 42 counts per 200mV (the first step is by 9.8-14.7mV or less than 3 bits). What accuracy and resolution are you expecting?

secretagent:
Ad536A output pin lineer; example;
input voltage : 20V Ad536 output: 0.200V ADC=39
input voltage : 40V Ad536 output: 0.400V ADC=81
input voltage : 60V Ad536 output: 0.600V ADC=123
input voltage : 80V Ad536 output: 0.801V ADC=165-166

The ADC calculation 1023 / 5 * V gives the values almost exactly as you have shown above. What is non-linear?

...R

Looks like the Arduino AREF is about 4.95V, how is the MCP1541 connected?

I am sure there are no problems with my friends connections, but even though the value I'm reading is stable, it is not linear, so even if I do a calculation I get an error.

For example: 0.200mV ADC input ADC Read:39

0.800mV ADC input ADC Read: 39*4= 156 but adc read 166 :S

secretagent:
I am sure there are no problems with my friends connections, but even though the value I'm reading is stable, it is not linear, so even if I do a calculation I get an error.

For example: 0.200mV ADC input ADC Read:39

0.800mV ADC input ADC Read: 39*4= 156 but adc read 166 :S

That is not the correct way to check the behaviour. You are assuming that 39 is perfect. But maybe it is marginal and might have been 38 or 40.

You need to do the calculation I showed in Reply #7. And you also need to know what the reference voltage actually is. I just assumed 5v, but maybe it is 4.95 as suggested in Reply #8

...R

Robin2:
That is not the correct way to check the behaviour. You are assuming that 39 is perfect. But maybe it is marginal and might have been 38 or 40.

You need to do the calculation I showed in Reply #7. And you also need to know what the reference voltage actually is. I just assumed 5v, but maybe it is 4.95 as suggested in Reply #8

…R

Robin

If you read the first post the OP states they are using a MCP1541 precision voltage reference source connected to AREF and in the setup() function they use the line

analogReference(EXTERNAL);

So the internal ADC is referenced to 4.096V.

Ian

IanCrowe:
So the internal ADC is referenced to 4.096V.

In that case the calculation I suggested in Reply #7 should be adjusted to

1023 / 4.096 * V which gives values of 50, 100, 150 and 200.

Those values are linear but do not match the output the OP reported which leads me to believe the ADC is not using the Aref voltage.

...R