After reading this tutorial, you will understand the basic of Arduino analog pins: What they are, how to use them as input or output, how to analogRead, and how to analogWrite. Also, we present the concept of Pulse-width modulation (PWM).

What is Analog ?

Analog signals are the signals in our “analog” world. The temperature, for instance, can be expressed in
an infinite set of values: e.g. 25°C, 25.1°C, 25.12°C, 25.123°C, 0°C, -4°C, -4.7°C, etc.

Analog temperature sensors provide analog voltage as an output signal, which corresponds to the measured temperature. Let’s consider the temperature sensor LM35. It measures the surrounding temperature with a linear scale of 10 mV/°C.

The 5V Arduino Boards reads and processes analog signals in a voltage range from 0 to 5 volts. The microcontroller of the Arduino board has an internal Analog-to-digital converter (ADC) for processing the analog input signals. The Arduino Uno, for instance, has six analog channels, in which six analog voltages (i.e. sensors) can be processed in parallel. The ports available for this purpose are labeled A0 to A5 on the Arduino Uno.

The resolution of its ADC is 10 bits. The 10-bit resolution corresponds to 210 = 1024 values. With a reference voltage of 5 volts, input signals from 0 to 5 volts can be read in, which are digitized by the ADC into values from 0 to 1023. This results in an accuracy of 5 V / 1024 = 4.9 mV

This 5V reference voltage is generated from the supply voltage and can be changed with the analogReference command. However, this command is not covered in this article.

Arduino analogRead

The Arduino analog read is done using analogRead() function by passing the analog pin as the function parameter. In the following instructions, the analog port A0 is read in and the resulting raw ADC value is then stored in the variable rawADC.

unsigned int rawADC = 0;
rawADC = analogRead(A0);

Now, let’s write the first analog sketch. The following circuit diagram depicts a potentiometer (variable resistor) connected to the Arduino analog pin A0.

Potentiometer circuit diagram

In the following sketch, the analog port A0 is read in and the resulting raw ADC value is then stored in the variable rawADC. Consequently, the program prints out the rawADC value on the serial monitor. Now, by rotating the potentiometer from fully clockwise to fully counter-clockwise, you will see that the ADC value alters between 0 and 1023, which corresponds to 0 V to 5V, respectively.

unsigned int rawADC = 0;    // variable for analog value

void setup() {
    Serial.begin(9600); //Init serial @ 9600 baudrate
}

void loop() {
  // read the analog raw value:
  rawADC = analogRead(A0);

  // print to the Serial Monitor
  Serial.print("Potentiometer value = ");
  Serial.println(rawADC);

  delay(1000);        // Wait 1000 ms
}

LM35 Arduino

The LM35 temperature sensor measures the temperature with a linear scale of 10 mV/°C. This means that each one degree Celsius is 10 mV. Thus, the equation to convert between raw ADC to degree Celsius is

Temperature [°C] = (rawADC/1024) * 5 * 100

The figure below shows the LM35 pinout for the TO-92 package from the LM35 datasheet. Simply connect pin 1 to 5V, pin 3 to GND, and pin 2 to an analog port.

LM35 pin diagram. Source: Texas Instruments

The following circuit diagram depicts an LM35 sensor connected to the Arduino analog pin A0.

LM35 interfacing with Arduino

In the following sketch, the temperature sensor LM35 is connected to the Arduino analog pin A0. The resulting raw ADC value is then stored in the variable rawADC. The temperature is then calculated according to the equation mentioned above and finally printed on the serial monitor.

// Define senor pin and variable for temperature
#define TEMP_SENSR_PIN  A0
double temp, rawADC;

void setup()
{
    Serial.begin(9600); //Init serial @ 9600 baudrate
}

void loop()
{
    // Read analog raw value
    rawADC = analogRead(TEMP_SENSR_PIN);
    // convert to degree celsius
    temp = (rawADC/1024.0) * 5.0 * 100.0;
    // Print temperature in °C
    Serial.print(temp);
    Serial.println("°C ");

    delay(1000);        // Wait 1000 ms
}

Arduino analogWrite

The Arduino outputs analog signals by means of pulse width modulation (PWM). With this technique, an analog signal can be generated by generating a digital signal, alternating between HIGH and LOW, with variable pulse time.

Due to the variable times of the HIGH phase (pulse time), an analog voltage between 0 to 100% (0V to 5V) can be generated. Think of it as the resulting average voltage. The PWM register is 8 bits, i.e. values from 0 to 255 (28 -1), which corresponds to an analog voltage between 0 to 5V.  The Arduino Uno default PWM frequency is 490 Hz, which corresponds to a period T = 1/frequency, which equals around 2 ms. So within this period, we control the percentage of output high to the complete period. This percentage is called the duty cycle.

PWM signal. Source: wikipedia.org

The PWM is usually used to control motors, servos, or the brightness of an LED, etc. The Arduino Uno PWM pins are 3, 5, 6, 9, 10, and 11. They are the same for Arduino Nano and Mini.

The output of an analog voltage by means of PWM is done with the function:

 analogWrite(Pin, Value)

The parameter Pin defines the PWM pin and Value defines duty cycle in an integer value between 0 and 255 (corresponds to 0% to 100%) as function parameters. For instance, Value = 128 represents a 50% duty cycle and 2.5 V.

Arduino map

Consider the following circuit diagram, a potentiometer (poti) is connected to the Arduino analog pin A0 and an LED connected to port 9.

Arduino LED and Poti circuit diagram

The sketch below is written to read the analog voltage from the poti, map the analog range (0 to 1023) to the PWM range (0 to 255) using the Arduino map() function and finally output PWM to dim the LED. As a result, the LED changes its brightness as you rotate the poti.

// Port for PWM and variable for the PWM value
#define PWM_PIN 9
#define TEMP_SENSR_PIN  A0

unsigned int valuePWM, rawADC = 0;

void setup()
{
    // Set port 9 as PWM output
    pinMode(PWM_PIN, OUTPUT);
}

void loop()
{
    // Read analog raw value
    rawADC = analogRead(TEMP_SENSR_PIN);
    // Map analog raw range to PWM range
    valuePWM = map(rawADC, 0, 1023, 0, 255);
    // Set PWM to the pin
    analogWrite(PWM_PIN, valuePWM);
}

Arduino PWM to analog

As mentioned already, the PWM is not an actual analog signal. Rather, the resulting average voltage seems to be analog. Fortunately, combining the output PWM signal with a low-pass filter creates an analog signal as shown in the following circuit diagram. This circuit consists of an RC circuit and a buffer.

PWM to analog converter