This is an old revision of the document!
The analogue inputs and outputs are used when the signal can take a range of values, unlike the digital signal that takes only two values (HIGH or LOW).
For measuring the analogue signal, microcontrollers have built-in analogue-to-digital converter (ADC) that returns the digital value of the voltage level. Usually, the binary number corresponds to the input voltage, not the value in Volts. The number of bits of the output value depends on the accuracy and internal construction of the converter and usually varies between 8 and 12.
analogRead()
The function analogRead() is used for analogue pins (A0, A1, A2, etc.) and reads the value on the analogue pin.
The syntax of a function is the following:
analogRead(pin);
The parameter pin is the name of the pin whose value is read.
The return type of the function is the integer value. On the Arduino Uno boards, it ranges between 0 and 1023. The reading of each analogue input takes around 100 ms.
Some microcontrollers use specific setups. Analogue input may work out of the box. Still, low-level control usually brings better results and higher flexibility (i.e. instead of changing the input voltage to reflect the full measurement range, you can regulate internal amplification and sensitivity. Please note implementation varies even between ESP32 chips family and not all chips provide all of the functions so it is essential to refer to the technical documentation.
ESP32 has 15 channels exposed (18 total) of the up to 12-bit resolution ADCs. Reading the raw data (12-bit resolution is the default, 8 samples per measure as default) using the analogRead()
function is easy.
Technically, under the hood on the hardware level, there are two ADCs (ADC1 and ADC2). ADC 1 uses GPIOs 32 through 39. ADC2 GPIOs 0,2,4, 12-15 and 25-27. Note that ADC2 is used for WiFi, so you cannot use it when WiFi communication is enabled.
Just execute analogRead(GPIO)
.
A number of useful functions are here (not limited to):
analogReadResolution(res)
- where res
is a value between 9 and 12 (default 12). For 9-bit resolution, you get 0..511 values; for 12-bit resolution, it is 0..4095 respectively. analogSetCycles(ccl)
- where ccl
is number of cycles per ADC sample. The default is 8, the valid number is between 1 and 255.analogSetClockDiv(divider)
- sets base clock divider for the ADC. That has an impact on the speed of conversion.analogSetAttenuation(a)
and analogSetPinAttenuation(GPIO, a)
- sets input attenuation (for all channels or for selected channels). The default is ADC_11db
. This parameter reflects the dynamic scaling of the input value:ADC_0db
- no attenuation (1V on input = 1088 reading on ADC), so full scale is 0..1.1V,ADC_2_5db
- 1.34 (1V on input = 2086 reading on ADC), so full scale is 0..1.5V,ADC_6db
- 1.5 (1V on input = 2975 reading on ADC), so full scale is 0..2.2V,ADC_11db
- 3.6 (1V on input = 3959 reading on ADC), so full scale is 0..3.9V.analogRead()
. As technically all channels use the same two registers (ADC1 and ADC2), you need to give it some time to sample (i.e. delay(100)
between consecutive reads on different channels).
Unlike analogue input, the analogue output does not generate varying voltage directly on the pin. In general, it uses the technique known as (Pulse Width Modulation (PWM)) that generates a high/low square signal of stable frequency but varying duty cycle (ratio of active and passive periods of the signal). Details are described later in the book. Because the PMW signal can provide different average power to the external element, e.g. LED, it can be considered as analogue output.
analogWrite()
The function analogWrite() is used to write an analogue value of the integer type as an output of the pin. An example of use is turning on/off the LED with various brightness levels or setting different speeds of the motors. The value that is written to the pin stays unchanged until the next value is written to the pin.
The syntax of a function is the following:
analogWrite(pin, value);
The parameter pin is the number of the pin.
The parameter value is the PWM signal value that can differ from 0 (off) to 255 (100% on).
This function does not have the return type.
The following example shows reading an analogue value from the A0 input of an Arduino Uno board and writing the analogue value to the output that can control the intensity of the LED.
#define LED_pin 3 //the pin number is chosen to support PWM generation void setup() { pinMode(LED_pin, OUTPUT); } int value; //variable that holds the result of analogue reading void loop() { value = analogRead(A0); //analogRead on Arduino Uno returns the value in the range 0 - 1023 value = value >> 2; //it should be converted to the value of the range 0 - 255 analogWrite(LED_pin, value); //writing converted value to PWM output }
PWM frequently controls analogue-style, efficient voltage on the GPIO pin. Instead of using a resistance driver, PWM uses pulses to change the effective power delivered to the actuator. It applies to motors, LEDs, bulbs, heaters and indirectly to the servos (but that works another way).
The classical analogWrite
method, known from Arduino (Uno, Mega) and ESP8266, does not work here.
ESP32 has sixteen (0 to 15) PWM channels (controllers) that can be freely bound to any of the regular GPIOs.
ESP32 can use various “resolutions” of the PWM: from 8-bit (0..255) to 15-bit (0..32767), while regular Arduino uses only 8-bit one.
To use PWM in ESP32, one must perform the following steps:
OUTPUT
,