AnalogRead/ADC accuracy

I have an MKR VIDOR4000 board, on this board I am trying some easy stuff since this is my first Arduino and it has been a long time since I did something with electronics.
I choose this board for the FPGA because I have worked with Xilinx devices in the past and I wanted to refresh my knowledge.

I had an LM35 laying around so I thought that would be cool to test the analog inputs with.

I connected the +Vs from the LM35 to the 5V pin on the Arduino, the GND to the GND and the Vout to the A1 pin. And I loaded the following code to the Arduino:

const int LED = 2;      // the PWM pin the LED is attached to
const int TMP = A1;     // the analog pin the LM35 is connected to.
const float AREF = 3.3; // The reference voltage for the ADC

void setup() {
  Serial.begin(9600);
  
  analogReference(AR_DEFAULT);
  
  pinMode(TMP, INPUT);
  pinMode(LED, OUTPUT);
}

void loop() {
  int analogValue = analogRead(TMP);

  float analogVoltage = analogValue / 1024.0  * AREF;
  
  float cel = analogVoltage / 0.01;
  float farh = ( cel*9 ) / 5 + 32;

  Serial.print("Raw: ");
  Serial.print(analogValue);
  Serial.print("; U: ");
  Serial.print(analogVoltage);
  Serial.print("; Temp: ");
  Serial.print(cel);
  Serial.print("*C, ");
  Serial.print(farh);
  Serial.println("*F");

  int brightness = (int)( cel * 2.55 );
  if (brightness <= 0) {
    brightness = 0;
  }
  if (brightness >= 255) {
    brightness = 255;
  }
  analogWrite(LED, brightness);
  
  delay(500);
}

This is the output I get when opening a Serial Terminal:

Raw: 383; U: 0.31; Temp: 30.86*C, 87.54*F
Raw: 386; U: 0.31; Temp: 31.10*C, 87.98*F
Raw: 382; U: 0.31; Temp: 30.78*C, 87.40*F
Raw: 388; U: 0.31; Temp: 31.26*C, 88.27*F
Raw: 390; U: 0.31; Temp: 31.42*C, 88.56*F
Raw: 390; U: 0.31; Temp: 31.42*C, 88.56*F
Raw: 382; U: 0.31; Temp: 30.78*C, 87.40*F
Raw: 382; U: 0.31; Temp: 30.78*C, 87.40*F
Raw: 381; U: 0.31; Temp: 30.70*C, 87.25*F
Raw: 375; U: 0.30; Temp: 30.21*C, 86.38*F
Raw: 378; U: 0.30; Temp: 30.45*C, 86.82*F
Raw: 383; U: 0.31; Temp: 30.86*C, 87.54*F
Raw: 385; U: 0.31; Temp: 31.02*C, 87.83*F
Raw: 381; U: 0.31; Temp: 30.70*C, 87.25*F
Raw: 385; U: 0.31; Temp: 31.02*C, 87.83*F
Raw: 378; U: 0.30; Temp: 30.45*C, 86.82*F
Raw: 392; U: 0.32; Temp: 31.58*C, 88.85*F
Raw: 387; U: 0.31; Temp: 31.18*C, 88.12*F
Raw: 404; U: 0.33; Temp: 32.55*C, 90.59*F
Raw: 381; U: 0.31; Temp: 30.70*C, 87.25*F
Raw: 379; U: 0.31; Temp: 30.53*C, 86.96*F
Raw: 381; U: 0.31; Temp: 30.70*C, 87.25*F
Raw: 384; U: 0.31; Temp: 30.94*C, 87.69*F
Raw: 387; U: 0.31; Temp: 31.18*C, 88.12*F
Raw: 374; U: 0.30; Temp: 30.13*C, 86.24*F
Raw: 384; U: 0.31; Temp: 30.94*C, 87.69*F
Raw: 384; U: 0.31; Temp: 30.94*C, 87.69*F
Raw: 404; U: 0.33; Temp: 32.55*C, 90.59*F
Raw: 392; U: 0.32; Temp: 31.58*C, 88.85*F
Raw: 383; U: 0.31; Temp: 30.86*C, 87.54*F
Raw: 373; U: 0.30; Temp: 30.05*C, 86.09*F
Raw: 390; U: 0.31; Temp: 31.42*C, 88.56*F
Raw: 384; U: 0.31; Temp: 30.94*C, 87.69*F
Raw: 386; U: 0.31; Temp: 31.10*C, 87.98*F
Raw: 384; U: 0.31; Temp: 30.94*C, 87.69*F
Raw: 386; U: 0.31; Temp: 31.10*C, 87.98*F
Raw: 383; U: 0.31; Temp: 30.86*C, 87.54*F
Raw: 407; U: 0.33; Temp: 32.79*C, 91.02*F
Raw: 392; U: 0.32; Temp: 31.58*C, 88.85*F
Raw: 365; U: 0.29; Temp: 29.41*C, 84.93*F

The temperature is around 27 degrees and when I put a multimeter on the LM35, I get a voltage of 0.292/0.293V. The voltage on the LM35 is rather stable around those voltages, however the reading from the ADC has a range of 27.88 to 33.52 degrees.

I tried putting a resistor of 10k between the Vout and the A1 pin, and also a small keramic capacitor (222uF) between the Vout to the GND pin. I don’t have a smaller capacitor laying around. Also it’s an older capacitor.

I see this on all analog ports I tried (I tried a few, not all). So I was wondering if this is as expected?

const float AREF = 3.3;

Is the 3.3V supply actually 3.3V? If the reference voltage changes it will affect the ADC readings.

The reference voltage is the default internal reference and is according to the documents with this board 3.3V. On the Vcc pin I measure 3.29-3.30V with my multimeter, I would expect that this voltage is also used as the internal reference. So it is reasonably accurate and stable (without checking with an oscilloscope because I don’t have one).

I did read somewhere that some boards suffer from unstable 3.3V when powered by the USB, maybe this is the case since I do use the USB to power the Arduino. I don’t know if this can explain the range the ADC is converting from a reasonable stable input voltage. Although the input is offcourse very small compared to the reference voltage (0.29V compared to the 3.3V reference).

I thought the internal reference of an Arduino UNO was 1.1V.

analogReference()

Calibrate the ADC by measuring an accurately known voltage, or set of known voltages. Calibration tutorial here.

adwsystems:
I thought the internal reference of an Arduino UNO was 1.1V.

analogReference()

No, not the INTERNAL, I said “default internal reference”, I meant “default analog reference” which is also a internal reference I presume, but I used AR_DEFAULT as type. However the MKR VIDOR4000 uses a Microchip ATSAMD21 controller (Cool it says ATMEL on a Microchip controller, I will never get used to that … ) so I guess that this board falls under the same category as the Zero etc. which has a default analog reference of 3.3V. At least that is how I understand the documentation, maybe I’m wrong?

jremington:
Calibrate the ADC by measuring an accurately known voltage, or set of known voltages. Calibration tutorial here.

I will look into calibrating the ADC, thanks. I will post the results!

Don't know if that board has a lower internal Aref. If not, then you shouldn't use an analogue temp sensor, Because noise on the MCU supply will make your temp readout instable.

Move to a digital temp sensor, like the DS18B20. Leo..