Arduino Due: Minimum reading of "20" on analog inputs on some PCBs

Hello,

I could use some advice troubleshooting an issue where the minimum readings of the ADCs on the Arduino Due are greater than 0. In other words, using this code:

analogReadResolution(12);
value = analogRead(0);

For example - the value is always between 20 and 4095. Here’s a bit more background about the issue. I just received 200 circuit boards back from the PCB company. 38 of those PCBs have issues with the ADCs not reaching “0”. But even those 38 vary in their low-end readings. 20 is the worst case. Here’s a table that shows test readings:

PCB2#	An0 Min	An1 Min	An2 Min	An3 Min	An4 Min	An5 Min	Average
16	0	0	0	0	1	0	0.17
17	0	0	0	0	1	0	0.17
20	0	0	0	1	0	0	0.17
22	0	0	0	0	1	0	0.17
34	0	0	0	1	1	0	0.33
10	0	0	1	0	2	0	0.50
19	0	0	0	2	1	1	0.67
28	1	0	1	1	0	1	0.67
23	1	1	0	0	2	1	0.83
13	1	0	1	1	1	2	1.00
24	1	0	1	1	2	1	1.00
25	1	1	2	0	1	1	1.00
31	1	1	1	2	1	2	1.33
3	2	2	2	3	2	2	2.17
15	2	3	2	3	2	3	2.50
12	1	2	3	4	4	4	3.00
6	5	5	5	5	5	5	5.00
27	4	6	6	6	6	6	5.67
14	6	6	7	7	7	6	6.50
32	6	7	6	8	8	7	7.00
8	6	9	7	6	7	8	7.17
11	9	7	9	8	7	7	7.83
18	8	7	8	8	7	9	7.83
26	9	8	8	8	7	7	7.83
33	8	8	9	8	8	8	8.17
38	8	9	8	9	9	7	8.33
1	5	9	10	10	7	10	8.50
5	10	8	9	10	10	9	9.33
29	7	8	8	8	19	8	9.67
4	11	10	11	11	11	11	10.83
30	12	12	10	12	12	12	11.67
36	13	12	13	13	13	13	12.83
2	13	14	13	13	13	13	13.17
7	16	16	15	15	15	15	15.33
37	15	16	16	17	12	16	15.33
9	18	18	19	19	19	18	18.50
35	19	18	19	20	19	20	19.17
21	20	20	22	22	22	22	21.33

For the ADC inputs above with minimum values greater than ~4, connecting the ADC input pin directly to ground still will not yield a 0 ADC result. The only way to get a 0 value is to input a slightly negative voltage.

It’s worth pointing out that the inputs on any one PCB tend to have the same lower-bound for all of the analog inputs. To me, this doesn’t appear to be an issue with the code, since a code problem would normally affect all of the modules, not just 38 of them. If it were an obvious PCB design flaw, again I would expect it to affect all of the modules. Could the Arduino Dues have been damaged during soldering to the PCB? Or, maybe this is some issue with the reference voltage?

I’ve attached the schematic for the PCB board having trouble. Thanks for any advice you might have.

Here’s the test code:

int analog0 = 10;
int prevAnalog0 = 10;
int analog1 = 10;
int prevAnalog1 = 10;
int analog2 = 10;
int prevAnalog2 = 10;
int analog3 = 10;
int prevAnalog3 = 10;
int analog4 = 10;
int prevAnalog4 = 10;
int analog5 = 10;
int prevAnalog5 = 10;
int digital22 = -1;
int prevDigital22 = -1;
int dacVal = 0;

long previousStamp = 0;
unsigned long currentStamp = 0;

void setup()
{
  // Set the Due's analog read resolution to 12 bits.  It defaults to 10.
  analogReadResolution(12);
  
  analogWrite(DAC1,dacVal);
  previousStamp = millis(); 
  pinMode(22,INPUT);
  
  Serial.begin(9600);
  while (! Serial);
  Serial.println("Equation Composer I/O Test");
  Serial.println("");
  
}

void loop()
{
  currentStamp = millis();
  if (currentStamp - previousStamp > 2000)
  {
    previousStamp = currentStamp;
    if (dacVal == 0)
      dacVal = 255;
    else
      dacVal = 0;
    analogWrite(DAC1,dacVal);
  }
  
  analog0 = analogRead(0);
  analog1 = analogRead(1);
  analog2 = analogRead(2);
  analog3 = analogRead(3);
  analog4 = analogRead(4);
  analog5 = analogRead(5);
  digital22 = digitalRead(22);
  
//  if(analog0 != prevAnalog0)
  if (1)
  {
    prevAnalog0 = analog0;
    
    Serial.print("An 0: ");
    Serial.println(analog0);
  }
  
//  if(analog1 != prevAnalog1)
  if (1)
  {
    prevAnalog1 = analog1;
    
    Serial.print("           An 1: ");
    Serial.println(analog1);
  }
//  if(analog2 != prevAnalog2)
  if (1)
  {
    prevAnalog2 = analog2;
    
    Serial.print("                      An 2: ");
    Serial.println(analog2);
  }
  
//  if(analog3 != prevAnalog3)
  if (1)
  {
    prevAnalog3 = analog3;
    
    Serial.print("                                 An 3: ");
    Serial.println(analog3);
  }
  
//  if(analog4 != prevAnalog4)
  if (1)
  {
    prevAnalog4 = analog4;
    
    Serial.print("                                            An 4: ");
    Serial.println(analog4);
  }
//  if(analog5 != prevAnalog5)
  if (1)
  {
    prevAnalog5 = analog5;
    
    Serial.print("                                                       An 5: ");
    Serial.println(analog5);
  }
  if(digital22 != prevDigital22)
  {
    prevDigital22 = digital22;
    
    Serial.print("                                                                  Dig22: ");
    Serial.println(digital22);
  }
}

For the ADC inputs above with minimum values greater than ~4, connecting the ADC input pin directly to ground still will not yield a 0 ADC result. The only way to get a 0 value is to input a slightly negative voltage.

I assume you've confirmed a good ground connection? The input-ground connects to the chip-ground?

This is just a guess, but try adding a delay before each read.

Try a long delay (something like 100mS) and if it helps you can dig-into the data sheet or experiment to see how fast the ADC "settles".

Having experimented with the Due I'd say the DAC / ADC circuitry on that chip is an afterthought and performs poorly. The DAC seems to have sparkle codes for example.

clone45: I've attached the schematic for the PCB board having trouble.

Yet, the PCB file is probably what we need to see, not the schematic.

Ideally the actual PCB file, not just a picture. So we can take a good look at your ground planes.

Absolutely! Thanks so much for your help. I’ve attached all of the PCB files, including the Gerber files, Eagle files, and just about everything else I have. It’s an open-source project anyhow. John Staskevich did all of the circuit design / PCB design for this project. I’m the programmer and creator of the product. If you need any guidance while reviewing the PCB designs, I’ll see if John can help out.

Cheers,
Bret

pcb_files.zip (3.56 MB)

Hi, when you are taking these analog input readings and getting the results no lower than 20, have you got the relevant analog inputs grounded, so that they definitely have zero potential om them?

Tom....... :)

TomGeorge: Hi, when you are taking these analog input readings and getting the results no lower than 20, have you got the relevant analog inputs grounded, so that they definitely have zero potential om them?

Tom....... :)

Yes. I can short PCB ground (or the SAM3X analog ground pin. There is only one ground on the board.) directly to an ADC input pin and analogRead() will return a non-zero value.

What's interesting to me is that the Arduino Due board does not have this issue. Here are the clues so far:

  1. Only 38 boards (out of 200) has this issue. This seems to rule out a software problem or "settling" problem. Unless settling time varies from chip to chip and affects all ADC inputs the same.

  2. The Arduino Due development boards do not have this problem. This seems to rule out an inherent problem with the Due ADCs in general, whereas some Dues just never reads "0" from its ADCs. (No offense MarkT)

  3. It's the low-value of the ADCs which is variable, which suggests it isn't a problem with AREF. (No offense me. Ha ha ha.)

  4. It doesn't seem to be a grounding issue.

I feel like Vizzini from the Princess Bride. "...so I can clearly not choose the wine in front of me!" Inconceivable!

Any ideas would be much appreciated. It's a very difficult issue to have. I can't ship my product until I get to the bottom of it.

Cheers, Bret

Hi have you given the PCB and Controller a good clean with isopropal alcohol or some flux removal chemical. I can remember, Alzheimer kicks in, another post with problems from conducting through solder paste flux. The post was only posted three or so weeks ago.

Forum members younger than me, Get Zee Grey Cells Working, please.

Tom... :)

You might have to consider a ZIF socket and S.O.T. of the SAM chip, although that complicates manufacturing as you'd have to process waffle trays of them yourself.

You might want to investigate parts from other suppliers should there be bad batches around.

Have you correlated performance against date/batch codes on the chip?

TomGeorge: Hi have you given the PCB and Controller a good clean with isopropal alcohol or some flux removal chemical. I can remember, Alzheimer kicks in, another post with problems from conducting through solder paste flux. The post was only posted three or so weeks ago.

Hi Tom, thanks for the reply. Since we are using a TQFP package, I can directly short the GNDANA pin to the ADn pin on the chip. Same non-zero result. So this seems to rule out a soldering quality issue.

MarkT: You might have to consider a ZIF socket and S.O.T. of the SAM chip, although that complicates manufacturing as you'd have to process waffle trays of them yourself.

You might want to investigate parts from other suppliers should there be bad batches around.

Have you correlated performance against date/batch codes on the chip?

Mark, thank you for posting your thoughts.

I will have to catalog the batch codes and see what I find. This leads me to another question that I don't have the experience to answer:

Is this kind of variation in ADC performance (er, zero-read voltage offset?) typical for a given uC?

The spectrum-nature of the measurements leads me to believe that there is some variation in components causing the problem. The SAM3X itself seems to be the most obvious possibility. I'm also open to the idea that some supporting component or voltage level on the board is causing the problem. I'm just not sure where to look.

I have an update to this question.

As an experiment, we had the SAM3X chips swapped between two "good" units and two "bad" units.

Just as a reminder:

  • The "good" units were able to read a minimum of "0" on the analog inputs.
  • The "bad" units were not able to read a minimum of "0" on the analog inputs. Worst case, the minimum was "20" or so.

We swapped chips to determine whether it was the SAM3X or something specific about our PCB. We found that the Sam3X chips are the problem, not our PCB circuitry. In other words, when we moved the chips between the "good" and "bad" units, the problem was solved in the "bad" units, and conversely the "good" units inherited the problem. If our PCB boards were the problem, switching the SAM3X chips wouldn't have made a difference.

This seems to leave two possibilities:

  1. That the SAM3Xs were somehow damaged during soldering/assembly, which is why we can't get a "0" analog reading from them.

  2. That the SAM3Xs were part of a "bad batch". (Does this ever happen?!)

We're still uncertain which is to blame. Any suggestions? Are there tests that anyone can recommend to unearth more information?

Cheers, Bret

That the SAM3Xs were part of a "bad batch". (Does this ever happen?!)

I worked on some "Analog/Mixed Signal" chips at IBM, and it was considered very difficult from a semiconductor process perspective to have repeatable low leakage between analog and digital signals on the same chip.

But that was Long Ago. But device physics hasn't changed much.

Hmm... You seem to have proved that it is a chip problem. Process parameters certainly can and do vary with different wafer batches. A lot of effort goes into controlling and monitoring All That, but I bet it Can Happen. Also there is a push to decrease Test Time in production, so chips may not have really exhaustive analog testing done, because it involves settling times etc. There are groups of people whose job is called "Test Time Reduction", playing with statistics and stuff like Test Sequence Limited Yield.

Then guys like you get the chips that made it out the door.

I would definitely talk to the Application Engineers in charge of this chip at the manufacturer. They can talk to the process people and the test and characterization people who really know the chip design. They may want you to send some failing chips back to their lab.

This stuff ain't simple.

Hi everyone,

We got an official response from Atmel:

Please refer the Table 46-31 and 46-32 in Electrical Characteristics section in SAM3X datasheet. As per the SAM3X ADC characteristics, offset error is typically around +11.5LSB.

This is a typical value which might vary (within the limits) for different batches in production (due to process variations, etc). Hence, the +10LSB error seems to be within the operating specifications of the ADC.

It can be solved by a software calibration process to find the offset error at cold startup and then applying it in the final ADC output.

So, there it is! The solution is to use either software or hardware calibration.

Cheers, Bret

The solution is to use either software or hardware calibration.

Yes, that what I thought, but I couldn't find any reference in the data sheet how to invoke a recalibration of the ADC. Anyone knows? For example, on Maple (STM32 cortex-3 , practically same uCPU as ARM SAM3X), you can run:

adc_enable(ADC1);
    adc_calibrate(ADC1);

I have personal experience of this, because the SAM3X chip is also used in the Duet controller board for the Ormerod 3D printer, which I contribute towards firmware for. The SAM3X chip unfortunately has horrendous ADC gain and offset error tolerances. These errors can be up to about 64LSB in 12-bit mode according to the datasheet, far worse than the atmega series processors used on other Arduinos.

To calibrate the ADC you need to have 2 known voltages available. One should be close to but slightly above ground, the other should be close to but slightly below the analog reference. You can provide these voltages using a 3-resistor voltage divider. It’s no use calibrating at ground and at Vref, because the linear range of some of these chips doesn’t quite extend that far.

Here a quote from STM32F103 data sheet:

Calibration The ADC has an built-in self calibration mode. Calibration significantly reduces accuracy errors due to internal capacitor bank variations. During calibration, an error-correction code (digital word) is calculated for each capacitor, and during all subsequent conversions, the error contribution of each capacitor is removed using this code. Analog-to-digital converter (ADC) Calibration is started by setting the CAL bit in the ADC_CR2 register. Once calibration is over, the CAL bit is reset by hardware and normal conversion can be performed. It is recommended to calibrate the ADC once at power-on. The calibration codes are stored in the ADC_DR as soon as the calibration phase ends. Note: 1 It is recommended to perform a calibration after each power-up. 2 Before starting a calibration the ADC must have been in power-off state (ADON bit = ‘0’) for at least two ADC clock cycles.

Looks like Atmel has not implemented this nice feature in its uCPU. So, external circuitry, if its just 3 resistors would be necessary, and than some code to measure at start-up time and subtract this offset later on. Things may get complicated when gain and differential mode in use.