Lesson 2: Analog input

On the UNO R3, analogRead() returns a number from 0 to 10231. In one sophomore mechanical-⁠engineering course, the most common answer for the largest reading was 2554. That’s the top of analogWrite()'s range, not analogRead()'s6.

What you need

  • Arduino UNO R3
  • USB cable
  • A potentiometer (knob)
  • Three jumper wires

Wire it, then check it

Attach the knob’s middle pin to A0 and its outer pins to 5V and GND5.

Before you run it on a real board, check each connection

Not working on a real board? Start with the wiring checklist.

Arduino version

l2-read-arduino.ino
// Lesson 2, Arduino version: read the knob on A0 and
// print the reading.
void setup() {
  Serial.begin(115200);
}

void loop() {
  int reading = analogRead(A0);  // 0 to 1023 on the UNO R3
  Serial.println(reading);
  delay(20);
}

analogRead(A0) starts a conversion on A0 and waits until it finishes3.

Register version

l2-read-registers.ino
// Lesson 2, register version: the same reading, done with
// the ADC registers.
void setup() {
  Serial.begin(115200);
  // Reference AVCC, input ADC0 (A0), result right-adjusted
  ADMUX = (1 << REFS0);
  // Turn the ADC on, with its clock at 16 MHz / 128
  ADCSRA = (1 << ADEN)
         | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}

void loop() {
  ADCSRA |= (1 << ADSC);           // start one conversion
  while (ADCSRA & (1 << ADSC)) {}  // ADSC stays 1 until done
  uint8_t low = ADCL;              // read ADCL first
  uint8_t high = ADCH;
  int reading = (high << 8) | low;
  Serial.println(reading);
  delay(20);
}

In ADMUX, REFS1:0 = 01 selects AVCC as the reference, and MUX3:0 = 0000 selects input ADC0. In ADCSRA, ADEN turns the ADC on, ADPS2:0 = 111 divides its clock by 128, and writing 1 to ADSC starts a conversion. ADSC reads as 1 until the conversion finishes2. The result is ADC = VIN × 1024 / VREF. Read ADCL first, then ADCH2.

analogRead() result against the voltage on A0A straight line from 0 at 0 V to 1023 at 5 V. The lab reads 0 at 0 V, 256 at 1.25 V, 512 at 2.5 V, 768 at 3.75 V, 1023 at 5 V. 1023 is ten bits all set to 1: 11 in ADCH and 11111111 in ADCL.analogRead()025651276810230 V1.252.53.755 VVIN on A0ADC = VIN × 1024 / VREF2565127681023, the topADCHADCL1023 = ten 1s19181716151413121110analogRead() result against the voltage on A0A straight line from 0 at 0 V to 1023 at 5 V. The lab reads 0 at 0 V, 256 at 1.25 V, 512 at 2.5 V, 768 at 3.75 V, 1023 at 5 V. 1023 is ten bits all set to 1: 11 in ADCH and 11111111 in ADCL.analogRead()025651276810230 V1.252.53.755 VVIN on A02565127681023, the topADCHADCL19181716151413121110
The conversion gives ADC = VIN × 1024 / VREF2, a 10-⁠bit number. Ten bits hold 0 to 10231, so at 5 V, where the formula says 1024, the lab reads 1023: every bit of ADCH and ADCL set to 1. The dots are the readings the lab gives at 0, 1.25, 2.5, 3.75 and 5 V.

Registers in this lesson (ATmega328P data-⁠space addresses)2

RegisterAddressBit 7Bit 6Bit 5Bit 4Bit 3Bit 2Bit 1Bit 0
ADMUX0x7CREFS1REFS0ADLAR–MUX3MUX2MUX1MUX0
ADCSRA0x7AADENADSCADATEADIFADIEADPS2ADPS1ADPS0
ADCH0x79––––––ADC9ADC8
ADCL0x78ADC7ADC6ADC5ADC4ADC3ADC2ADC1ADC0

Run it in the lab

Turn the knob and watch ADCH and ADCL change. At 2.5 V both programs print 5122.

Drill

  1. What is the largest number analogRead() returns on an UNO R3?

    Show the answer

    1023. The UNO R3’s ADC is 10-⁠bit. In one sophomore course, the most common answer was 255, which is the maximum for analogWrite. 1, 4, 6

  2. With the knob at 2.5 V, what does the sketch print?

    Show the answer

    512. ADC = VIN × 1024 / VREF = 2.5 × 1024 / 5. 2

  3. Why read ADCL before ADCH?

    Show the answer

    So both halves come from the same conversion. Arduino’s own analogRead reads ADCL first. 3

Sources

  1. Arduino reference: analogRead
  2. Microchip ATmega328P datasheet DS40002061A: §24.7 ADC conversion result (p256); Table 24-3 (p257); ADEN and ADSC (p258)
  3. ArduinoCore-⁠avr, cores/arduino/wiring_analog.c
  4. Bedillion & Muci-Küchler, ASEE 2018: SDSM&T ME-265, 25 students
  5. Arduino example: AnalogReadSerial: potentiometer wiring
  6. Arduino reference: analogWrite: values 0 to 255

Next: Lesson 3