|ESP32 In MicroPython: Analog Input|
|Written by Mike James & Harry Fairhead|
|Tuesday, 17 October 2023|
Page 1 of 3
Analog input is the way to interface many sensors. This extract is from Programming the ESP32 in MicroPython, part of the I Programmer Library and it shows you how to get accurate readings from the on board ADC.
Programming the ESP32in MicroPython
By Harry Fairhead & Mike James
Buy from Amazon.
The ESP32 has a wide range of analog capabilities. It has two A-to-D converters (ADCs) and two D-to-A converters (DACs) connected to specific GPIO pins. In addition, it has a set of capacitive input lines which can be used as touch sensors.
The ESP32 has two 12-bit onboard ADCs, ADC1 supports 8 channels and ADC2 supports 10 channels. The only problem is that the WiFi uses one of the two channels, ADC2, and hence its use is best avoided unless you turn WiFi off or use it only when the WiFi is inactive.
The GPIO lines that can be used by the ADC are fixed. ADC 1 can use GPIO32 to 39 and ADC 2 can use GPIO 0, 2, 4, 12-15 and 25-27. In practice not all of these lines can be used. Of the 8 ADC1 channels only 6 are available on development boards. So even though the hardware seems to offer 18 ADC inputs this is actually reduced to six that are easy to use:
GPIO 36 and 39 are also used to read the built-in Hall sensor, see later, and are also best avoided.
The ADC is a successive approximation converter. You don't need to know how it works to use it, but it isn't difficult to understand. The input voltage is compared to a standard voltage, VREF. First a voltage equal to VREF/2 is generated and the input voltage is compared to this. If it is lower then the most significant bit is a 0 and if it is equal or greater then the most significant bit is a 1. At the next step the voltage generated is VREF/2+VREF/4 and the comparison is repeated to generate the next bit. Successive approximation converters are easy to build, but they are slow.
The ESP32 ADC uses a reference voltage that is generated on-chip and varies between 1000mV and 1200mV. Since 2018 ESP32 chips have the reference voltage burned into the eFuse memory and this makes calibration a matter of reading the value and using it to correct the result. The easiest way to discover if the device you are using has calibration data is to use espefuse.py which is installed along with esptool.py and can be used to read and write the eFuse memory. This is a non-volatile write-once memory that you can use to record small amounts of configuration data, but it is better to avoid using it with MicroPython as there is no easy-to-use interface. It can also damage the ESP32 if you change the wrong bits as once set to 1 a bit cannot be changed back to 0. To discover the calibration data use:
python espefuse -p COM6 adc_info
replacing COM6 with the serial port that the ESP32 is connected to. If no calibration data is available you will see:
ADC VRef calibration: None (1100mV nominal)
and the best you can do is assume the middle value for the reference voltage. If there is calibration data you will see a single point calibration:
ADC VRef calibration: 1149mV
and you might also see a two-point calibration for each channel:
ADC readings stored in efuse BLK3: ADC1 Low reading (150mV): 306 ADC1 High reading (850mV): 3153 ADC2 Low reading (150mV): 389 ADC2 High reading (850mV): 3206
If you want to automate the correction you can read the eFuse memory directly from MicroPython:
from machine import mem32 def getVCal(): VC=(mem32[0x3FF5_A010]>>8)& 0x1F if(VC & 0x10 ): VC=-(VC & 0x0F) return 1100+VC*7 print(getVCal())
The calibration value is stored as a 5-bit sign-magnitude value in increments of seven and as an offset from 1100 – the middle of the range. The calibration is used by MicroPython to get a more accurate result.
|Last Updated ( Tuesday, 17 October 2023 )|